1 /*
2 * Copyright (c) 2018 - 2023, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <nrfx.h>
35
36 #if NRFX_CHECK(NRFX_NFCT_ENABLED)
37
38 #include <nrfx_nfct.h>
39
40 #define NRFX_LOG_MODULE NFCT
41 #include <nrfx_log.h>
42
43 #define FIELD_TIMER_FREQUENCY_HZ NRFX_MHZ_TO_HZ(1)
44
45 #if !defined(USE_WORKAROUND_FOR_ANOMALY_79) && \
46 (defined(NRF52832_XXAA) || defined(NRF52832_XXAB))
47 #define USE_WORKAROUND_FOR_ANOMALY_79 1
48 #endif
49
50 #if !defined(USE_WORKAROUND_FOR_ANOMALY_190) && \
51 (defined(NRF52833_XXAA) || defined(NRF52840_XXAA) || \
52 defined(NRF5340_XXAA_APPLICATION))
53 #define USE_WORKAROUND_FOR_ANOMALY_190 1
54 #endif
55
56 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79) || NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
57 #define NFCT_WORKAROUND_USES_TIMER 1
58 #endif
59
60 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
61 #include <nrfx_timer.h>
62
63 typedef struct
64 {
65 const nrfx_timer_t timer; /**< Timer instance that supports the correct NFC field detection. */
66 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
67 bool fieldevents_filter_active; /**< Flag that indicates that the field events are ignored. */
68 bool is_hfclk_on; /**< HFCLK has started - one of the NFC activation conditions. */
69 bool is_delayed; /**< Required time delay has passed - one of the NFC activation conditions. */
70 #elif NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
71 uint32_t field_state_cnt; /**< Counter of the FIELDLOST events. */
72 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
73 } nrfx_nfct_timer_workaround_t;
74
75 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
76 #define NRFX_NFCT_ACTIVATE_DELAY 1000 /**< Minimal delay in us between NFC field detection and activation of NFCT. */
77 #define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_ACTIVATE_DELAY
78 #elif NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
79 #define NRFX_NFCT_FIELDLOST_THR 7
80 #define NRFX_NFCT_FIELD_TIMER_PERIOD 100 /**< Field polling period in us. */
81 #define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_FIELD_TIMER_PERIOD
82 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
83
84 static nrfx_nfct_timer_workaround_t m_timer_workaround =
85 {
86 .timer = NRFX_TIMER_INSTANCE(NRFX_NFCT_CONFIG_TIMER_INSTANCE_ID),
87 };
88 #endif // NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
89
90 #define NFCT_FRAMEDELAYMAX_DEFAULT (0x00001000UL) /**< Default value of the FRAMEDELAYMAX. */
91 #define NFCT_FRAMEDELAYMIN_DEFAULT (0x00000480UL) /**< Default value of the FRAMEDELAYMIN. */
92
93 /* Mask of all possible interrupts that are relevant for data reception. */
94 #define NRFX_NFCT_RX_INT_MASK (NRF_NFCT_INT_RXFRAMESTART_MASK | \
95 NRF_NFCT_INT_RXFRAMEEND_MASK | \
96 NRF_NFCT_INT_RXERROR_MASK)
97
98 /* Mask of all possible interrupts that are relevant for data transmission. */
99 #define NRFX_NFCT_TX_INT_MASK (NRF_NFCT_INT_TXFRAMESTART_MASK | \
100 NRF_NFCT_INT_TXFRAMEEND_MASK)
101
102
103 /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_RXERROR event. */
104 #define NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK (NRF_NFCT_RX_FRAME_STATUS_CRC_MASK | \
105 NRF_NFCT_RX_FRAME_STATUS_PARITY_MASK | \
106 NRF_NFCT_RX_FRAME_STATUS_OVERRUN_MASK)
107
108 /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_ERROR event. */
109 #if defined (NRF52832_XXAA) || defined(NRF52832_XXAB)
110 #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK | \
111 NRF_NFCT_ERROR_NFCFIELDTOOSTRONG_MASK | \
112 NRF_NFCT_ERROR_NFCFIELDTOOWEAK_MASK)
113 #else
114 #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
115 #endif
116
117 /* Macros for conversion of bits to bytes. */
118 #define NRFX_NFCT_BYTES_TO_BITS(_bytes) ((_bytes) << 3)
119 #define NRFX_NFCT_BITS_TO_BYTES(_bits) ((_bits) >> 3)
120
121 /* Macro for checking whether the NFCT interrupt is active. */
122 #define NRFX_NFCT_EVT_ACTIVE(_name) \
123 (nrf_nfct_event_check(NRF_NFCT, NRFX_CONCAT_2(NRF_NFCT_EVENT_, _name)) && \
124 nrf_nfct_int_enable_check(NRF_NFCT, NRFX_CONCAT_3(NRF_NFCT_INT_, _name, _MASK)))
125
126 /* Macro for callback execution. */
127 #define NRFX_NFCT_CB_HANDLE(_cb, _evt) \
128 if (_cb != NULL) \
129 { \
130 _cb(&_evt); \
131 }
132
133 typedef enum
134 {
135 NRFX_NFC_FIELD_STATE_NONE, /**< Initial value that indicates no NFCT field events. */
136 NRFX_NFC_FIELD_STATE_OFF, /**< The NFCT FIELDLOST event has been set. */
137 NRFX_NFC_FIELD_STATE_ON, /**< The NFCT FIELDDETECTED event has been set. */
138 NRFX_NFC_FIELD_STATE_UNKNOWN /**< Both NFCT field events have been set - ambiguous state. */
139 } nrfx_nfct_field_state_t;
140
141 /** @brief NFCT control block. */
142 typedef struct
143 {
144 nrfx_nfct_config_t config;
145 nrfx_drv_state_t state;
146 volatile bool field_on;
147 uint32_t frame_delay_max;
148 uint32_t frame_delay_min;
149 } nrfx_nfct_control_block_t;
150
151 static nrfx_nfct_control_block_t m_nfct_cb;
152
153 /**
154 * @brief Common part of the setup used for the NFCT initialization and reinitialization.
155 */
nrfx_nfct_hw_init_setup(void)156 static void nrfx_nfct_hw_init_setup(void)
157 {
158 // Use Window Grid frame delay mode.
159 nrf_nfct_frame_delay_mode_set(NRF_NFCT, NRF_NFCT_FRAME_DELAY_MODE_WINDOWGRID);
160
161 /* Begin: Workaround for anomaly 25 */
162 /* Workaround for wrong SENSRES values require using SDD00001, but here SDD00100 is used
163 because it is required to operate with Windows Phone */
164 nrf_nfct_sensres_bit_frame_sdd_set(NRF_NFCT, NRF_NFCT_SENSRES_BIT_FRAME_SDD_00100);
165 /* End: Workaround for anomaly 25 */
166 }
167
nrfx_nfct_frame_delay_max_set(bool default_delay)168 static void nrfx_nfct_frame_delay_max_set(bool default_delay)
169 {
170 if (default_delay)
171 {
172 nrf_nfct_frame_delay_max_set(NRF_NFCT, NFCT_FRAMEDELAYMAX_DEFAULT);
173 }
174 else
175 {
176 nrf_nfct_frame_delay_max_set(NRF_NFCT, m_nfct_cb.frame_delay_max);
177 }
178 }
179
180 /** @brief Function for evaluating and handling the NFC field events.
181 *
182 * @param[in] field_state Current field state.
183 */
nrfx_nfct_field_event_handler(volatile nrfx_nfct_field_state_t field_state)184 static void nrfx_nfct_field_event_handler(volatile nrfx_nfct_field_state_t field_state)
185 {
186 nrfx_nfct_evt_t nfct_evt;
187
188 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
189 if(m_timer_workaround.fieldevents_filter_active)
190 {
191 return;
192 }
193 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
194
195 if (field_state == NRFX_NFC_FIELD_STATE_UNKNOWN)
196 {
197 /* Probe NFC field */
198 field_state = (nrfx_nfct_field_check()) ? NRFX_NFC_FIELD_STATE_ON :
199 NRFX_NFC_FIELD_STATE_OFF;
200 }
201
202 /* Field event service. Only take action on field transition -
203 * based on the value of m_nfct_cb.field_on
204 */
205 switch (field_state)
206 {
207 case NRFX_NFC_FIELD_STATE_ON:
208 if (!m_nfct_cb.field_on)
209 {
210 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
211 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
212 m_timer_workaround.is_hfclk_on = false;
213 m_timer_workaround.is_delayed = false;
214 m_timer_workaround.fieldevents_filter_active = true;
215
216 nrfx_timer_clear(&m_timer_workaround.timer);
217 nrfx_timer_enable(&m_timer_workaround.timer);
218 #elif NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
219 nrfx_timer_clear(&m_timer_workaround.timer);
220 nrfx_timer_enable(&m_timer_workaround.timer);
221 m_timer_workaround.field_state_cnt = 0;
222 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
223 #endif // NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
224
225 m_nfct_cb.field_on = true;
226 nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_DETECTED;
227 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
228 }
229 break;
230
231 case NRFX_NFC_FIELD_STATE_OFF:
232 if (m_nfct_cb.field_on)
233 {
234 nrf_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_SENSE);
235 nrf_nfct_int_disable(NRF_NFCT, NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
236 m_nfct_cb.field_on = false;
237 nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_LOST;
238
239 /* Begin: Workaround for anomaly 218 */
240 nrfx_nfct_frame_delay_max_set(true);
241 /* End: Workaround for anomaly 218 */
242
243 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
244 }
245 break;
246
247 default:
248 /* No implementation required */
249 break;
250 }
251 }
252
253 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
254 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
nrfx_nfct_activate_check(void)255 static void nrfx_nfct_activate_check(void)
256 {
257 static bool is_field_validation_pending = false;
258
259 if (is_field_validation_pending)
260 {
261 is_field_validation_pending = false;
262 m_timer_workaround.fieldevents_filter_active = false;
263
264 // Check the field status and take action if field is lost.
265 nrfx_nfct_field_event_handler(NRFX_NFC_FIELD_STATE_UNKNOWN);
266 return;
267 }
268
269 if ((m_timer_workaround.is_hfclk_on) && (m_timer_workaround.is_delayed))
270 {
271 nrf_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_ACTIVATE);
272 is_field_validation_pending = true;
273
274 // Start the timer second time to validate whether the tag has locked to the field.
275 nrfx_timer_clear(&m_timer_workaround.timer);
276 nrfx_timer_enable(&m_timer_workaround.timer);
277 }
278 }
279 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
280
281 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
282 /* Begin: Workaround for anomaly 116 */
nrfx_nfct_reset(void)283 static inline void nrfx_nfct_reset(void)
284 {
285 uint32_t fdmax;
286 uint32_t fdmin;
287 uint32_t int_enabled;
288 uint8_t nfcid1[NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE];
289 nrf_nfct_sensres_nfcid1_size_t nfcid1_size;
290 nrf_nfct_selres_protocol_t protocol;
291
292 // Save parameter settings before the reset of the NFCT peripheral.
293 fdmax = nrf_nfct_frame_delay_max_get(NRF_NFCT);
294 fdmin = nrf_nfct_frame_delay_min_get(NRF_NFCT);
295 nfcid1_size = nrf_nfct_nfcid1_get(NRF_NFCT, nfcid1);
296 protocol = nrf_nfct_selres_protocol_get(NRF_NFCT);
297 int_enabled = nrf_nfct_int_enable_get(NRF_NFCT);
298
299 // Reset the NFCT peripheral.
300 *(volatile uint32_t *)0x40005FFC = 0;
301 *(volatile uint32_t *)0x40005FFC;
302 *(volatile uint32_t *)0x40005FFC = 1;
303
304 // Restore parameter settings after the reset of the NFCT peripheral.
305 nrf_nfct_frame_delay_max_set(NRF_NFCT, fdmax);
306 nrf_nfct_frame_delay_min_set(NRF_NFCT, fdmin);
307 nrf_nfct_nfcid1_set(NRF_NFCT, nfcid1, nfcid1_size);
308 nrf_nfct_selres_protocol_set(NRF_NFCT, protocol);
309
310 // Restore general HW configuration.
311 nrfx_nfct_hw_init_setup();
312
313 // Restore interrupts.
314 nrf_nfct_int_enable(NRF_NFCT, int_enabled);
315
316 // Disable interrupts associated with data exchange.
317 nrf_nfct_int_disable(NRF_NFCT, NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
318
319 NRFX_LOG_INFO("Reinitialize");
320 }
321 /* End: Workaround for anomaly 116 */
322
nrfx_nfct_field_poll(void)323 static void nrfx_nfct_field_poll(void)
324 {
325 if (!nrfx_nfct_field_check())
326 {
327 if (++m_timer_workaround.field_state_cnt > NRFX_NFCT_FIELDLOST_THR)
328 {
329 nrfx_nfct_evt_t nfct_evt =
330 {
331 .evt_id = NRFX_NFCT_EVT_FIELD_LOST,
332 };
333
334 nrfx_timer_disable(&m_timer_workaround.timer);
335 m_nfct_cb.field_on = false;
336
337 nrfx_nfct_frame_delay_max_set(true);
338
339 /* Begin: Workaround for anomaly 116 */
340 /* resume the NFCT to initialized state */
341 nrfx_nfct_reset();
342 /* End: Workaround for anomaly 116 */
343
344 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
345 }
346 return;
347 }
348
349 m_timer_workaround.field_state_cnt = 0;
350 }
351 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
352
nrfx_nfct_field_timer_handler(nrf_timer_event_t event_type,void * p_context)353 static void nrfx_nfct_field_timer_handler(nrf_timer_event_t event_type, void * p_context)
354 {
355 (void)p_context;
356
357 if (event_type != NRF_TIMER_EVENT_COMPARE0)
358 {
359 return;
360 }
361
362 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
363 m_timer_workaround.is_delayed = true;
364
365 nrfx_timer_disable(&m_timer_workaround.timer);
366 nrfx_nfct_activate_check();
367 #elif NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
368 nrfx_nfct_field_poll();
369 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
370 }
371
nrfx_nfct_field_timer_config(void)372 static inline nrfx_err_t nrfx_nfct_field_timer_config(void)
373 {
374 nrfx_err_t err_code;
375 nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG(FIELD_TIMER_FREQUENCY_HZ);
376 timer_cfg.interrupt_priority = NRFX_NFCT_DEFAULT_CONFIG_IRQ_PRIORITY;
377
378 err_code = nrfx_timer_init(&m_timer_workaround.timer,
379 &timer_cfg,
380 nrfx_nfct_field_timer_handler);
381 if (err_code != NRFX_SUCCESS)
382 {
383 return err_code;
384 }
385
386 nrfx_timer_extended_compare(&m_timer_workaround.timer,
387 NRF_TIMER_CC_CHANNEL0,
388 nrfx_timer_us_to_ticks(&m_timer_workaround.timer,
389 NRFX_NFCT_TIMER_PERIOD),
390 NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
391 true);
392 return err_code;
393 }
394 #endif // NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
395
396 static inline
nrf_nfct_nfcid1_size_to_sensres_size(uint8_t nfcid1_size)397 nrf_nfct_sensres_nfcid1_size_t nrf_nfct_nfcid1_size_to_sensres_size(uint8_t nfcid1_size)
398 {
399 switch (nfcid1_size)
400 {
401 case NRFX_NFCT_NFCID1_SINGLE_SIZE:
402 return NRF_NFCT_SENSRES_NFCID1_SIZE_SINGLE;
403
404 case NRFX_NFCT_NFCID1_DOUBLE_SIZE:
405 return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
406
407 case NRFX_NFCT_NFCID1_TRIPLE_SIZE:
408 return NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE;
409
410 default:
411 return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
412 }
413 }
414
nrfx_nfct_rxtx_int_enable(uint32_t rxtx_int_mask)415 static inline void nrfx_nfct_rxtx_int_enable(uint32_t rxtx_int_mask)
416 {
417 nrf_nfct_int_enable(NRF_NFCT, rxtx_int_mask & m_nfct_cb.config.rxtx_int_mask);
418 }
419
nrfx_nfct_init(nrfx_nfct_config_t const * p_config)420 nrfx_err_t nrfx_nfct_init(nrfx_nfct_config_t const * p_config)
421 {
422 NRFX_ASSERT(p_config);
423
424 nrfx_err_t err_code = NRFX_SUCCESS;
425
426 if (m_nfct_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
427 {
428 return NRFX_ERROR_INVALID_STATE;
429 }
430
431 m_nfct_cb.config = *p_config;
432 nrfx_nfct_hw_init_setup();
433
434 NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
435 NRFX_IRQ_PRIORITY_SET(NFCT_IRQn, NRFX_NFCT_DEFAULT_CONFIG_IRQ_PRIORITY);
436 NRFX_IRQ_ENABLE(NFCT_IRQn);
437
438 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
439 /* Initialize Timer module as the workaround for NFCT HW issues. */
440 err_code = nrfx_nfct_field_timer_config();
441 #endif // NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
442
443 m_nfct_cb.state = NRFX_DRV_STATE_INITIALIZED;
444 m_nfct_cb.frame_delay_max = NFCT_FRAMEDELAYMAX_DEFAULT;
445 m_nfct_cb.frame_delay_min = NFCT_FRAMEDELAYMIN_DEFAULT;
446
447 NRFX_LOG_INFO("Initialized");
448 return err_code;
449 }
450
nrfx_nfct_uninit(void)451 void nrfx_nfct_uninit(void)
452 {
453 nrfx_nfct_disable();
454
455 NRFX_IRQ_DISABLE(NFCT_IRQn);
456 NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
457
458 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
459 /* De-initialize Timer module as the workaround for NFCT HW issues. */
460 nrfx_timer_uninit(&m_timer_workaround.timer);
461 #endif // NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
462
463 m_nfct_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
464 }
465
nrfx_nfct_enable(void)466 void nrfx_nfct_enable(void)
467 {
468 nrf_nfct_error_status_clear(NRF_NFCT, NRFX_NFCT_ERROR_STATUS_ALL_MASK);
469 nrf_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_SENSE);
470
471 nrf_nfct_int_enable(NRF_NFCT, NRF_NFCT_INT_FIELDDETECTED_MASK |
472 NRF_NFCT_INT_ERROR_MASK |
473 NRF_NFCT_INT_SELECTED_MASK);
474 #if !NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
475 nrf_nfct_int_enable(NRF_NFCT, NRF_NFCT_INT_FIELDLOST_MASK);
476 #endif // !NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
477
478 NRFX_LOG_INFO("Start");
479 }
480
nrfx_nfct_disable(void)481 void nrfx_nfct_disable(void)
482 {
483 nrf_nfct_int_disable(NRF_NFCT, NRF_NFCT_DISABLE_ALL_INT);
484 nrf_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_DISABLE);
485
486 NRFX_LOG_INFO("Stop");
487 }
488
nrfx_nfct_field_check(void)489 bool nrfx_nfct_field_check(void)
490 {
491 uint32_t const field_state = nrf_nfct_field_status_get(NRF_NFCT);
492
493 if (((field_state & NRF_NFCT_FIELD_STATE_PRESENT_MASK) == 0) &&
494 ((field_state & NRF_NFCT_FIELD_STATE_LOCK_MASK) == 0))
495 {
496 /* Field is not active */
497 return false;
498 }
499
500 return true;
501 }
502
nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_tx_data)503 void nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_tx_data)
504 {
505 NRFX_ASSERT(p_tx_data);
506
507 nrf_nfct_rxtx_buffer_set(NRF_NFCT, (uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
508
509 nrfx_nfct_rxtx_int_enable(NRFX_NFCT_RX_INT_MASK);
510 nrf_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_ENABLERXDATA);
511 }
512
nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,nrf_nfct_frame_delay_mode_t delay_mode)513 nrfx_err_t nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,
514 nrf_nfct_frame_delay_mode_t delay_mode)
515 {
516 NRFX_ASSERT(p_tx_data);
517 NRFX_ASSERT(p_tx_data->p_data);
518
519 nrfx_err_t err = NRFX_SUCCESS;
520
521 if (p_tx_data->data_size == 0)
522 {
523 return NRFX_ERROR_INVALID_LENGTH;
524 }
525
526 NRFX_CRITICAL_SECTION_ENTER();
527
528 /* In case when NFC frame transmission has already started, it returns an error. */
529 if (NRFX_NFCT_EVT_ACTIVE(TXFRAMESTART))
530 {
531 err = NRFX_ERROR_BUSY;
532 }
533 else
534 {
535 /* In case when Tx operation was scheduled with delay, stop scheduled Tx operation. */
536 #if defined(NRF52_SERIES)
537 *(volatile uint32_t *)0x40005010 = 0x01;
538 #elif defined(NRF5340_XXAA_APPLICATION) && defined(NRF_TRUSTZONE_NONSECURE)
539 *(volatile uint32_t *)0x4002D010 = 0x01;
540 #elif defined(NRF5340_XXAA_APPLICATION)
541 *(volatile uint32_t *)0x5002D010 = 0x01;
542 #endif
543 nrf_nfct_rxtx_buffer_set(NRF_NFCT, (uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
544 nrf_nfct_tx_bits_set(NRF_NFCT, NRFX_NFCT_BYTES_TO_BITS(p_tx_data->data_size));
545 nrf_nfct_frame_delay_mode_set(NRF_NFCT, (nrf_nfct_frame_delay_mode_t) delay_mode);
546 nrfx_nfct_frame_delay_max_set(false);
547
548 nrfx_nfct_rxtx_int_enable(NRFX_NFCT_TX_INT_MASK);
549 nrf_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_STARTTX);
550 }
551
552 NRFX_CRITICAL_SECTION_EXIT();
553
554 if (err == NRFX_SUCCESS)
555 {
556 NRFX_LOG_INFO("Tx start");
557 }
558
559 return err;
560 }
561
nrfx_nfct_bits_tx(nrfx_nfct_data_desc_t const * p_tx_data,nrf_nfct_frame_delay_mode_t delay_mode)562 nrfx_err_t nrfx_nfct_bits_tx(nrfx_nfct_data_desc_t const * p_tx_data,
563 nrf_nfct_frame_delay_mode_t delay_mode)
564 {
565 NRFX_ASSERT(p_tx_data);
566 NRFX_ASSERT(p_tx_data->p_data);
567
568 nrfx_err_t err = NRFX_SUCCESS;
569
570 if (p_tx_data->data_size == 0)
571 {
572 return NRFX_ERROR_INVALID_LENGTH;
573 }
574
575 /* Get buffer length, add additional byte if bits go beyond last whole byte */
576 uint32_t buffer_length = NRFX_NFCT_BITS_TO_BYTES(p_tx_data->data_size);
577 if (p_tx_data->data_size & NFCT_TXD_AMOUNT_TXDATABITS_Msk)
578 {
579 ++buffer_length;
580 }
581
582 NRFX_CRITICAL_SECTION_ENTER();
583
584 /* In case when NFC frame transmission has already started, it returns an error. */
585 if (NRFX_NFCT_EVT_ACTIVE(TXFRAMESTART))
586 {
587 err = NRFX_ERROR_BUSY;
588 }
589 else
590 {
591 /* In case when Tx operation was scheduled with delay, stop scheduled Tx operation. */
592 #if defined(NRF52_SERIES)
593 *(volatile uint32_t *)0x40005010 = 0x01;
594 #elif defined(NRF5340_XXAA_APPLICATION) && defined(NRF_TRUSTZONE_NONSECURE)
595 *(volatile uint32_t *)0x4002D010 = 0x01;
596 #elif defined(NRF5340_XXAA_APPLICATION)
597 *(volatile uint32_t *)0x5002D010 = 0x01;
598 #endif
599 nrf_nfct_rxtx_buffer_set(NRF_NFCT, (uint8_t *) p_tx_data->p_data, buffer_length);
600 nrf_nfct_tx_bits_set(NRF_NFCT, p_tx_data->data_size);
601 nrf_nfct_frame_delay_mode_set(NRF_NFCT, (nrf_nfct_frame_delay_mode_t) delay_mode);
602 nrfx_nfct_frame_delay_max_set(false);
603
604 nrfx_nfct_rxtx_int_enable(NRFX_NFCT_TX_INT_MASK);
605 nrf_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_STARTTX);
606 }
607
608 NRFX_CRITICAL_SECTION_EXIT();
609
610 if (err == NRFX_SUCCESS)
611 {
612 NRFX_LOG_INFO("Tx start");
613 }
614
615 return err;
616 }
617
nrfx_nfct_state_force(nrfx_nfct_state_t state)618 void nrfx_nfct_state_force(nrfx_nfct_state_t state)
619 {
620 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
621 if (state == NRFX_NFCT_STATE_ACTIVATED)
622 {
623 m_timer_workaround.is_hfclk_on = true;
624 /* NFCT will be activated based on additional conditions */
625 nrfx_nfct_activate_check();
626 return;
627 }
628 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
629 nrf_nfct_task_trigger(NRF_NFCT, (nrf_nfct_task_t) state);
630 }
631
nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state)632 void nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state)
633 {
634 if (sub_state == NRFX_NFCT_ACTIVE_STATE_DEFAULT)
635 {
636 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
637 if (((*(uint32_t volatile *)(0x40005420)) & 0x1UL) == (1UL))
638 #else
639 if (nrf_nfct_sleep_state_get(NRF_NFCT) == NRF_NFCT_SLEEP_STATE_SLEEP_A)
640 #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
641 {
642 // Default state is SLEEP_A
643 nrf_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_GOSLEEP);
644 }
645 else
646 {
647 // Default state is IDLE
648 nrf_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_GOIDLE);
649 }
650 }
651 else
652 {
653 nrf_nfct_task_trigger(NRF_NFCT, (nrf_nfct_task_t) sub_state);
654 }
655
656 nrfx_nfct_frame_delay_max_set(true);
657
658 /* Disable TX/RX here (will be enabled at SELECTED) */
659 nrf_nfct_int_disable(NRF_NFCT, NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
660 }
661
nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param)662 nrfx_err_t nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param)
663 {
664 NRFX_ASSERT(p_param);
665
666 switch (p_param->id)
667 {
668 case NRFX_NFCT_PARAM_ID_FDT:
669 {
670 uint32_t delay = p_param->data.fdt;
671 uint32_t delay_thr = NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Msk;
672 uint32_t delay_max;
673
674 delay_max = (delay > delay_thr) ? delay_thr : delay;
675 if (delay_max < m_nfct_cb.frame_delay_min)
676 {
677 return NRFX_ERROR_INVALID_PARAM;
678 }
679
680 m_nfct_cb.frame_delay_max = delay_max;
681 break;
682 }
683
684 case NRFX_NFCT_PARAM_ID_FDT_MIN:
685 {
686 uint32_t delay = p_param->data.fdt_min;
687 uint32_t delay_thr = NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Msk;
688 uint32_t delay_min;
689
690 delay_min = (delay > delay_thr) ? delay_thr : delay;
691 if (delay_min > m_nfct_cb.frame_delay_max)
692 {
693 return NRFX_ERROR_INVALID_PARAM;
694 }
695
696 m_nfct_cb.frame_delay_min = delay_min;
697 nrf_nfct_frame_delay_min_set(NRF_NFCT, m_nfct_cb.frame_delay_min);
698 break;
699 }
700
701 case NRFX_NFCT_PARAM_ID_SEL_RES:
702 if (p_param->data.sel_res_protocol > NRF_NFCT_SELRES_PROTOCOL_NFCDEP_T4AT)
703 {
704 return NRFX_ERROR_INVALID_PARAM;
705 }
706
707 nrf_nfct_selres_protocol_set(NRF_NFCT,
708 (nrf_nfct_selres_protocol_t) p_param->data.sel_res_protocol);
709 break;
710
711 case NRFX_NFCT_PARAM_ID_NFCID1:
712 {
713 nrf_nfct_sensres_nfcid1_size_t id_size_mask;
714
715 id_size_mask = nrf_nfct_nfcid1_size_to_sensres_size(p_param->data.nfcid1.id_size);
716 nrf_nfct_nfcid1_set(NRF_NFCT, p_param->data.nfcid1.p_id, id_size_mask);
717 break;
718 }
719
720 default:
721 break;
722 }
723
724 return NRFX_SUCCESS;
725 }
726
nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,uint32_t nfcid1_buff_len)727 nrfx_err_t nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,
728 uint32_t nfcid1_buff_len)
729 {
730 if ((nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE) &&
731 (nfcid1_buff_len != NRFX_NFCT_NFCID1_DOUBLE_SIZE) &&
732 (nfcid1_buff_len != NRFX_NFCT_NFCID1_TRIPLE_SIZE))
733 {
734 return NRFX_ERROR_INVALID_LENGTH;
735 }
736
737 #if defined(FICR_NFC_TAGHEADER0_MFGID_Msk) && !defined(NRF_TRUSTZONE_NONSECURE)
738 uint32_t nfc_tag_header0 = NRF_FICR->NFC.TAGHEADER0;
739 uint32_t nfc_tag_header1 = NRF_FICR->NFC.TAGHEADER1;
740 uint32_t nfc_tag_header2 = NRF_FICR->NFC.TAGHEADER2;
741 #else
742 uint32_t nfc_tag_header0 = 0x5F;
743 uint32_t nfc_tag_header1 = 0;
744 uint32_t nfc_tag_header2 = 0;
745 #endif
746
747 p_nfcid1_buff[0] = (uint8_t) (nfc_tag_header0 >> 0);
748 p_nfcid1_buff[1] = (uint8_t) (nfc_tag_header0 >> 8);
749 p_nfcid1_buff[2] = (uint8_t) (nfc_tag_header0 >> 16);
750 p_nfcid1_buff[3] = (uint8_t) (nfc_tag_header1 >> 0);
751
752 if (nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE)
753 {
754 p_nfcid1_buff[4] = (uint8_t) (nfc_tag_header1 >> 8);
755 p_nfcid1_buff[5] = (uint8_t) (nfc_tag_header1 >> 16);
756 p_nfcid1_buff[6] = (uint8_t) (nfc_tag_header1 >> 24);
757
758 if (nfcid1_buff_len == NRFX_NFCT_NFCID1_TRIPLE_SIZE)
759 {
760 p_nfcid1_buff[7] = (uint8_t) (nfc_tag_header2 >> 0);
761 p_nfcid1_buff[8] = (uint8_t) (nfc_tag_header2 >> 8);
762 p_nfcid1_buff[9] = (uint8_t) (nfc_tag_header2 >> 16);
763 }
764 /* Begin: Workaround for anomaly 181. */
765 /* Workaround for wrong value in NFCID1. Value 0x88 cannot be used as byte 3
766 of a double-size NFCID1, according to the NFC Forum Digital Protocol specification. */
767 else if (p_nfcid1_buff[3] == 0x88)
768 {
769 p_nfcid1_buff[3] |= 0x11;
770 }
771 /* End: Workaround for anomaly 181 */
772 }
773
774 return NRFX_SUCCESS;
775 }
776
nrfx_nfct_autocolres_enable(void)777 void nrfx_nfct_autocolres_enable(void)
778 {
779 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
780 (*(uint32_t *)(0x4000559C)) &= (~(0x1UL));
781 #else
782 nrf_nfct_autocolres_enable(NRF_NFCT);
783 #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
784 }
785
nrfx_nfct_autocolres_disable(void)786 void nrfx_nfct_autocolres_disable(void)
787 {
788 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
789 (*(uint32_t *)(0x4000559C)) |= (0x1UL);
790 #else
791 nrf_nfct_autocolres_disable(NRF_NFCT);
792 #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
793 }
794
nrfx_nfct_irq_handler(void)795 void nrfx_nfct_irq_handler(void)
796 {
797 nrfx_nfct_field_state_t current_field = NRFX_NFC_FIELD_STATE_NONE;
798
799 if (NRFX_NFCT_EVT_ACTIVE(FIELDDETECTED))
800 {
801 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_FIELDDETECTED);
802 current_field = NRFX_NFC_FIELD_STATE_ON;
803
804 NRFX_LOG_DEBUG("Field detected");
805 }
806
807 #if !NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
808 if (NRFX_NFCT_EVT_ACTIVE(FIELDLOST))
809 {
810 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_FIELDLOST);
811 current_field = (current_field == NRFX_NFC_FIELD_STATE_NONE) ?
812 NRFX_NFC_FIELD_STATE_OFF : NRFX_NFC_FIELD_STATE_UNKNOWN;
813
814 NRFX_LOG_DEBUG("Field lost");
815 }
816 #endif //!NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
817
818 /* Perform actions if any FIELD event is active */
819 if (current_field != NRFX_NFC_FIELD_STATE_NONE)
820 {
821 nrfx_nfct_field_event_handler(current_field);
822 }
823
824 if (NRFX_NFCT_EVT_ACTIVE(RXFRAMESTART))
825 {
826 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_RXFRAMESTART);
827
828 nrfx_nfct_evt_t nfct_evt =
829 {
830 .evt_id = NRFX_NFCT_EVT_RX_FRAMESTART
831 };
832
833 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
834 }
835
836 if (NRFX_NFCT_EVT_ACTIVE(RXFRAMEEND))
837 {
838 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_RXFRAMEEND);
839
840 nrfx_nfct_evt_t nfct_evt =
841 {
842 .evt_id = NRFX_NFCT_EVT_RX_FRAMEEND
843 };
844
845 /* Take into account only the number of whole bytes. */
846 nfct_evt.params.rx_frameend.rx_status = 0;
847 nfct_evt.params.rx_frameend.rx_data.p_data = nrf_nfct_rxtx_buffer_get(NRF_NFCT);
848 nfct_evt.params.rx_frameend.rx_data.data_size =
849 NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_rx_bits_get(NRF_NFCT, true));
850
851 if (NRFX_NFCT_EVT_ACTIVE(RXERROR))
852 {
853 nfct_evt.params.rx_frameend.rx_status =
854 (nrf_nfct_rx_frame_status_get(NRF_NFCT) & NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
855 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_RXERROR);
856
857 NRFX_LOG_DEBUG("Rx error (0x%x)", (unsigned int) nfct_evt.params.rx_frameend.rx_status);
858
859 /* Clear rx frame status */
860 nrf_nfct_rx_frame_status_clear(NRF_NFCT, NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
861 }
862
863 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
864
865 NRFX_LOG_DEBUG("Rx fend");
866 }
867
868 if (NRFX_NFCT_EVT_ACTIVE(SELECTED))
869 {
870 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_SELECTED);
871 /* Clear also RX END and RXERROR events because SW does not take care of
872 commands that were received before selecting the tag. */
873 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_RXFRAMEEND);
874 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_RXERROR);
875 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_TXFRAMESTART);
876 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_TXFRAMEEND);
877
878 nrfx_nfct_frame_delay_max_set(false);
879
880 /* At this point any previous error status can be ignored. */
881 nrf_nfct_rx_frame_status_clear(NRF_NFCT, NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
882 nrf_nfct_error_status_clear(NRF_NFCT, NRFX_NFCT_ERROR_STATUS_ALL_MASK);
883
884 nrfx_nfct_evt_t nfct_evt =
885 {
886 .evt_id = NRFX_NFCT_EVT_SELECTED
887 };
888 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
889
890 NRFX_LOG_DEBUG("Selected");
891 }
892
893 if (NRFX_NFCT_EVT_ACTIVE(ERROR))
894 {
895 uint32_t err_status = nrf_nfct_error_status_get(NRF_NFCT);
896 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_ERROR);
897
898 nrfx_nfct_evt_t nfct_evt =
899 {
900 .evt_id = NRFX_NFCT_EVT_ERROR
901 };
902
903 /* Clear FRAMEDELAYTIMEOUT error (expected HW behaviour) when SLP_REQ command was received. */
904 if (err_status & NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
905 {
906 nrf_nfct_error_status_clear(NRF_NFCT, NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK);
907
908 nfct_evt.params.error.reason = NRFX_NFCT_ERROR_FRAMEDELAYTIMEOUT;
909 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
910 }
911
912 /* Report any other error. */
913 err_status &= ~NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK;
914 if (err_status)
915 {
916 NRFX_LOG_DEBUG("Error (0x%x)", (unsigned int) err_status);
917 }
918
919 /* Clear error status. */
920 nrf_nfct_error_status_clear(NRF_NFCT, NRFX_NFCT_ERROR_STATUS_ALL_MASK);
921 }
922
923 if (NRFX_NFCT_EVT_ACTIVE(TXFRAMESTART))
924 {
925 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_TXFRAMESTART);
926
927 if (m_nfct_cb.config.cb != NULL)
928 {
929 nrfx_nfct_evt_t nfct_evt;
930
931 nfct_evt.evt_id = NRFX_NFCT_EVT_TX_FRAMESTART;
932 nfct_evt.params.tx_framestart.tx_data.p_data = nrf_nfct_rxtx_buffer_get(NRF_NFCT);
933 nfct_evt.params.tx_framestart.tx_data.data_size =
934 NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_tx_bits_get(NRF_NFCT));
935
936 m_nfct_cb.config.cb(&nfct_evt);
937 }
938 }
939
940 if (NRFX_NFCT_EVT_ACTIVE(TXFRAMEEND))
941 {
942 nrf_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_TXFRAMEEND);
943
944 nrfx_nfct_evt_t nfct_evt =
945 {
946 .evt_id = NRFX_NFCT_EVT_TX_FRAMEEND
947 };
948
949 /* Ignore any frame transmission until a new TX is scheduled by nrfx_nfct_tx() */
950 nrf_nfct_int_disable(NRF_NFCT, NRFX_NFCT_TX_INT_MASK);
951
952 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
953
954 NRFX_LOG_DEBUG("Tx fend");
955 }
956 }
957
958 #endif // NRFX_CHECK(NRFX_NFCT_ENABLED)
959