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