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