NFC tag unresponsive after shutting down during concurrent read

Hi,

I have detected a possible issue either in the SDK or the silicon related to the NFC tag. In my project we shut down the label and enable it based on certain conditions and our testers reported that in rare cases the NFC tag remains unresponsive and unreadable after it's enabled. We use the the nRF52840 chip, the old SDK 17.1.0 and nfc_t2t_lib NFC simulation lib on a custom board.

To reproduce the issue, I used a FEIG NFC reader to periodically read out the NFC tag as quickly as possible (every ~40ms) while I made the system busy with some interrupts. These were BLE or GPIO related interrupts that make the NFC shutdown mechanism delay a few ms. Usually the nfc_t2t_emulation_stop() function is called at the moment we receive a NFC_T2T_FIELD_LOST event in the callback, but these mentioned interrupts can delay the call chain. By the time the emulation is stopped and the NFC label is disabled, we already receive the low-level FIELD_DETECTED and SELECTED events (those two will generate the NFC_T2T_FIELD_DETECTED event on higher level) from the next NFC reading session. In these scenarios, the NFC tag remains disabled after nfc_t2t_emulation_start() is called later and we only receive FIELD_DETECTED events on low-level and nothing on the T2T level. 

I can also see that when the emulation starts and the label is enabled, we detect 3-4 events at the same time (usually FIELD_DETECTEDFIELD_LOSTSELECTED and event 284) and only the FIELD_DETECTED afterwards. My hypothesis is that somehow the concurrent reading interacts poorly with the shutdown mechanism and some interrupts get cached or stuck and when I re-enable the label it's in an inconsistent state of some sort and isn't able to communicate with the reader anymore.

I used the RTT backend to log the events coming directly from the NFCT interrupt handler (nrfx_nfct_irq_handler()). Below you can see the moment the NFC label is enabled again and multiple events occur at the same time (probably occurred during shutdown) and then only field detected events.

This behavior also occurs if I just randomly shut down the T2T simulation while I'm reading the label as frequently as possible. If the shutdown happens at the right moment (e.g after field lost event or even after the first field detected event but before the selected event), then the NFC label remains operational after simulation start. My workaround implementation works exactly like that, just ensuring that if we want to shut down the NFC label and there is a concurrent read session, we wait until the session is over and the field lost event is received. 

I'd like to get some thoughts on this issue, has it ever been reported? I checked these 2 cases, but mine seems different: 

 RE: NFC tag stops working suddenly in very rare cases 

 RE: NFC stops working 

Parents
  • Hi, 

    Do you have a nRF52840 DK? and have you tried reproducing it on the DK? 
    For us it is easier to benchmark these issues with the DK as a the reference hardware just to eliminate most other variables just in case. 

    I'd like to get some thoughts on this issue, has it ever been reported? I checked these 2 cases, but mine seems different: 

    I will dig internally and see what I can find and get back to you. 


    Regards,
    Jonathan

Reply
  • Hi, 

    Do you have a nRF52840 DK? and have you tried reproducing it on the DK? 
    For us it is easier to benchmark these issues with the DK as a the reference hardware just to eliminate most other variables just in case. 

    I'd like to get some thoughts on this issue, has it ever been reported? I checked these 2 cases, but mine seems different: 

    I will dig internally and see what I can find and get back to you. 


    Regards,
    Jonathan

