ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
nrfx_nfct.c
Go to the documentation of this file.
1 
41 #include <nrfx.h>
42 
43 #if NRFX_CHECK(NRFX_NFCT_ENABLED)
44 
45 #include <nrfx_nfct.h>
46 
47 #define NRFX_LOG_MODULE NFCT
48 #include <nrfx_log.h>
49 
50 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \
51  defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
52 #define USE_TIMER_WORKAROUND
53 #endif
54 
55 #if defined(USE_TIMER_WORKAROUND)
56 #include <nrfx_timer.h>
57 
58 typedef struct
59 {
60  const nrfx_timer_t timer;
61 #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
62  bool fieldevents_filter_active;
63  bool is_hfclk_on;
64  bool is_delayed;
65 #else
66  uint32_t field_state_cnt;
67 #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
68 } nrfx_nfct_timer_workaround_t;
69 
70 #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
71  #define NRFX_NFCT_ACTIVATE_DELAY 1000
72  #define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_ACTIVATE_DELAY
73 #else
74  #define NRFX_NFCT_FIELDLOST_THR 7
75  #define NRFX_NFCT_FIELD_TIMER_PERIOD 100
76  #define NRFX_NFCT_TIMER_PERIOD NRFX_NFCT_FIELD_TIMER_PERIOD
77 #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
78 #define NRFX_NFCT_TIMER_INSTANCE 4
80 static nrfx_nfct_timer_workaround_t m_timer_workaround =
81 {
82  .timer = NRFX_TIMER_INSTANCE(NRFX_NFCT_TIMER_INSTANCE),
83 };
84 #endif // defined(USE_TIMER_WORKAROUND)
85 
86 #define NRFX_NFCT_FWT_MAX_DIFF 1u
87 #define NFCT_FRAMEDELAYMAX_DEFAULT (0x00001000UL)
89 /* Mask of all possible interrupts that are relevant for data reception. */
90 #define NRFX_NFCT_RX_INT_MASK (NRF_NFCT_INT_RXFRAMESTART_MASK | \
91  NRF_NFCT_INT_RXFRAMEEND_MASK | \
92  NRF_NFCT_INT_RXERROR_MASK)
93 
94 /* Mask of all possible interrupts that are relevant for data transmission. */
95 #define NRFX_NFCT_TX_INT_MASK (NRF_NFCT_INT_TXFRAMESTART_MASK | \
96  NRF_NFCT_INT_TXFRAMEEND_MASK)
97 
98 
99 /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_RXERROR event. */
100 #define NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK (NRF_NFCT_RX_FRAME_STATUS_CRC_MASK | \
101  NRF_NFCT_RX_FRAME_STATUS_PARITY_MASK | \
102  NRF_NFCT_RX_FRAME_STATUS_OVERRUN_MASK)
103 
104 /* Mask of all possible errors from the @ref NRF_NFCT_EVENT_ERROR event. */
105 #if defined (NRF52832_XXAA) || defined(NRF52832_XXAB)
106 #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK | \
107  NRF_NFCT_ERROR_NFCFIELDTOOSTRONG_MASK | \
108  NRF_NFCT_ERROR_NFCFIELDTOOWEAK_MASK)
109 #else
110 #define NRFX_NFCT_ERROR_STATUS_ALL_MASK (NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
111 #endif
112 
113 /* Macros for conversion of bits to bytes. */
114 #define NRFX_NFCT_BYTES_TO_BITS(_bytes) ((_bytes) << 3)
115 #define NRFX_NFCT_BITS_TO_BYTES(_bits) ((_bits) >> 3)
116 
117 /* Macro for checking whether the NFCT interrupt is active. */
118 #define NRFX_NFCT_EVT_ACTIVE(_name) (nrf_nfct_event_check(NRFX_CONCAT_2(NRF_NFCT_EVENT_, _name)) && \
119  nrf_nfct_int_enable_check(NRFX_CONCAT_3(NRF_NFCT_INT_, _name, _MASK)))
120 
121 /* Macro for callback execution. */
122 #define NRFX_NFCT_CB_HANDLE(_cb, _evt) \
123  if (_cb != NULL) \
124  { \
125  _cb(&_evt); \
126  }
127 
128 typedef enum
129 {
130  NRFX_NFC_FIELD_STATE_NONE,
131  NRFX_NFC_FIELD_STATE_OFF,
132  NRFX_NFC_FIELD_STATE_ON,
133  NRFX_NFC_FIELD_STATE_UNKNOWN
134 } nrfx_nfct_field_state_t;
135 
137 typedef struct
138 {
139  nrfx_nfct_config_t config;
140  nrfx_drv_state_t state;
141  volatile bool field_on;
142  uint32_t frame_delay_max;
143 } nrfx_nfct_control_block_t;
144 
145 static nrfx_nfct_control_block_t m_nfct_cb;
146 
150 static void nrfx_nfct_hw_init_setup(void)
151 {
152  // Use Window Grid frame delay mode.
153  nrf_nfct_frame_delay_mode_set(NRF_NFCT_FRAME_DELAY_MODE_WINDOWGRID);
154 
155  /* Begin: Workaround for anomaly 25 */
156  /* Workaround for wrong SENSRES values require using SDD00001, but here SDD00100 is used
157  because it is required to operate with Windows Phone */
158  nrf_nfct_sensres_bit_frame_sdd_set(NRF_NFCT_SENSRES_BIT_FRAME_SDD_00100);
159  /* End: Workaround for anomaly 25 */
160 }
161 
162 static void nrfx_nfct_frame_delay_max_set(bool default_delay)
163 {
164  if (default_delay)
165  {
166  nrf_nfct_frame_delay_max_set(NFCT_FRAMEDELAYMAX_DEFAULT);
167  }
168  else
169  {
170  nrf_nfct_frame_delay_max_set(m_nfct_cb.frame_delay_max);
171  }
172 }
173 
178 static void nrfx_nfct_field_event_handler(volatile nrfx_nfct_field_state_t field_state)
179 {
180  nrfx_nfct_evt_t nfct_evt;
181 
182 #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
183  if(m_timer_workaround.fieldevents_filter_active)
184  {
185  return;
186  }
187 #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
188 
189  if (field_state == NRFX_NFC_FIELD_STATE_UNKNOWN)
190  {
191  /* Probe NFC field */
192  field_state = (nrfx_nfct_field_check()) ? NRFX_NFC_FIELD_STATE_ON : NRFX_NFC_FIELD_STATE_OFF;
193  }
194 
195  /* Field event service. Only take action on field transition -
196  * based on the value of m_nfct_cb.field_on
197  */
198  switch (field_state)
199  {
200  case NRFX_NFC_FIELD_STATE_ON:
201  if (!m_nfct_cb.field_on)
202  {
203 #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
204  /* Begin: Workaround for anomaly 190 */
205  m_timer_workaround.is_hfclk_on = false;
206  m_timer_workaround.is_delayed = false;
207  m_timer_workaround.fieldevents_filter_active = true;
208 
209  nrfx_timer_clear(&m_timer_workaround.timer);
210  nrfx_timer_enable(&m_timer_workaround.timer);
211  /* End: Workaround for anomaly 190 */
212 #elif defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
213  nrfx_timer_clear(&m_timer_workaround.timer);
214  nrfx_timer_enable(&m_timer_workaround.timer);
215  m_timer_workaround.field_state_cnt = 0;
216 #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
217 
218  m_nfct_cb.field_on = true;
219  nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_DETECTED;
220  NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
221  }
222  break;
223 
224  case NRFX_NFC_FIELD_STATE_OFF:
225  if (m_nfct_cb.field_on)
226  {
227  nrf_nfct_task_trigger(NRF_NFCT_TASK_SENSE);
228  nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
229  m_nfct_cb.field_on = false;
230  nfct_evt.evt_id = NRFX_NFCT_EVT_FIELD_LOST;
231 
232  /* Begin: Workaround for anomaly 218 */
233  nrfx_nfct_frame_delay_max_set(true);
234  /* End: Workaround for anomaly 218 */
235 
236  NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
237  }
238  break;
239 
240  default:
241  /* No implementation required */
242  break;
243  }
244 }
245 
246 #if defined(USE_TIMER_WORKAROUND)
247 
248 #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
249 static void nrfx_nfct_activate_check(void)
250 {
251  static bool is_field_validation_pending = false;
252 
253  if (is_field_validation_pending)
254  {
255  is_field_validation_pending = false;
256  m_timer_workaround.fieldevents_filter_active = false;
257 
258  // Check the field status and take action if field is lost.
259  nrfx_nfct_field_event_handler(NRFX_NFC_FIELD_STATE_UNKNOWN);
260  return;
261  }
262 
263  if ((m_timer_workaround.is_hfclk_on) && (m_timer_workaround.is_delayed))
264  {
265  nrf_nfct_task_trigger(NRF_NFCT_TASK_ACTIVATE);
266  is_field_validation_pending = true;
267 
268  // Start the timer second time to validate whether the tag has locked to the field.
269  nrfx_timer_clear(&m_timer_workaround.timer);
270  nrfx_timer_enable(&m_timer_workaround.timer);
271  }
272 }
273 #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
274 
275 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
276 /* Begin: Workaround for anomaly 116 */
277 static inline void nrfx_nfct_reset(void)
278 {
279  uint32_t fdm;
280  uint32_t int_enabled;
281  uint8_t nfcid1[NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE];
282  nrf_nfct_sensres_nfcid1_size_t nfcid1_size;
283  nrf_nfct_selres_protocol_t protocol;
284 
285  // Save parameter settings before the reset of the NFCT peripheral.
286  fdm = nrf_nfct_frame_delay_max_get();
287  nfcid1_size = nrf_nfct_nfcid1_get(nfcid1);
288  protocol = nrf_nfct_selsres_protocol_get();
289  int_enabled = nrf_nfct_int_enable_get();
290 
291  // Reset the NFCT peripheral.
292  *(volatile uint32_t *)0x40005FFC = 0;
293  *(volatile uint32_t *)0x40005FFC;
294  *(volatile uint32_t *)0x40005FFC = 1;
295 
296  // Restore parameter settings after the reset of the NFCT peripheral.
297  nrf_nfct_frame_delay_max_set(fdm);
298  nrf_nfct_nfcid1_set(nfcid1, nfcid1_size);
299  nrf_nfct_selres_protocol_set(protocol);
300 
301  // Restore general HW configuration.
302  nrfx_nfct_hw_init_setup();
303 
304  // Restore interrupts.
305  nrf_nfct_int_enable(int_enabled);
306 
307  // Disable interrupts associated with data exchange.
308  nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
309 
310  NRFX_LOG_INFO("Reinitialize");
311 }
312 /* End: Workaround for anomaly 116 */
313 
314 static void nrfx_nfct_field_poll(void)
315 {
316  if (!nrfx_nfct_field_check())
317  {
318  if (++m_timer_workaround.field_state_cnt > NRFX_NFCT_FIELDLOST_THR)
319  {
320  nrfx_nfct_evt_t nfct_evt =
321  {
322  .evt_id = NRFX_NFCT_EVT_FIELD_LOST,
323  };
324 
325  nrfx_timer_disable(&m_timer_workaround.timer);
326  m_nfct_cb.field_on = false;
327 
328  /* Begin: Workaround for anomaly 218 */
329  nrfx_nfct_frame_delay_max_set(true);
330  /* End: Workaround for anomaly 218 */
331 
332  /* Begin: Workaround for anomaly 116 */
333  /* resume the NFCT to initialized state */
334  nrfx_nfct_reset();
335  /* End: Workaround for anomaly 116 */
336 
337  NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
338  }
339  return;
340  }
341 
342  m_timer_workaround.field_state_cnt = 0;
343 }
344 #endif // defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
345 
346 static void nrfx_nfct_field_timer_handler(nrf_timer_event_t event_type, void * p_context)
347 {
348  (void)p_context;
349 
350  if (event_type != NRF_TIMER_EVENT_COMPARE0)
351  {
352  return;
353  }
354 
355 #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
356  m_timer_workaround.is_delayed = true;
357 
358  nrfx_timer_disable(&m_timer_workaround.timer);
359  nrfx_nfct_activate_check();
360 #else
361  nrfx_nfct_field_poll();
362 #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
363 }
364 
365 static inline nrfx_err_t nrfx_nfct_field_timer_config(void)
366 {
367  nrfx_err_t err_code;
368  nrfx_timer_config_t timer_cfg =
369  {
370  .frequency = NRF_TIMER_FREQ_1MHz,
371  .mode = NRF_TIMER_MODE_TIMER,
372  .bit_width = NRF_TIMER_BIT_WIDTH_16,
373  .interrupt_priority = NRFX_NFCT_CONFIG_IRQ_PRIORITY
374  };
375 
376  err_code = nrfx_timer_init(&m_timer_workaround.timer, &timer_cfg, nrfx_nfct_field_timer_handler);
377  if (err_code != NRFX_SUCCESS)
378  {
379  return err_code;
380  }
381 
382  nrfx_timer_extended_compare(&m_timer_workaround.timer,
383  NRF_TIMER_CC_CHANNEL0,
384  nrfx_timer_us_to_ticks(&m_timer_workaround.timer, NRFX_NFCT_TIMER_PERIOD),
385  NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
386  true);
387  return err_code;
388 }
389 #endif // defined(USE_TIMER_WORKAROUND)
390 
391 static inline nrf_nfct_sensres_nfcid1_size_t nrf_nfct_nfcid1_size_to_sensres_size(uint8_t nfcid1_size)
392 {
393  switch (nfcid1_size)
394  {
395  case NRFX_NFCT_NFCID1_SINGLE_SIZE:
396  return NRF_NFCT_SENSRES_NFCID1_SIZE_SINGLE;
397 
398  case NRFX_NFCT_NFCID1_DOUBLE_SIZE:
399  return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
400 
401  case NRFX_NFCT_NFCID1_TRIPLE_SIZE:
402  return NRF_NFCT_SENSRES_NFCID1_SIZE_TRIPLE;
403 
404  default:
405  return NRF_NFCT_SENSRES_NFCID1_SIZE_DOUBLE;
406  }
407 }
408 
409 static inline void nrfx_nfct_rxtx_int_enable(uint32_t rxtx_int_mask)
410 {
411  nrf_nfct_int_enable(rxtx_int_mask & m_nfct_cb.config.rxtx_int_mask);
412 }
413 
414 nrfx_err_t nrfx_nfct_init(nrfx_nfct_config_t const * p_config)
415 {
416  NRFX_ASSERT(p_config);
417 
418  nrfx_err_t err_code = NRFX_SUCCESS;
419 
420  if (m_nfct_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
421  {
422  return NRFX_ERROR_INVALID_STATE;
423  }
424 
425  m_nfct_cb.config = *p_config;
426  nrfx_nfct_hw_init_setup();
427 
428  NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
429  NRFX_IRQ_PRIORITY_SET(NFCT_IRQn, NRFX_NFCT_CONFIG_IRQ_PRIORITY);
430  NRFX_IRQ_ENABLE(NFCT_IRQn);
431 
432 #if defined(USE_TIMER_WORKAROUND)
433  /* Initialize Timer module as the workaround for NFCT HW issues. */
434  err_code = nrfx_nfct_field_timer_config();
435 #endif // defined(USE_TIMER_WORKAROUND)
436 
437  if (err_code == NRFX_SUCCESS)
438  {
439  uint8_t default_nfcid1[NRFX_NFCT_NFCID1_DEFAULT_LEN];
440  err_code = nrfx_nfct_nfcid1_default_bytes_get(default_nfcid1, sizeof(default_nfcid1));
441  NRFX_ASSERT(err_code == NRFX_SUCCESS);
442  nrf_nfct_nfcid1_set(default_nfcid1, NRF_NFCT_SENSRES_NFCID1_SIZE_DEFAULT);
443  }
444  else
445  {
446  return err_code;
447  }
448 
449  m_nfct_cb.state = NRFX_DRV_STATE_INITIALIZED;
450  m_nfct_cb.frame_delay_max = NFCT_FRAMEDELAYMAX_DEFAULT;
451 
452  NRFX_LOG_INFO("Initialized");
453  return err_code;
454 }
455 
456 void nrfx_nfct_uninit(void)
457 {
458  nrfx_nfct_disable();
459 
460  NRFX_IRQ_DISABLE(NFCT_IRQn);
461  NRFX_IRQ_PENDING_CLEAR(NFCT_IRQn);
462 
463 #if defined(USE_TIMER_WORKAROUND)
464  /* De-initialize Timer module as the workaround for NFCT HW issues. */
465  nrfx_timer_uninit(&m_timer_workaround.timer);
466 #endif // defined(USE_TIMER_WORKAROUND)
467 
468  m_nfct_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
469 }
470 
471 void nrfx_nfct_enable(void)
472 {
473  nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
474  nrf_nfct_task_trigger(NRF_NFCT_TASK_SENSE);
475 
476  nrf_nfct_int_enable(NRF_NFCT_INT_FIELDDETECTED_MASK | NRF_NFCT_INT_ERROR_MASK |
477  NRF_NFCT_INT_SELECTED_MASK);
478 #if !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
479  nrf_nfct_int_enable(NRF_NFCT_INT_FIELDLOST_MASK);
480 #endif // !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
481 
482  NRFX_LOG_INFO("Start");
483 }
484 
485 void nrfx_nfct_disable(void)
486 {
487  nrf_nfct_int_disable(NRF_NFCT_DISABLE_ALL_INT);
488  nrf_nfct_task_trigger(NRF_NFCT_TASK_DISABLE);
489 
490  NRFX_LOG_INFO("Stop");
491 }
492 
493 bool nrfx_nfct_field_check(void)
494 {
495  uint32_t const field_state = nrf_nfct_field_status_get();
496 
497  if (((field_state & NRF_NFCT_FIELD_STATE_PRESENT_MASK) == 0) &&
498  ((field_state & NRF_NFCT_FIELD_STATE_LOCK_MASK) == 0))
499  {
500  /* Field is not active */
501  return false;
502  }
503 
504  return true;
505 }
506 
507 void nrfx_nfct_rx(nrfx_nfct_data_desc_t const * p_tx_data)
508 {
509  NRFX_ASSERT(p_tx_data);
510 
511  nrf_nfct_rxtx_buffer_set((uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
512 
513  nrfx_nfct_rxtx_int_enable(NRFX_NFCT_RX_INT_MASK);
514  nrf_nfct_task_trigger(NRF_NFCT_TASK_ENABLERXDATA);
515 }
516 
517 nrfx_err_t nrfx_nfct_tx(nrfx_nfct_data_desc_t const * p_tx_data,
518  nrf_nfct_frame_delay_mode_t delay_mode)
519 {
520  NRFX_ASSERT(p_tx_data);
521  NRFX_ASSERT(p_tx_data->p_data);
522 
523  if (p_tx_data->data_size == 0)
524  {
525  return NRFX_ERROR_INVALID_LENGTH;
526  }
527 
528  nrf_nfct_rxtx_buffer_set((uint8_t *) p_tx_data->p_data, p_tx_data->data_size);
529  nrf_nfct_tx_bits_set(NRFX_NFCT_BYTES_TO_BITS(p_tx_data->data_size));
530  nrf_nfct_frame_delay_mode_set((nrf_nfct_frame_delay_mode_t) delay_mode);
531 
532  nrfx_nfct_rxtx_int_enable(NRFX_NFCT_TX_INT_MASK);
533  nrf_nfct_task_trigger(NRF_NFCT_TASK_STARTTX);
534 
535  NRFX_LOG_INFO("Tx start");
536  return NRFX_SUCCESS;
537 }
538 
539 void nrfx_nfct_state_force(nrfx_nfct_state_t state)
540 {
541 #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
542  if (state == NRFX_NFCT_STATE_ACTIVATED)
543  {
544  m_timer_workaround.is_hfclk_on = true;
545  /* NFCT will be activated based on additional conditions */
546  nrfx_nfct_activate_check();
547  return;
548  }
549 #endif // defined(NRF52833_XXAA) || defined(NRF52840_XXAA)
550  nrf_nfct_task_trigger((nrf_nfct_task_t) state);
551 }
552 
553 void nrfx_nfct_init_substate_force(nrfx_nfct_active_state_t sub_state)
554 {
555  if (sub_state == NRFX_NFCT_ACTIVE_STATE_DEFAULT)
556  {
557 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
558  if (((*(uint32_t volatile *)(0x40005420)) & 0x1UL) == (1UL))
559 #else
560  if (nrf_nfct_sleep_state_get() == NRF_NFCT_SLEEP_STATE_SLEEP_A)
561 #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
562  {
563  // Default state is SLEEP_A
564  nrf_nfct_task_trigger(NRF_NFCT_TASK_GOSLEEP);
565  }
566  else
567  {
568  // Default state is IDLE
569  nrf_nfct_task_trigger(NRF_NFCT_TASK_GOIDLE);
570  }
571  }
572  else
573  {
574  nrf_nfct_task_trigger((nrf_nfct_task_t) sub_state);
575  }
576 
577  /* Begin: Workaround for anomaly 218 */
578  nrfx_nfct_frame_delay_max_set(true);
579  /* End: Workaround for anomaly 218 */
580 
581  /* Disable TX/RX here (will be enabled at SELECTED) */
582  nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK);
583 }
584 
585 nrfx_err_t nrfx_nfct_parameter_set(nrfx_nfct_param_t const * p_param)
586 {
587  NRFX_ASSERT(p_param);
588 
589  switch (p_param->id)
590  {
591  case NRFX_NFCT_PARAM_ID_FDT:
592  {
593  uint32_t delay = p_param->data.fdt;
594  uint32_t delay_thr = NFCT_FRAMEDELAYMAX_FRAMEDELAYMAX_Msk;
595 
596  // Delay validation.
597  if (delay > (delay_thr + NRFX_NFCT_FWT_MAX_DIFF))
598  {
599  return NRFX_ERROR_INVALID_PARAM;
600  }
601 
602  delay = (delay > delay_thr) ? delay_thr : delay;
603  m_nfct_cb.frame_delay_max = delay;
604  break;
605  }
606 
607  case NRFX_NFCT_PARAM_ID_SEL_RES:
608  if (p_param->data.sel_res_protocol > NRF_NFCT_SELRES_PROTOCOL_NFCDEP_T4AT)
609  {
610  return NRFX_ERROR_INVALID_PARAM;
611  }
612 
613  nrf_nfct_selres_protocol_set((nrf_nfct_selres_protocol_t) p_param->data.sel_res_protocol);
614  break;
615 
616  case NRFX_NFCT_PARAM_ID_NFCID1:
617  {
618  nrf_nfct_sensres_nfcid1_size_t id_size_mask;
619 
620  id_size_mask = nrf_nfct_nfcid1_size_to_sensres_size(p_param->data.nfcid1.id_size);
621  nrf_nfct_nfcid1_set(p_param->data.nfcid1.p_id, id_size_mask);
622  break;
623  }
624 
625  default:
626  break;
627  }
628 
629  return NRFX_SUCCESS;
630 }
631 
632 nrfx_err_t nrfx_nfct_nfcid1_default_bytes_get(uint8_t * const p_nfcid1_buff,
633  uint32_t nfcid1_buff_len)
634 {
635  if ((nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE) &&
636  (nfcid1_buff_len != NRFX_NFCT_NFCID1_DOUBLE_SIZE) &&
637  (nfcid1_buff_len != NRFX_NFCT_NFCID1_TRIPLE_SIZE))
638  {
639  return NRFX_ERROR_INVALID_LENGTH;
640  }
641 
642  uint32_t nfc_tag_header0 = NRF_FICR->NFC.TAGHEADER0;
643  uint32_t nfc_tag_header1 = NRF_FICR->NFC.TAGHEADER1;
644  uint32_t nfc_tag_header2 = NRF_FICR->NFC.TAGHEADER2;
645 
646  p_nfcid1_buff[0] = (uint8_t) (nfc_tag_header0 >> 0);
647  p_nfcid1_buff[1] = (uint8_t) (nfc_tag_header0 >> 8);
648  p_nfcid1_buff[2] = (uint8_t) (nfc_tag_header0 >> 16);
649  p_nfcid1_buff[3] = (uint8_t) (nfc_tag_header1 >> 0);
650 
651  if (nfcid1_buff_len != NRFX_NFCT_NFCID1_SINGLE_SIZE)
652  {
653  p_nfcid1_buff[4] = (uint8_t) (nfc_tag_header1 >> 8);
654  p_nfcid1_buff[5] = (uint8_t) (nfc_tag_header1 >> 16);
655  p_nfcid1_buff[6] = (uint8_t) (nfc_tag_header1 >> 24);
656 
657  if (nfcid1_buff_len == NRFX_NFCT_NFCID1_TRIPLE_SIZE)
658  {
659  p_nfcid1_buff[7] = (uint8_t) (nfc_tag_header2 >> 0);
660  p_nfcid1_buff[8] = (uint8_t) (nfc_tag_header2 >> 8);
661  p_nfcid1_buff[9] = (uint8_t) (nfc_tag_header2 >> 16);
662  }
663  /* Begin: Workaround for anomaly 181. */
664  /* Workaround for wrong value in NFCID1. Value 0x88 cannot be used as byte 3
665  of a double-size NFCID1, according to the NFC Forum Digital Protocol specification. */
666  else if (p_nfcid1_buff[3] == 0x88)
667  {
668  p_nfcid1_buff[3] |= 0x11;
669  }
670  /* End: Workaround for anomaly 181 */
671  }
672 
673  return NRFX_SUCCESS;
674 }
675 
676 void nrfx_nfct_autocolres_enable(void)
677 {
678 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
679  (*(uint32_t *)(0x4000559C)) &= (~(0x1UL));
680 #else
681  nrf_nfct_autocolres_enable();
682 #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
683 }
684 
685 void nrfx_nfct_autocolres_disable(void)
686 {
687 #if defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
688  (*(uint32_t *)(0x4000559C)) |= (0x1UL);
689 #else
690  nrf_nfct_autocolres_disable();
691 #endif //defined(NRF52832_XXAA) || defined(NRF52832_XXAB)
692 }
693 
694 void nrfx_nfct_irq_handler(void)
695 {
696  nrfx_nfct_field_state_t current_field = NRFX_NFC_FIELD_STATE_NONE;
697 
698  if (NRFX_NFCT_EVT_ACTIVE(FIELDDETECTED))
699  {
700  nrf_nfct_event_clear(NRF_NFCT_EVENT_FIELDDETECTED);
701  current_field = NRFX_NFC_FIELD_STATE_ON;
702 
703  NRFX_LOG_DEBUG("Field detected");
704  }
705 
706 #if !defined(NRF52832_XXAA) && !defined(NRF52832_XXAB)
707  if (NRFX_NFCT_EVT_ACTIVE(FIELDLOST))
708  {
709  nrf_nfct_event_clear(NRF_NFCT_EVENT_FIELDLOST);
710  current_field = (current_field == NRFX_NFC_FIELD_STATE_NONE) ?
711  NRFX_NFC_FIELD_STATE_OFF : NRFX_NFC_FIELD_STATE_UNKNOWN;
712 
713  NRFX_LOG_DEBUG("Field lost");
714  }
715 #endif
716 
717  /* Perform actions if any FIELD event is active */
718  if (current_field != NRFX_NFC_FIELD_STATE_NONE)
719  {
720  nrfx_nfct_field_event_handler(current_field);
721  }
722 
723  if (NRFX_NFCT_EVT_ACTIVE(RXFRAMEEND))
724  {
725  nrf_nfct_event_clear(NRF_NFCT_EVENT_RXFRAMEEND);
726 
727  nrfx_nfct_evt_t nfct_evt =
728  {
729  .evt_id = NRFX_NFCT_EVT_RX_FRAMEEND
730  };
731 
732  /* Take into account only the number of whole bytes. */
733  nfct_evt.params.rx_frameend.rx_status = 0;
734  nfct_evt.params.rx_frameend.rx_data.p_data = nrf_nfct_rxtx_buffer_get();
735  nfct_evt.params.rx_frameend.rx_data.data_size = NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_rx_bits_get(true));
736 
737  if (NRFX_NFCT_EVT_ACTIVE(RXERROR))
738  {
739  nfct_evt.params.rx_frameend.rx_status =
740  (nrf_nfct_rx_frame_status_get() & NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
741  nrf_nfct_event_clear(NRF_NFCT_EVENT_RXERROR);
742 
743  NRFX_LOG_DEBUG("Rx error (0x%x)", (unsigned int) nfct_evt.params.rx_frameend.rx_status);
744 
745  /* Clear rx frame status */
746  nrf_nfct_rx_frame_status_clear(NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
747  }
748 
749  NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
750 
751  /* Clear TXFRAMESTART EVENT so it can be checked in hal_nfc_send */
752  nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
753 
754  NRFX_LOG_DEBUG("Rx fend");
755  }
756 
757  if (NRFX_NFCT_EVT_ACTIVE(TXFRAMEEND))
758  {
759  nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMEEND);
760 
761  nrfx_nfct_evt_t nfct_evt =
762  {
763  .evt_id = NRFX_NFCT_EVT_TX_FRAMEEND
764  };
765 
766  /* Disable TX END event to ignore frame transmission other than READ response */
767  nrf_nfct_int_disable(NRFX_NFCT_TX_INT_MASK);
768 
769  NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
770 
771  NRFX_LOG_DEBUG("Tx fend");
772  }
773 
774  if (NRFX_NFCT_EVT_ACTIVE(SELECTED))
775  {
776  nrf_nfct_event_clear(NRF_NFCT_EVENT_SELECTED);
777  /* Clear also RX END and RXERROR events because SW does not take care of
778  commands that were received before selecting the tag. */
779  nrf_nfct_event_clear(NRF_NFCT_EVENT_RXFRAMEEND);
780  nrf_nfct_event_clear(NRF_NFCT_EVENT_RXERROR);
781  nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
782  nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMEEND);
783 
784  /* Begin: Workaround for anomaly 218 */
785  nrfx_nfct_frame_delay_max_set(false);
786  /* End: Workaround for anomaly 218 */
787 
788  /* At this point any previous error status can be ignored. */
789  nrf_nfct_rx_frame_status_clear(NRFX_NFCT_FRAME_STATUS_RX_ALL_MASK);
790  nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
791 
792  nrfx_nfct_evt_t nfct_evt =
793  {
794  .evt_id = NRFX_NFCT_EVT_SELECTED
795  };
796  NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
797 
798  NRFX_LOG_DEBUG("Selected");
799  }
800 
801  if (NRFX_NFCT_EVT_ACTIVE(ERROR))
802  {
803  uint32_t err_status = nrf_nfct_error_status_get();
804  nrf_nfct_event_clear(NRF_NFCT_EVENT_ERROR);
805 
806  nrfx_nfct_evt_t nfct_evt =
807  {
808  .evt_id = NRFX_NFCT_EVT_ERROR
809  };
810 
811  /* Clear FRAMEDELAYTIMEOUT error (expected HW behaviour) when SLP_REQ command was received. */
812  if (err_status & NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK)
813  {
814  nrf_nfct_error_status_clear(NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK);
815 
816  nfct_evt.params.error.reason = NRFX_NFCT_ERROR_FRAMEDELAYTIMEOUT;
817  NRFX_NFCT_CB_HANDLE(m_nfct_cb.config.cb, nfct_evt);
818  }
819 
820  /* Report any other error. */
821  err_status &= ~NRF_NFCT_ERROR_FRAMEDELAYTIMEOUT_MASK;
822  if (err_status)
823  {
824  NRFX_LOG_DEBUG("Error (0x%x)", (unsigned int) err_status);
825  }
826 
827  /* Clear error status. */
828  nrf_nfct_error_status_clear(NRFX_NFCT_ERROR_STATUS_ALL_MASK);
829  }
830 
831  if (NRFX_NFCT_EVT_ACTIVE(TXFRAMESTART))
832  {
833  nrf_nfct_event_clear(NRF_NFCT_EVENT_TXFRAMESTART);
834 
835  if (m_nfct_cb.config.cb != NULL)
836  {
837  nrfx_nfct_evt_t nfct_evt;
838 
839  nfct_evt.evt_id = NRFX_NFCT_EVT_TX_FRAMESTART;
840  nfct_evt.params.tx_framestart.tx_data.p_data = nrf_nfct_rxtx_buffer_get();
841  nfct_evt.params.tx_framestart.tx_data.data_size = NRFX_NFCT_BITS_TO_BYTES(nrf_nfct_tx_bits_get());
842 
843  m_nfct_cb.config.cb(&nfct_evt);
844  }
845  }
846 }
847 
848 #endif // NRFX_CHECK(NRFX_NFCT_ENABLED)
#define NRFX_NFCT_CONFIG_IRQ_PRIORITY
Definition: sdk_config.h:12604