1 /*
2 * Copyright (c) 2018 - 2025, 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 #include <hal/nrf_ficr.h>
40
41 #define NRFX_LOG_MODULE NFCT
42 #include <nrfx_log.h>
43
44 #define FIELD_TIMER_FREQUENCY_HZ NRFX_MHZ_TO_HZ(1)
45
46 #if !defined(USE_WORKAROUND_FOR_ANOMALY_79) && \
47 (defined(NRF52832_XXAA) || defined(NRF52832_XXAB))
48 #define USE_WORKAROUND_FOR_ANOMALY_79 1
49 #endif
50
51 #if !defined(USE_WORKAROUND_FOR_ANOMALY_190) && \
52 (defined(NRF52833_XXAA) || defined(NRF52840_XXAA) || \
53 defined(NRF5340_XXAA_APPLICATION))
54 #define USE_WORKAROUND_FOR_ANOMALY_190 1
55 #endif
56
57 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79) || NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
58 #define NFCT_WORKAROUND_USES_TIMER 1
59 #endif
60
61 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
62 #include <nrfx_timer.h>
63
64 typedef struct
65 {
66 const nrfx_timer_t timer; /**< Timer instance that supports the correct NFC field detection. */
67 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
68 bool fieldevents_filter_active; /**< Flag that indicates that the field events are ignored. */
69 bool is_hfclk_on; /**< HFCLK has started - one of the NFC activation conditions. */
70 bool is_delayed; /**< Required time delay has passed - one of the NFC activation conditions. */
71 #elif NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
72 uint32_t field_state_cnt; /**< Counter of the FIELDLOST events. */
73 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
74 } nrfx_nfct_timer_workaround_t;
75
76 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
77 #define NRFX_NFCT_ACTIVATE_DELAY 1000 /**< Minimal delay in us between NFC field detection and activation of NFCT. */
78 #define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_ACTIVATE_DELAY
79 #elif NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
80 #define NRFX_NFCT_FIELDLOST_THR 7
81 #define NRFX_NFCT_FIELD_TIMER_PERIOD 100 /**< Field polling period in us. */
82 #define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_FIELD_TIMER_PERIOD
83 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
84
85 static nrfx_nfct_timer_workaround_t m_timer_workaround =
86 {
87 .timer = NRFX_TIMER_INSTANCE(NRFX_NFCT_CONFIG_TIMER_INSTANCE_ID),
88 };
89 #endif // NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
90
91 #define NFCT_FRAMEDELAYMAX_DEFAULT (0x00001000UL) /**< Default value of the FRAMEDELAYMAX. */
92 #define NFCT_FRAMEDELAYMIN_DEFAULT (0x00000480UL) /**< Default value of the FRAMEDELAYMIN. */
93
94 /* Mask of all possible interrupts that are relevant for data reception. */
95 #define NRFX_NFCT_RX_INT_MASK (NRF_NFCT_INT_RXFRAMESTART_MASK | \
96 NRF_NFCT_INT_RXFRAMEEND_MASK | \
97 NRF_NFCT_INT_RXERROR_MASK)
98
99 /* Mask of all possible interrupts that are relevant for data transmission. */
100 #define NRFX_NFCT_TX_INT_MASK (NRF_NFCT_INT_TXFRAMESTART_MASK | \
101 NRF_NFCT_INT_TXFRAMEEND_MASK)
102
103
104 /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_RXERROR event. */
105 #define NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK (NRF_NFCT_RX_FRAME_STATUS_CRC_MASK | \
106 NRF_NFCT_RX_FRAME_STATUS_PARITY_MASK | \
107 NRF_NFCT_RX_FRAME_STATUS_OVERRUN_MASK)
108
109 /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_ERROR event. */
110 #if defined (NRF52832_XXAA) || defined(NRF52832_XXAB)
111 #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK | \
112 NRF_NFCT_ERROR_NFCFIELDTOOSTRONG_MASK | \
113 NRF_NFCT_ERROR_NFCFIELDTOOWEAK_MASK)
114 #else
115 #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
116 #endif
117
118 /* Macros for conversion of bits to bytes. */
119 #define NRFX_NFCT_BYTES_TO_BITS(_bytes) ((_bytes) << 3UL)
120 #define NRFX_NFCT_BITS_TO_BYTES(_bits) ((_bits) >> 3UL)
121
122 /* Macro for checking whether the NFCT interrupt is active. */
123 #define NRFX_NFCT_EVT_ACTIVE(_name, _mask) \
124 (((_mask) & NRFY_EVENT_TO_INT_BITMASK(NRFX_CONCAT_2(NRF_NFCT_EVENT_, _name))) && \
125 nrfy_nfct_int_enable_check(NRF_NFCT, NRFX_CONCAT_3(NRF_NFCT_INT_, _name, _MASK)))
126
127 /* Macro for callback execution. */
128 #define NRFX_NFCT_CB_HANDLE(_cb, _evt) \
129 if (_cb != NULL) \
130 { \
131 _cb(&_evt); \
132 }
133
134 typedef enum
135 {
136 NRFX_NFC_FIELD_STATE_NONE, /**< Initial value that indicates no NFCT field events. */
137 NRFX_NFC_FIELD_STATE_OFF, /**< The NFCT FIELDLOST event has been set. */
138 NRFX_NFC_FIELD_STATE_ON, /**< The NFCT FIELDDETECTED event has been set. */
139 NRFX_NFC_FIELD_STATE_UNKNOWN /**< Both NFCT field events have been set - ambiguous state. */
140 } nrfx_nfct_field_state_t;
141
142 /** @brief NFCT control block. */
143 typedef struct
144 {
145 nrfx_nfct_config_t config;
146 nrfx_drv_state_t state;
147 volatile bool field_on;
148 uint32_t frame_delay_max;
149 uint32_t frame_delay_min;
150 } nrfx_nfct_control_block_t;
151
152 static nrfx_nfct_control_block_t m_nfct_cb;
153
154 /**
155 * @brief Common part of the setup used for the NFCT initialization and reinitialization.
156 */
nfct_hw_init_setup(void)157 static void nfct_hw_init_setup(void)
158 {
159 // Use Window Grid frame delay mode.
160 nrfy_nfct_frame_delay_mode_set(NRF_NFCT, NRF_NFCT_FRAME_DELAY_MODE_WINDOWGRID);
161
162 /* Begin: Workaround for anomaly 25 */
163 /* Workaround for wrong SENSRES values require using SDD00001, but here SDD00100 is used
164 because it is required to operate with Windows Phone */
165 nrfy_nfct_sensres_bit_frame_sdd_set(NRF_NFCT, NRF_NFCT_SENSRES_BIT_FRAME_SDD_00100);
166 /* End: Workaround for anomaly 25 */
167 }
168
nfct_frame_delay_max_set(bool default_delay)169 static void nfct_frame_delay_max_set(bool default_delay)
170 {
171 if (default_delay)
172 {
173 nrfy_nfct_frame_delay_max_set(NRF_NFCT, NFCT_FRAMEDELAYMAX_DEFAULT);
174 }
175 else
176 {
177 nrfy_nfct_frame_delay_max_set(NRF_NFCT, m_nfct_cb.frame_delay_max);
178 }
179 }
180
nfct_trims_apply(void)181 static void nfct_trims_apply(void)
182 {
183 #if NRFY_NFCT_HAS_BIAS_CONFIG_TRIM_REG && defined(FICR_TRIM_GLOBAL_NFCT_BIASCFG_VALUE_Msk)
184 nrf_nfct_bias_config_t bias_cfg;
185
186 bias_cfg.trim_ibpsr = (NRF_FICR->TRIM.GLOBAL.NFCT.BIASCFG & NFCT_BIASCFG_TRIMIBPSR_Msk)
187 >> NFCT_BIASCFG_TRIMIBPSR_Pos;
188
189 bias_cfg.coarse_ibpsr = (NRF_FICR->TRIM.GLOBAL.NFCT.BIASCFG & NFCT_BIASCFG_COARSEIBPSR_Msk)
190 >> NFCT_BIASCFG_COARSEIBPSR_Pos;
191
192 bias_cfg.reference_volatge = (NRF_FICR->TRIM.GLOBAL.NFCT.BIASCFG &
193 NFCT_BIASCFG_REFERENCEVOLTAGE_Msk)
194 >> NFCT_BIASCFG_REFERENCEVOLTAGE_Pos;
195
196 bias_cfg.spare = (NRF_FICR->TRIM.GLOBAL.NFCT.BIASCFG & NFCT_BIASCFG_SPARE_Msk)
197 >> NFCT_BIASCFG_SPARE_Pos;
198
199 nrfy_nfct_bias_config_set(NRF_NFCT, &bias_cfg);
200 #endif
201 }
202
203 /** @brief Function for evaluating and handling the NFC field events.
204 *
205 * @param[in] field_state Current field state.
206 */
nfct_field_event_handler(volatile nrfx_nfct_field_state_t field_state)207 static void nfct_field_event_handler(volatile nrfx_nfct_field_state_t field_state)
208 {
209 nrfx_nfct_evt_t nfct_evt;
210
211 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
212 if(m_timer_workaround.fieldevents_filter_active)
213 {
214 return;
215 }
216 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
217
218 if (field_state == NRFX_NFC_FIELD_STATE_UNKNOWN)
219 {
220 /* Probe NFC field */
221 field_state = (nrfx_nfct_field_check()) ? NRFX_NFC_FIELD_STATE_ON :
222 NRFX_NFC_FIELD_STATE_OFF;
223 }
224
225 /* Field event service. Only take action on field transition -
226 * based on the value of m_nfct_cb.field_on
227 */
228 switch (field_state)
229 {
230 case NRFX_NFC_FIELD_STATE_ON:
231 if (!m_nfct_cb.field_on)
232 {
233 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
234 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
235 m_timer_workaround.is_hfclk_on = false;
236 m_timer_workaround.is_delayed = false;
237 m_timer_workaround.fieldevents_filter_active = true;
238
239 nrfx_timer_clear(&m_timer_workaround.timer);
240 nrfx_timer_enable(&m_timer_workaround.timer);
241 #elif NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
242 nrfx_timer_clear(&m_timer_workaround.timer);
243 nrfx_timer_enable(&m_timer_workaround.timer);
244 m_timer_workaround.field_state_cnt = 0;
245 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
246 #endif // NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
247
248 m_nfct_cb.field_on = true;
249 nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_DETECTED;
250 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
251 }
252 break;
253
254 case NRFX_NFC_FIELD_STATE_OFF:
255 if (m_nfct_cb.field_on)
256 {
257 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_SENSE);
258 nrfy_nfct_int_disable(NRF_NFCT, NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
259 m_nfct_cb.field_on = false;
260 nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_LOST;
261
262 /* Begin: Workaround for anomaly 218 */
263 nfct_frame_delay_max_set(true);
264 /* End: Workaround for anomaly 218 */
265
266 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
267 }
268 break;
269
270 default:
271 /* No implementation required */
272 break;
273 }
274 }
275
276 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
277 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
nfct_activate_check(void)278 static void nfct_activate_check(void)
279 {
280 static bool is_field_validation_pending = false;
281
282 if (is_field_validation_pending)
283 {
284 is_field_validation_pending = false;
285 m_timer_workaround.fieldevents_filter_active = false;
286
287 // Check the field status and take action if field is lost.
288 nfct_field_event_handler(NRFX_NFC_FIELD_STATE_UNKNOWN);
289 return;
290 }
291
292 if ((m_timer_workaround.is_hfclk_on) && (m_timer_workaround.is_delayed))
293 {
294 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_ACTIVATE);
295 is_field_validation_pending = true;
296
297 // Start the timer second time to validate whether the tag has locked to the field.
298 nrfx_timer_clear(&m_timer_workaround.timer);
299 nrfx_timer_enable(&m_timer_workaround.timer);
300 }
301 }
302 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
303
304 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
305 /* Begin: Workaround for anomaly 116 */
nfct_reset(void)306 static inline void nfct_reset(void)
307 {
308 nrfy_nfct_parameters_t nfct_params;
309
310 // Save parameter settings before the reset of the NFCT peripheral.
311 nrfy_nfct_parameters_save(NRF_NFCT, &nfct_params);
312
313 // Reset the NFCT peripheral.
314 *(volatile uint32_t *)0x40005FFC = 0;
315 *(volatile uint32_t *)0x40005FFC;
316 *(volatile uint32_t *)0x40005FFC = 1;
317
318 // Restore parameter settings after the reset of the NFCT peripheral.
319 nrfy_nfct_parameters_restore(NRF_NFCT, &nfct_params);
320
321 // Restore general HW configuration.
322 nfct_hw_init_setup();
323
324 // Restore interrupts.
325 nrfy_nfct_int_enable(NRF_NFCT, nfct_params.int_enabled);
326
327 // Disable interrupts associated with data exchange.
328 nrfy_nfct_int_disable(NRF_NFCT, NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
329
330 NRFX_LOG_INFO("Reinitialize");
331 }
332 /* End: Workaround for anomaly 116 */
333
nfct_field_poll(void)334 static void nfct_field_poll(void)
335 {
336 if (!nrfx_nfct_field_check())
337 {
338 if (++m_timer_workaround.field_state_cnt > NRFX_NFCT_FIELDLOST_THR)
339 {
340 nrfx_nfct_evt_t nfct_evt =
341 {
342 .evt_id = NRFX_NFCT_EVT_FIELD_LOST,
343 };
344
345 nrfx_timer_disable(&m_timer_workaround.timer);
346 m_nfct_cb.field_on = false;
347
348 nfct_frame_delay_max_set(true);
349
350 /* Begin: Workaround for anomaly 116 */
351 /* resume the NFCT to initialized state */
352 nfct_reset();
353 /* End: Workaround for anomaly 116 */
354
355 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
356 }
357 return;
358 }
359
360 m_timer_workaround.field_state_cnt = 0;
361 }
362 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
363
nfct_field_timer_handler(nrf_timer_event_t event_type,void * p_context)364 static void nfct_field_timer_handler(nrf_timer_event_t event_type, void * p_context)
365 {
366 (void)p_context;
367
368 if (event_type != NRF_TIMER_EVENT_COMPARE0)
369 {
370 return;
371 }
372
373 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
374 m_timer_workaround.is_delayed = true;
375
376 nrfx_timer_disable(&m_timer_workaround.timer);
377 nfct_activate_check();
378 #elif NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
379 nfct_field_poll();
380 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
381 }
382
nfct_field_timer_config(uint8_t irq_priority)383 static inline nrfx_err_t nfct_field_timer_config(uint8_t irq_priority)
384 {
385 nrfx_err_t err_code;
386 nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG(FIELD_TIMER_FREQUENCY_HZ);
387 timer_cfg.interrupt_priority = irq_priority;
388
389 err_code = nrfx_timer_init(&m_timer_workaround.timer,
390 &timer_cfg,
391 nfct_field_timer_handler);
392 if (err_code != NRFX_SUCCESS)
393 {
394 return err_code;
395 }
396
397 nrfx_timer_extended_compare(&m_timer_workaround.timer,
398 NRF_TIMER_CC_CHANNEL0,
399 nrfx_timer_us_to_ticks(&m_timer_workaround.timer,
400 NRFX_NFCT_TIMER_PERIOD),
401 NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
402 true);
403 return err_code;
404 }
405 #endif // NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
406
407 static inline
nfct_nfcid1_size_to_sensres_size(uint8_t nfcid1_size)408 nrf_nfct_sensres_nfcid1_size_t nfct_nfcid1_size_to_sensres_size(uint8_t nfcid1_size)
409 {
410 switch (nfcid1_size)
411 {
412 case NRFX_NFCT_NFCID1_SINGLE_SIZE:
413 return NRF_NFCT_SENSRES_NFCID1_SIZE_SINGLE;
414
415 case NRFX_NFCT_NFCID1_DOUBLE_SIZE:
416 return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
417
418 case NRFX_NFCT_NFCID1_TRIPLE_SIZE:
419 return NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE;
420
421 default:
422 return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
423 }
424 }
425
nrfx_nfct_rxtx_int_enable(uint32_t rxtx_int_mask)426 static inline void nrfx_nfct_rxtx_int_enable(uint32_t rxtx_int_mask)
427 {
428 nrfy_nfct_int_enable(NRF_NFCT, rxtx_int_mask & m_nfct_cb.config.rxtx_int_mask);
429 }
430
nfct_stop_tx(void)431 static void nfct_stop_tx(void)
432 {
433 #if NRF_NFCT_HAS_STOPTX_TASK
434 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_STOPTX);
435 #else
436 #if defined(NRF52_SERIES)
437 *(volatile uint32_t *)0x40005010 = 0x01;
438 #elif defined(NRF5340_XXAA_APPLICATION) && defined(NRF_TRUSTZONE_NONSECURE)
439 *(volatile uint32_t *)0x4002D010 = 0x01;
440 #elif defined(NRF5340_XXAA_APPLICATION)
441 *(volatile uint32_t *)0x5002D010 = 0x01;
442 #endif
443 #endif // NRF_NFCT_HAS_STOPTX_TASK
444 }
445
nrfx_nfct_init(nrfx_nfct_config_t const * p_config)446 nrfx_err_t nrfx_nfct_init(nrfx_nfct_config_t const * p_config)
447 {
448 NRFX_ASSERT(p_config);
449
450 nrfx_err_t err_code = NRFX_SUCCESS;
451
452 if (m_nfct_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
453 {
454 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
455 err_code = NRFX_ERROR_ALREADY;
456 #else
457 err_code = NRFX_ERROR_INVALID_STATE;
458 #endif
459 NRFX_LOG_WARNING("Function: %s, error code: %s.",
460 __func__,
461 NRFX_LOG_ERROR_STRING_GET(err_code));
462 return err_code;
463 }
464
465 nfct_trims_apply();
466
467 #if NRFY_NFCT_HAS_PAD_CONFIG_REG
468 /* Make sure that NFC pads are configured as NFCT antenna pins. */
469 if (!nrfy_nfct_pad_config_enable_check(NRF_NFCT))
470 {
471 err_code = NRFX_ERROR_FORBIDDEN;
472 NRFX_LOG_WARNING("Function: %s, error code: %s.",
473 __func__,
474 NRFX_LOG_ERROR_STRING_GET(err_code));
475 NRFX_LOG_ERROR("NFCT pads are not configured as NFCT antenna pins");
476 return err_code;
477 }
478 #endif
479
480 m_nfct_cb.config = *p_config;
481 nfct_hw_init_setup();
482
483 nrfy_nfct_int_init(NRF_NFCT, p_config->rxtx_int_mask, p_config->irq_priority, false);
484
485 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
486 /* Initialize Timer module as the workaround for NFCT HW issues. */
487 err_code = nfct_field_timer_config(p_config->irq_priority);
488 #endif
489
490 m_nfct_cb.state = NRFX_DRV_STATE_INITIALIZED;
491 m_nfct_cb.field_on = false;
492 m_nfct_cb.frame_delay_max = NFCT_FRAMEDELAYMAX_DEFAULT;
493 m_nfct_cb.frame_delay_min = NFCT_FRAMEDELAYMIN_DEFAULT;
494
495 NRFX_LOG_INFO("Initialized.");
496 return err_code;
497 }
498
nrfx_nfct_uninit(void)499 void nrfx_nfct_uninit(void)
500 {
501 nrfx_nfct_disable();
502
503 nrfy_nfct_int_uninit(NRF_NFCT);
504
505 #if NRFX_CHECK(NFCT_WORKAROUND_USES_TIMER)
506 /* De-initialize Timer module as the workaround for NFCT HW issues. */
507 nrfx_timer_uninit(&m_timer_workaround.timer);
508 #endif
509
510 m_nfct_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
511 NRFX_LOG_INFO("Uninitialized.");
512 }
513
nrfx_nfct_init_check(void)514 bool nrfx_nfct_init_check(void)
515 {
516 return (m_nfct_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
517 }
518
nrfx_nfct_enable(void)519 void nrfx_nfct_enable(void)
520 {
521 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
522
523 nrfy_nfct_error_status_clear(NRF_NFCT, NRFX_NFCT_ERROR_STATUS_ALL_MASK);
524 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_SENSE);
525
526 nrfy_nfct_int_enable(NRF_NFCT, NRF_NFCT_INT_FIELDDETECTED_MASK |
527 NRF_NFCT_INT_ERROR_MASK |
528 NRF_NFCT_INT_SELECTED_MASK |
529 (NRFX_IS_ENABLED(USE_WORKAROUND_FOR_ANOMALY_79) ?
530 0 : NRF_NFCT_INT_FIELDLOST_MASK));
531
532 NRFX_LOG_INFO("Start");
533 }
534
nrfx_nfct_disable(void)535 void nrfx_nfct_disable(void)
536 {
537 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
538
539 nrfy_nfct_int_disable(NRF_NFCT, NRF_NFCT_DISABLE_ALL_INT);
540 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_DISABLE);
541
542 NRFX_LOG_INFO("Stop");
543 }
544
nrfx_nfct_field_check(void)545 bool nrfx_nfct_field_check(void)
546 {
547 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
548
549 uint32_t const field_state = nrfy_nfct_field_status_get(NRF_NFCT);
550
551 if (((field_state & NRF_NFCT_FIELD_STATE_PRESENT_MASK) == 0) &&
552 ((field_state & NRF_NFCT_FIELD_STATE_LOCK_MASK) == 0))
553 {
554 /* Field is not active */
555 return false;
556 }
557
558 return true;
559 }
560
nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_rx_data)561 nrfx_err_t nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_rx_data)
562 {
563 nrfx_err_t err;
564
565 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
566 NRFX_ASSERT(p_rx_data);
567
568 // EasyDMA requires that transfer buffers are placed in DataRAM,
569 // signal error if they are not.
570 if (!nrf_dma_accessible_check(NRF_NFCT, p_rx_data->p_data))
571 {
572 err = NRFX_ERROR_INVALID_ADDR;
573 NRFX_LOG_WARNING("Function: %s, error code: %s.",
574 __func__,
575 NRFX_LOG_ERROR_STRING_GET(err));
576 return err;
577 }
578
579 #if defined(__GNUC__)
580 #pragma GCC diagnostic push
581 #pragma GCC diagnostic ignored "-Wcast-qual"
582 #endif
583
584 nrfy_nfct_rxtx_buffer_set(NRF_NFCT,
585 (uint8_t *)p_rx_data->p_data,
586 (uint16_t)p_rx_data->data_size,
587 true);
588
589 #if defined(__GNUC__)
590 #pragma GCC diagnostic pop
591 #endif
592
593 nrfx_nfct_rxtx_int_enable(NRFX_NFCT_RX_INT_MASK);
594 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_ENABLERXDATA);
595
596 return NRFX_SUCCESS;
597 }
598
nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,nrf_nfct_frame_delay_mode_t delay_mode)599 nrfx_err_t nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,
600 nrf_nfct_frame_delay_mode_t delay_mode)
601 {
602 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
603 NRFX_ASSERT(p_tx_data);
604 NRFX_ASSERT(p_tx_data->p_data);
605
606 nrfx_err_t err = NRFX_SUCCESS;
607
608 if (p_tx_data->data_size == 0)
609 {
610 return NRFX_ERROR_INVALID_LENGTH;
611 }
612
613 // EasyDMA requires that transfer buffers are placed in DataRAM,
614 // signal error if they are not.
615 if (!nrf_dma_accessible_check(NRF_NFCT, p_tx_data->p_data))
616 {
617 err = NRFX_ERROR_INVALID_ADDR;
618 NRFX_LOG_WARNING("Function: %s, error code: %s.",
619 __func__,
620 NRFX_LOG_ERROR_STRING_GET(err));
621 return err;
622 }
623
624 NRFX_CRITICAL_SECTION_ENTER();
625
626 /* In case when NFC frame transmission has already started, it returns an error. */
627 if (nrfy_nfct_event_check(NRF_NFCT, NRF_NFCT_EVENT_TXFRAMESTART) &&
628 nrfy_nfct_int_enable_check(NRF_NFCT, NRF_NFCT_INT_TXFRAMESTART_MASK))
629 {
630 err = NRFX_ERROR_BUSY;
631 }
632 else
633 {
634 /* In case when Tx operation was scheduled with delay, stop scheduled Tx operation. */
635 nfct_stop_tx();
636
637 #if defined(__GNUC__)
638 #pragma GCC diagnostic push
639 #pragma GCC diagnostic ignored "-Wcast-qual"
640 #endif
641
642 nrfy_nfct_rxtx_buffer_set(NRF_NFCT,
643 (uint8_t *)p_tx_data->p_data,
644 (uint16_t)p_tx_data->data_size,
645 false);
646
647 #if defined(__GNUC__)
648 #pragma GCC diagnostic pop
649 #endif
650
651 nrfy_nfct_tx_bits_set(NRF_NFCT, (uint16_t)NRFX_NFCT_BYTES_TO_BITS(p_tx_data->data_size));
652 nrfy_nfct_frame_delay_mode_set(NRF_NFCT, (nrf_nfct_frame_delay_mode_t) delay_mode);
653 nfct_frame_delay_max_set(false);
654
655 nrfx_nfct_rxtx_int_enable(NRFX_NFCT_TX_INT_MASK);
656 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_STARTTX);
657 }
658
659 NRFX_CRITICAL_SECTION_EXIT();
660
661 if (err == NRFX_SUCCESS)
662 {
663 NRFX_LOG_INFO("Tx start");
664 }
665
666 return err;
667 }
668
nrfx_nfct_bits_tx(nrfx_nfct_data_desc_t const * p_tx_data,nrf_nfct_frame_delay_mode_t delay_mode)669 nrfx_err_t nrfx_nfct_bits_tx(nrfx_nfct_data_desc_t const * p_tx_data,
670 nrf_nfct_frame_delay_mode_t delay_mode)
671 {
672 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
673 NRFX_ASSERT(p_tx_data);
674 NRFX_ASSERT(p_tx_data->p_data);
675
676 nrfx_err_t err = NRFX_SUCCESS;
677
678 if (p_tx_data->data_size == 0)
679 {
680 return NRFX_ERROR_INVALID_LENGTH;
681 }
682
683 // EasyDMA requires that transfer buffers are placed in DataRAM,
684 // signal error if they are not.
685 if (!nrf_dma_accessible_check(NRF_NFCT, p_tx_data->p_data))
686 {
687 err = NRFX_ERROR_INVALID_ADDR;
688 NRFX_LOG_WARNING("Function: %s, error code: %s.",
689 __func__,
690 NRFX_LOG_ERROR_STRING_GET(err));
691 return err;
692 }
693
694 /* Get buffer length, add additional byte if bits go beyond last whole byte */
695 uint32_t buffer_length = NRFX_NFCT_BITS_TO_BYTES(p_tx_data->data_size);
696 if (p_tx_data->data_size & NFCT_TXD_AMOUNT_TXDATABITS_Msk)
697 {
698 ++buffer_length;
699 }
700
701 NRFX_CRITICAL_SECTION_ENTER();
702
703 /* In case when NFC frame transmission has already started, it returns an error. */
704 if (nrfy_nfct_event_check(NRF_NFCT, NRF_NFCT_EVENT_TXFRAMESTART) &&
705 nrfy_nfct_int_enable_check(NRF_NFCT, NRF_NFCT_INT_TXFRAMESTART_MASK))
706 {
707 err = NRFX_ERROR_BUSY;
708 }
709 else
710 {
711 /* In case when Tx operation was scheduled with delay, stop scheduled Tx operation. */
712 nfct_stop_tx();
713
714 #if defined(__GNUC__)
715 #pragma GCC diagnostic push
716 #pragma GCC diagnostic ignored "-Wcast-qual"
717 #endif
718
719 nrfy_nfct_rxtx_buffer_set(NRF_NFCT,
720 (uint8_t *)p_tx_data->p_data,
721 (uint16_t)buffer_length,
722 false);
723
724 #if defined(__GNUC__)
725 #pragma GCC diagnostic pop
726 #endif
727
728 nrfy_nfct_tx_bits_set(NRF_NFCT, (uint16_t)p_tx_data->data_size);
729 nrfy_nfct_frame_delay_mode_set(NRF_NFCT, (nrf_nfct_frame_delay_mode_t)delay_mode);
730 nfct_frame_delay_max_set(false);
731
732 nrfx_nfct_rxtx_int_enable(NRFX_NFCT_TX_INT_MASK);
733 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_STARTTX);
734 }
735
736 NRFX_CRITICAL_SECTION_EXIT();
737
738 if (err == NRFX_SUCCESS)
739 {
740 NRFX_LOG_INFO("Tx start");
741 }
742
743 return err;
744 }
745
nrfx_nfct_state_force(nrfx_nfct_state_t state)746 void nrfx_nfct_state_force(nrfx_nfct_state_t state)
747 {
748 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
749
750 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
751 if (state == NRFX_NFCT_STATE_ACTIVATED)
752 {
753 m_timer_workaround.is_hfclk_on = true;
754 /* NFCT will be activated based on additional conditions */
755 nfct_activate_check();
756 return;
757 }
758 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_190)
759 nrfy_nfct_task_trigger(NRF_NFCT, (nrf_nfct_task_t) state);
760 }
761
nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state)762 void nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state)
763 {
764 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
765
766 if (sub_state == NRFX_NFCT_ACTIVE_STATE_DEFAULT)
767 {
768 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
769 if (((*(uint32_t volatile *)(0x40005420)) & 0x1UL) == (1UL))
770 #else
771 if (nrfy_nfct_sleep_state_get(NRF_NFCT) == NRF_NFCT_SLEEP_STATE_SLEEP_A)
772 #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
773 {
774 // Default state is SLEEP_A
775 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_GOSLEEP);
776 }
777 else
778 {
779 // Default state is IDLE
780 nrfy_nfct_task_trigger(NRF_NFCT, NRF_NFCT_TASK_GOIDLE);
781 }
782 }
783 else
784 {
785 nrfy_nfct_task_trigger(NRF_NFCT, (nrf_nfct_task_t) sub_state);
786 }
787
788 nfct_frame_delay_max_set(true);
789
790 /* Disable TX/RX here (will be enabled at SELECTED) */
791 nrfy_nfct_int_disable(NRF_NFCT, NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
792 }
793
nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param)794 nrfx_err_t nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param)
795 {
796 NRFX_ASSERT(p_param);
797
798 switch (p_param->id)
799 {
800 case NRFX_NFCT_PARAM_ID_FDT:
801 {
802 uint32_t delay = p_param->data.fdt;
803 uint32_t delay_thr = NRF_NFCT_FRAME_DELAY_MAX_MAX_VALUE;
804 uint32_t delay_max;
805
806 delay_max = (delay > delay_thr) ? delay_thr : delay;
807 if (delay_max < m_nfct_cb.frame_delay_min)
808 {
809 return NRFX_ERROR_INVALID_PARAM;
810 }
811
812 m_nfct_cb.frame_delay_max = delay_max;
813 break;
814 }
815
816 case NRFX_NFCT_PARAM_ID_FDT_MIN:
817 {
818 uint32_t delay = p_param->data.fdt_min;
819 uint32_t delay_thr = NRF_NFCT_FRAME_DELAY_MAX_MAX_VALUE;
820 uint32_t delay_min;
821
822 delay_min = (delay > delay_thr) ? delay_thr : delay;
823 if (delay_min > m_nfct_cb.frame_delay_max)
824 {
825 return NRFX_ERROR_INVALID_PARAM;
826 }
827
828 m_nfct_cb.frame_delay_min = delay_min;
829 nrfy_nfct_frame_delay_min_set(NRF_NFCT, (uint16_t)m_nfct_cb.frame_delay_min);
830 break;
831 }
832
833 case NRFX_NFCT_PARAM_ID_SEL_RES:
834 if (p_param->data.sel_res_protocol > NRF_NFCT_SELRES_PROTOCOL_NFCDEP_T4AT)
835 {
836 return NRFX_ERROR_INVALID_PARAM;
837 }
838
839 nrfy_nfct_selres_protocol_set(NRF_NFCT,
840 (nrf_nfct_selres_protocol_t) p_param->data.sel_res_protocol);
841 break;
842
843 case NRFX_NFCT_PARAM_ID_NFCID1:
844 {
845 nrf_nfct_sensres_nfcid1_size_t id_size_mask;
846
847 id_size_mask = nfct_nfcid1_size_to_sensres_size(p_param->data.nfcid1.id_size);
848 nrfy_nfct_nfcid1_set(NRF_NFCT, p_param->data.nfcid1.p_id, id_size_mask);
849 break;
850 }
851
852 default:
853 break;
854 }
855
856 return NRFX_SUCCESS;
857 }
858
nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,uint32_t nfcid1_buff_len)859 nrfx_err_t nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,
860 uint32_t nfcid1_buff_len)
861 {
862 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
863 NRFX_ASSERT(p_nfcid1_buff);
864
865 uint32_t tag_header[3];
866
867 if ((nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE) &&
868 (nfcid1_buff_len != NRFX_NFCT_NFCID1_DOUBLE_SIZE) &&
869 (nfcid1_buff_len != NRFX_NFCT_NFCID1_TRIPLE_SIZE))
870 {
871 return NRFX_ERROR_INVALID_LENGTH;
872 }
873
874 #if (NRF_FICR_HAS_NFC_TAGHEADER || NRF_FICR_HAS_NFC_TAGHEADER_ARRAY) && \
875 !defined(NRF_TRUSTZONE_NONSECURE)
876 tag_header[0] = nrf_ficr_nfc_tagheader_get(NRF_FICR, 0);
877 tag_header[1] = nrf_ficr_nfc_tagheader_get(NRF_FICR, 1);
878 tag_header[2] = nrf_ficr_nfc_tagheader_get(NRF_FICR, 2);
879 #else
880 /* IC manufacturer ID byte, set to Nordic Semiconductor value. */
881 tag_header[0] = 0x5F;
882 tag_header[1] = 0;
883 tag_header[2] = 0;
884 #endif
885
886 p_nfcid1_buff[0] = (uint8_t) (tag_header[0] >> 0);
887 p_nfcid1_buff[1] = (uint8_t) (tag_header[0] >> 8);
888 p_nfcid1_buff[2] = (uint8_t) (tag_header[0] >> 16);
889 p_nfcid1_buff[3] = (uint8_t) (tag_header[1] >> 0);
890
891 if (nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE)
892 {
893 p_nfcid1_buff[4] = (uint8_t) (tag_header[1] >> 8);
894 p_nfcid1_buff[5] = (uint8_t) (tag_header[1] >> 16);
895 p_nfcid1_buff[6] = (uint8_t) (tag_header[1] >> 24);
896
897 if (nfcid1_buff_len == NRFX_NFCT_NFCID1_TRIPLE_SIZE)
898 {
899 p_nfcid1_buff[7] = (uint8_t) (tag_header[2] >> 0);
900 p_nfcid1_buff[8] = (uint8_t) (tag_header[2] >> 8);
901 p_nfcid1_buff[9] = (uint8_t) (tag_header[2] >> 16);
902 }
903 /* Begin: Workaround for anomaly 181. */
904 /* Workaround for wrong value in NFCID1. Value 0x88 cannot be used as byte 3
905 of a double-size NFCID1, according to the NFC Forum Digital Protocol specification. */
906 else if (p_nfcid1_buff[3] == 0x88)
907 {
908 p_nfcid1_buff[3] |= 0x11;
909 }
910 /* End: Workaround for anomaly 181 */
911 }
912
913 return NRFX_SUCCESS;
914 }
915
nrfx_nfct_autocolres_enable(void)916 void nrfx_nfct_autocolres_enable(void)
917 {
918 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
919
920 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
921 (*(uint32_t *)(0x4000559C)) &= (~(0x1UL));
922 #else
923 nrfy_nfct_autocolres_enable(NRF_NFCT);
924 #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
925 }
926
nrfx_nfct_autocolres_disable(void)927 void nrfx_nfct_autocolres_disable(void)
928 {
929 NRFX_ASSERT(m_nfct_cb.state == NRFX_DRV_STATE_INITIALIZED);
930
931 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
932 (*(uint32_t *)(0x4000559C)) |= (0x1UL);
933 #else
934 nrfy_nfct_autocolres_disable(NRF_NFCT);
935 #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
936 }
937
nrfx_nfct_irq_handler(void)938 void nrfx_nfct_irq_handler(void)
939 {
940 nrfx_nfct_field_state_t current_field = NRFX_NFC_FIELD_STATE_NONE;
941 uint32_t evt_mask = nrfy_nfct_events_process(NRF_NFCT,
942 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_FIELDDETECTED) |
943 (NRFX_IS_ENABLED(USE_WORKAROUND_FOR_ANOMALY_79) ? 0 :
944 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_FIELDLOST)) |
945 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_FIELDLOST) |
946 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_RXFRAMESTART) |
947 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_RXFRAMEEND) |
948 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_RXERROR) |
949 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_SELECTED) |
950 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_ERROR) |
951 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_TXFRAMESTART) |
952 NRFY_EVENT_TO_INT_BITMASK(NRF_NFCT_EVENT_TXFRAMEEND));
953
954 if (NRFX_NFCT_EVT_ACTIVE(FIELDDETECTED, evt_mask))
955 {
956 current_field = NRFX_NFC_FIELD_STATE_ON;
957
958 NRFX_LOG_DEBUG("Field detected");
959 }
960
961 #if !NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
962 if (NRFX_NFCT_EVT_ACTIVE(FIELDLOST, evt_mask))
963 {
964 current_field = (current_field == NRFX_NFC_FIELD_STATE_NONE) ?
965 NRFX_NFC_FIELD_STATE_OFF : NRFX_NFC_FIELD_STATE_UNKNOWN;
966
967 NRFX_LOG_DEBUG("Field lost");
968 }
969 #endif //!NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_79)
970
971 /* Perform actions if any FIELD event is active */
972 if (current_field != NRFX_NFC_FIELD_STATE_NONE)
973 {
974 nfct_field_event_handler(current_field);
975 }
976
977 if (NRFX_NFCT_EVT_ACTIVE(RXFRAMESTART, evt_mask))
978 {
979 nrfx_nfct_evt_t nfct_evt =
980 {
981 .evt_id = NRFX_NFCT_EVT_RX_FRAMESTART
982 };
983
984 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
985 }
986
987 if (NRFX_NFCT_EVT_ACTIVE(RXFRAMEEND, evt_mask))
988 {
989 nrfx_nfct_evt_t nfct_evt =
990 {
991 .evt_id = NRFX_NFCT_EVT_RX_FRAMEEND
992 };
993
994 /* Take into account only the number of whole bytes. */
995 nfct_evt.params.rx_frameend.rx_status = 0;
996 nfct_evt.params.rx_frameend.rx_data.p_data = nrfy_nfct_rxtx_buffer_get(NRF_NFCT);
997 nfct_evt.params.rx_frameend.rx_data.data_size =
998 NRFX_NFCT_BITS_TO_BYTES(nrfy_nfct_rx_bits_get(NRF_NFCT, true));
999
1000 if (NRFX_NFCT_EVT_ACTIVE(RXERROR, evt_mask))
1001 {
1002 nfct_evt.params.rx_frameend.rx_status =
1003 (nrfy_nfct_rx_frame_status_get(NRF_NFCT) & NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
1004
1005 NRFX_LOG_DEBUG("Rx error (0x%x)", (unsigned int) nfct_evt.params.rx_frameend.rx_status);
1006
1007 /* Clear rx frame status */
1008 nrfy_nfct_rx_frame_status_clear(NRF_NFCT, NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
1009 }
1010
1011 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
1012
1013 NRFX_LOG_DEBUG("Rx fend");
1014 }
1015
1016 if (NRFX_NFCT_EVT_ACTIVE(SELECTED, evt_mask))
1017 {
1018 /* Clear also RX END and RXERROR events because SW does not take care of
1019 commands that were received before selecting the tag. */
1020 nrfy_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_RXFRAMEEND);
1021 nrfy_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_RXERROR);
1022 nrfy_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_TXFRAMESTART);
1023 nrfy_nfct_event_clear(NRF_NFCT, NRF_NFCT_EVENT_TXFRAMEEND);
1024
1025 nfct_frame_delay_max_set(false);
1026
1027 /* At this point any previous error status can be ignored. */
1028 nrfy_nfct_rx_frame_status_clear(NRF_NFCT, NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
1029 nrfy_nfct_error_status_clear(NRF_NFCT, NRFX_NFCT_ERROR_STATUS_ALL_MASK);
1030
1031 nrfx_nfct_evt_t nfct_evt =
1032 {
1033 .evt_id = NRFX_NFCT_EVT_SELECTED
1034 };
1035 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
1036
1037 NRFX_LOG_DEBUG("Selected");
1038 }
1039
1040 if (NRFX_NFCT_EVT_ACTIVE(ERROR, evt_mask))
1041 {
1042 uint32_t err_status = nrfy_nfct_error_status_get(NRF_NFCT);
1043
1044 nrfx_nfct_evt_t nfct_evt =
1045 {
1046 .evt_id = NRFX_NFCT_EVT_ERROR
1047 };
1048
1049 /* Clear FRAMEDELAYTIMEOUT error (expected HW behaviour) when SLP_REQ command was received. */
1050 if (err_status & NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
1051 {
1052 nrfy_nfct_error_status_clear(NRF_NFCT, NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK);
1053
1054 nfct_evt.params.error.reason = NRFX_NFCT_ERROR_FRAMEDELAYTIMEOUT;
1055 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
1056 }
1057
1058 /* Report any other error. */
1059 err_status &= (uint32_t)~NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK;
1060 if (err_status)
1061 {
1062 NRFX_LOG_DEBUG("Error (0x%x)", (unsigned int) err_status);
1063 }
1064
1065 /* Clear error status. */
1066 nrfy_nfct_error_status_clear(NRF_NFCT, NRFX_NFCT_ERROR_STATUS_ALL_MASK);
1067 }
1068
1069 if (NRFX_NFCT_EVT_ACTIVE(TXFRAMESTART, evt_mask))
1070 {
1071 if (m_nfct_cb.config.cb != NULL)
1072 {
1073 nrfx_nfct_evt_t nfct_evt;
1074
1075 nfct_evt.evt_id = NRFX_NFCT_EVT_TX_FRAMESTART;
1076 nfct_evt.params.tx_framestart.tx_data.p_data = nrfy_nfct_rxtx_buffer_get(NRF_NFCT);
1077 nfct_evt.params.tx_framestart.tx_data.data_size =
1078 NRFX_NFCT_BITS_TO_BYTES(nrfy_nfct_tx_bits_get(NRF_NFCT));
1079
1080 m_nfct_cb.config.cb(&nfct_evt);
1081 }
1082 }
1083
1084 if (NRFX_NFCT_EVT_ACTIVE(TXFRAMEEND, evt_mask))
1085 {
1086 nrfx_nfct_evt_t nfct_evt =
1087 {
1088 .evt_id = NRFX_NFCT_EVT_TX_FRAMEEND
1089 };
1090
1091 /* Ignore any frame transmission until a new TX is scheduled by nrfx_nfct_tx() */
1092 nrfy_nfct_int_disable(NRF_NFCT, NRFX_NFCT_TX_INT_MASK);
1093
1094 NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
1095
1096 NRFX_LOG_DEBUG("Tx fend");
1097 }
1098 }
1099
1100 #endif // NRFX_CHECK(NRFX_NFCT_ENABLED)
1101