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