Children
  • Yes, I do have a dev kit. I'm gonna try to reproduce it on that as well. It might take me a few days though.

  • Thanks, that would be much appreciated. 

    I did find something that seems relevant or similar to the issue you describe here form another customer case that we also confirmed. The NFC gets stuck getting only a FIELDDETECTED event. Its possible to recover from this state by triggering SENSE or the DISABLE task, so calling nfc_t2t_emulation_stop/nfc_t2t_emulation_start. 

    Regards,
    Jonathan

  • Hey Jonathan,

    I could reproduce the issue on the nRF52840-DK with the following example:

    #include "Build.h"
    #include "nrf_drv_clock.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "nrf_sdh.h"
    #include "nrfx_rtc.h"
    #include "hal/nrf_nfct.h"
    #include "nfc_t2t_lib.h"
    #include "nrf_delay.h"
    
    //===================================================================
    // Local Variables
    //===================================================================
    
    //===================================================================
    //Local Function Prototypes
    //===================================================================
    /** @brief The processor enters a low-power state until one of a number of events occurs (e.g. interrupt).
     */
    static void vEventHandler(void *pvContext, nfc_t2t_event_t tEvent, const uint8_t *pu8Data, size_t tDataLength);
    static bool bFieldLostEvent = false;
    
    void init();
    
    //===================================================================
    //Global Functions
    //===================================================================
    
    //===================================================================
    // Local Functions
    //===================================================================
    
    // use the free rtc instance 2 (instance 0 -> softdevice, instance 1 -> libuarte)
    static const nrfx_rtc_t rtcInstance = NRFX_RTC_INSTANCE(2);
    
    uint32_t getRtc1Count(void)
    {
        return nrfx_rtc_counter_get(&rtcInstance);
    }
    // nothing to do -> keep empty as it is a mandatory parameter for the rtc init
    void irqHandler(nrfx_rtc_int_type_t tParam)
    {
    }
    
    int main(void)
    {
        init();
        uint8_t delay = 0U;
    
        // Enter main loop.
        for (;;)
        {
            while(NRF_LOG_PROCESS())
            {
    
            }
            if (bFieldLostEvent)
            {
                bFieldLostEvent = false;
                NRF_LOG_INFO("delay: %d", (int)delay);
                nrf_delay_ms(delay);
    
                (void)nfc_t2t_emulation_stop();
    
                const uint8_t payload[] = {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U};
                (void)nfc_t2t_payload_set(payload, 10U);
                (void)nfc_t2t_emulation_start();
    
                // (void)nfc_t2t_emulation_stop();
                // (void)nfc_t2t_emulation_start();
                delay = (delay + 1U) % 100U;
            }
        }
    }
    
    void init()
    {
        nrfx_rtc_config_t rtc_config = NRFX_RTC_DEFAULT_CONFIG;
        //rtc_config.interrupt_priority = irq_prio_inc(p_config->int_prio);
    
        rtc_config.prescaler = 0;
        ret_code_t tErrCode = nrfx_rtc_init(&rtcInstance, &rtc_config, irqHandler);
        APP_ERROR_CHECK(tErrCode);
    
        tErrCode = nrfx_rtc_cc_set(&rtcInstance, 0, INT16_MAX, false);
        nrfx_rtc_overflow_enable(&rtcInstance, true);
        APP_ERROR_CHECK(tErrCode);
        nrfx_rtc_enable(&rtcInstance);
    
        // initialize the nrf log module
        tErrCode = NRF_LOG_INIT(getRtc1Count);
        APP_ERROR_CHECK(tErrCode);
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        // initialize the clock
        tErrCode = nrf_drv_clock_init();
        APP_ERROR_CHECK(tErrCode);
    
        // start LF clock needed by RTC (timer module).
        nrf_drv_clock_lfclk_request(NULL);
        while (nrf_drv_clock_lfclk_is_running() == false)
        {
            // wait
        };
    
        // start execution.
        NRF_LOG_INFO("Start %s %02u.%02u.%02u",
                     cProjectName,
                     MAJOR_SOFTWARE_VERSION,
                     MINOR_SOFTWARE_VERSION,
                     BUGFIX_SOFTWARE_VERSION);
    
        const uint32_t u32ErrorStatus = nfc_t2t_setup(vEventHandler, NULL);
        NRF_LOG_INFO("T2T lib init error: %d", u32ErrorStatus);
    
        const uint8_t payload[] = {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U};
        const uint32_t u32ErrorStatusPayload = nfc_t2t_payload_set(payload, 10U);
        NRF_LOG_INFO("T2T lib payload set serror: %d", u32ErrorStatusPayload);
    
        const uint32_t u32ErrorStatusStart = nfc_t2t_emulation_start();
        NRF_LOG_INFO("T2T lib emulation start error: %d", u32ErrorStatusStart);
    }
    
    static void vEventHandler(void *pvContext, nfc_t2t_event_t tEvent, const uint8_t *pu8Data, size_t tDataLength)
    {
        (void)pvContext;   // unused
        (void)pu8Data;     // unused
        (void)tDataLength; // unused
    
        switch (tEvent)
        {
            case NFC_T2T_EVENT_FIELD_ON:
                NRF_LOG_INFO("t2t event: NFC_FIELD_DETECTED");
                break;
    
            case NFC_T2T_EVENT_FIELD_OFF:
                NRF_LOG_INFO("t2t event: NFC_FIELD_REMOVED");
                bFieldLostEvent = true;
                break;
    
            case NFC_T2T_EVENT_DATA_READ:
                NRF_LOG_INFO("t2t event: NFC_TAG_READ");
                break;
    
            case NFC_T2T_EVENT_STOPPED:
                NRF_LOG_INFO("t2t event: NFC_T2T_EVENT_STOPPED");
                break;
    
            default:
                NRF_LOG_INFO("t2t event: DEFAULT");
                break;
        }
    }

    I added an artificial delay in the main loop before I turn off the NFC tag simulation and I only receive FIELD_DETECTED (not the high level T2T_FIELD_ON, but the low-level NFCT one) event after a few seconds, which makes my tag unresponsive.

    I also tried to stop and re-start the communication again (the lines commented out), but it didn't help. The only thing that works for me is a processor reset.

    Could you please try to reproduce it on your side as well? The key is to have an active NFC reader that reads the tag as fast as possible. In my case I only sent inventory commands (which generates FIELD_DETECTED and SELECTED events on NFCT level) in an infinite loop as a separate application.

    Best regards,

    Attila

Related