NRFX_NFCT

Hello DevZone,

I am trying to build a NFC driver but I am getting issues with it reinitializing every time I detect a field.

I am unable to use the T2T and T4T libraries as they do not give me the functionality I need.

In short I have a T2T poller which is sending commands to my nRF but the T2T library is not able to write back.

I want to use the nrfx_nfct library to build my own NFC driver but I cannot understand why I am getting reinitialization when a field is detected.

My goal is to set data ready based on the type of command I receive but unfortunately I'm not even able to receive anything due to the reinitialization.

uint8_t rxBlaBla[100];
uint8_t txBlaBla[100];
nrfx_nfct_data_desc_t rxBla, txBla;

void nfc_caaallback(nrfx_nfct_evt_t const * p_event)
{
    switch (p_event->evt_id)
    {
        case NRFX_NFCT_EVT_FIELD_DETECTED:
            NRF_LOG_DEBUG("Field On");
            break;
        case NRFX_NFCT_EVT_FIELD_LOST:
            NRF_LOG_DEBUG("Field Off");
            nrfx_nfct_autocolres_disable();
            break;
        case NRFX_NFCT_EVT_SELECTED:
            NRF_LOG_DEBUG("Selected");
            break;
        case NRFX_NFCT_EVT_TX_FRAMESTART:
            NRF_LOG_DEBUG("Started TX frame");
            break;
        case NRFX_NFCT_EVT_TX_FRAMEEND:
            NRF_LOG_DEBUG("Ended TX frame");
            break;
        case NRFX_NFCT_EVT_RX_FRAMESTART:
            NRF_LOG_DEBUG("Started RX frame");
            break;
        case NRFX_NFCT_EVT_RX_FRAMEEND:
        {    
            NRF_LOG_DEBUG("Ended RX frame status = %d", p_event->params.rx_frameend.rx_status);
            NRF_LOG_DEBUG("Data len in received frame is %d", p_event->params.rx_frameend.rx_data.data_size);
            uint16_t command = uint16_big_decode(p_event->params.rx_frameend.rx_data.p_data);
            NRF_LOG_DEBUG("Data is 0x%04x", command);
        }   break;
        case NRFX_NFCT_EVT_ERROR:
        {    NRF_LOG_DEBUG("Error occured. Error is %d", p_event->params.error.reason);
             nrfx_nfct_data_desc_t rx;
             rx.data_size = sizeof(m_ndef_msg_buf);
             rx.p_data = m_ndef_msg_buf;
             nrfx_nfct_rx(&rx);
        }   break;
        default:
            /* No implementation required */
            break;
    }
}

int main(void)
{
    log_init();
    
    
    rxBla.data_size = sizeof(rxBlaBla);
    rxBla.p_data = rxBlaBla;

    txBla.data_size = sizeof(txBlaBla);
    txBla.p_data = txBlaBla;

    nrfx_nfct_config_t config =
    {
        .rxtx_int_mask = (NRF_NFCT_INT_RXFRAMEEND_MASK   | 
                                    NRF_NFCT_INT_RXERROR_MASK      | 
                                    NRF_NFCT_INT_TXFRAMESTART_MASK | 
                                    NRF_NFCT_INT_TXFRAMEEND_MASK),
        .cb = nfc_caaallback
    };

    uint32_t u32ErrCode;

    u32ErrCode = nrf_drv_clock_init();
    APP_ERROR_CHECK(u32ErrCode);
    nrf_drv_clock_lfclk_request(NULL);
    nrf_drv_clock_hfclk_request(NULL);

    u32ErrCode = nrfx_nfct_init(&config);
    APP_ERROR_CHECK(u32ErrCode);
    
    nrfx_nfct_rx(&rxBla);
    u32ErrCode = nrfx_nfct_tx(&txBla, NRF_NFCT_FRAME_DELAY_MODE_EXACTVAL);
    APP_ERROR_CHECK(u32ErrCode);

    nrfx_nfct_enable();


    while(1)
    {
        while(NRF_LOG_PROCESS());
    }

}

The RTT output I get is:

<info> NFCT: Reinitialize
<info> NFCT: Initialized
<info> NFCT: Tx start
<info> NFCT: Start
<debug> app: Field On
<info> NFCT: Reinitialize
<debug> app: Field Off
<debug> app: Field On
<info> NFCT: Reinitialize
<debug> app: Field Off
<debug> app: Field On
<info> NFCT: Reinitialize
<info> NFCT: Reinitialize
<debug> app: Field Off
<debug> app: Field On
<info> NFCT: Reinitialize
<debug> app: Field Off

  • Sorry, we don't have any flow charts that are using the nfc driver directly, so you would need to rely on the NFC hardware description in the nRF52832 Product Specifications in this case:
    https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/nfc.html#concept_kmr_nxj_1s 

    I would still recommend to double check if the NFC library can do what you want, e.g.:
    https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.1.0/nfc_type4tag_dox.html 

    Also double check if any of the errata's apply to your case:
    https://infocenter.nordicsemi.com/topic/errata_nRF52832_Rev1/ERR/nRF52832/Rev1/latest/err_832_new.html 

  • I am also working with this library and facing the same issue even with the example project nfc_writable_ndef_msg.

    Here the log's output:

    <info> NFCT: Tx start
    <info> TIMER: Disabled instance: 0.
    <info> NFCT: Reinitialize
    <info> TIMER: Enabled instance: 0.
    <info> TIMER: Disabled instance: 0.
    <info> NFCT: Reinitialize
    <info> TIMER: Enabled instance: 0.
    <info> TIMER: Disabled instance: 0.
    <info> NFCT: Reinitialize
    <info> TIMER: Enabled instance: 0.
    <info> NFCT: Tx start
    <info> NFCT: Tx start
    <info> TIMER: Disabled instance: 0.
    <info> NFCT: Reinitialize
    <info> TIMER: Enabled instance: 0.
    <info> TIMER: Disabled instance: 0.
    <info> NFCT: Reinitialize

    What I could track about this problem is the workaround 116 on the nrfx_nfct.c file, descript as:

     * If you are using the nRF52832 chip, the workarounds for the following anomalies are applied:
     * - 79. NFCT: A false EVENTS_FIELDDETECTED event occurs after the field is lost.
     * - 116. NFCT does not release HFCLK when switching from ACTIVATED to SENSE mode.
     * To implement the first workaround, an instance of NRF_TIMER is used. After the NFC field is detected,
     * the timing module periodically polls its state to determine when the field is turned off.
     * To implement the second workaround, power reset is used to release the clock acquired by NFCT
     * after the field is turned off. Note that the NFCT register configuration is restored to defaults.

    I see that the function nrfx_nfct_field_poll() is called periodically but is detects field off very often, even when the polling device (an android smartphone in my case) is still close to the nrf52832 NFC antenna. I don't know if the workaround is not working or if I am not understanding what is happening.

    Does anyone know what to do here?

  • I would still recommend to double check if the NFC library can do what you want, e.g.:

    Like I mentioned in my original post, I have tried to use them but they did not do what I want.

    I managed to fix my reinitialize problem and got it working how I want it to.

    The only thing I had to do was force the state to active when the field was detected.

    Here is my solution for any other that have the same problem. Note: this uses no NDEF, just binary data.

    #include "nrf_drv_clock.h"
    #include "nrfx_nfct.h"
    
    
    static nrfx_nfct_data_desc_t rx, tx;
    static nrf_drv_clock_handler_item_t m_clock_handler_item; /**< Clock event handler item structure. */
    
    static inline void clock_event_handler(nrf_drv_clock_evt_type_t event)
    {
        switch(event)
        {
            case NRF_DRV_CLOCK_EVT_HFCLK_STARTED:
                /* Activate NFCT only when HFXO is running */
                nrfx_nfct_state_force(NRFX_NFCT_STATE_ACTIVATED);
                break;
    
            default:
                /* No implementation required */
                break;
        }
    }
    
    startic void nfc_caaallback(nrfx_nfct_evt_t const * p_event)
    {
        switch (p_event->evt_id)
        {
            case NRFX_NFCT_EVT_FIELD_DETECTED:
                NRF_LOG_DEBUG("Field On");
                nrf_drv_clock_hfclk_request(&m_clock_handler_item);
                
                break;
            case NRFX_NFCT_EVT_FIELD_LOST:
                NRF_LOG_DEBUG("Field Off");
                nrf_drv_clock_hfclk_release();
                break;
            case NRFX_NFCT_EVT_SELECTED:
                NRF_LOG_DEBUG("Selected");
                memset(m_ndef_msg_buf, 0, sizeof(m_ndef_msg_buf));
                nrfx_nfct_rx(&rx);
                break;
            case NRFX_NFCT_EVT_TX_FRAMESTART:
                NRF_LOG_DEBUG("Started TX frame");
                break;
            case NRFX_NFCT_EVT_TX_FRAMEEND:
                NRF_LOG_DEBUG("Ended TX frame");
                memset(m_ndef_msg_buf, 0, sizeof(m_ndef_msg_buf));
                nrfx_nfct_rx(&rx);
                break;
            case NRFX_NFCT_EVT_RX_FRAMESTART:
                NRF_LOG_DEBUG("Started RX frame");
                break;
            case NRFX_NFCT_EVT_RX_FRAMEEND:
            {    
                NRF_LOG_DEBUG("Ended RX frame status = %d", p_event->params.rx_frameend.rx_status);
                NRF_LOG_DEBUG("Data len in received frame is %d", p_event->params.rx_frameend.rx_data.data_size);
        
        
                uint16_t command = uint16_big_decode(p_event->params.rx_frameend.rx_data.p_data);
                NRF_LOG_DEBUG("Data is 0x%04x", command);
                
            }   break;
            case NRFX_NFCT_EVT_ERROR:
            {    NRF_LOG_DEBUG("Error occured. Error is %d", p_event->params.error.reason);
                 nrfx_nfct_rx(&rx);
            }   break;
            default:
                /* No implementation required */
                break;
        }
    }
    
    int main(void)
    {
        log_init();
        
        
        rx.data_size = sizeof(m_ndef_msg_buf);
        rx.p_data = m_ndef_msg_buf;
    
        tx.data_size = sizeof(m_ndef_msg_buf);
        tx.p_data = m_ndef_msg_buf;
    
        nrfx_nfct_config_t config =
        {
            .rxtx_int_mask = (NRF_NFCT_INT_RXFRAMEEND_MASK   | 
                                        NRF_NFCT_INT_RXERROR_MASK      | 
                                        NRF_NFCT_INT_TXFRAMESTART_MASK | 
                                        NRF_NFCT_INT_TXFRAMEEND_MASK),
            .cb = nfc_caaallback
        };
    
    
        uint32_t u32ErrCode;
        m_clock_handler_item.event_handler = clock_event_handler;
        m_clock_handler_item.p_next        = NULL;
        
        u32ErrCode = nrf_drv_clock_init();
        APP_ERROR_CHECK(u32ErrCode);
    
        u32ErrCode = nrfx_nfct_init(&config);
        APP_ERROR_CHECK(u32ErrCode);
        
        nrfx_nfct_enable();
    
        while(1)
        {
            while(NRF_LOG_PROCESS());
            __WFE();
        }
    
    }

Related