Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NFC doesn't work when the softdevice is enabled

Hello,

I'm using the sdk v17.0.2 with softdevice s140 with a custom PCB shipping the nrf52840.

I'm facing an issue where I cannot enable NFC and softdevice at the same time.

When the NFC is enabled and the softdevice is not, the my tag can be read from an Android smartphone. But I soon I enable the softdevice (with nrf_sdh_enable_request), the tag cannot be read anymore.

There is my very simple example:

#include "nfc_ndef_msg.h"
#include "nfc_t2t_lib.h"
#include "nfc_text_rec.h"
#include <app_error.h>
#include <nrf_log.h>
#include <nrf_pwr_mgmt.h>
#include <nrf_sdh.h>
#include <string.h>

#define MAX_REC_COUNT 3 /**< Maximum records count. */

/* Text message in English with its language code. */
/** @snippet [NFC text usage_1] */
static const uint8_t en_payload[] = {
        'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'};
static const uint8_t en_code[] = {'e', 'n'};
/** @snippet [NFC text usage_1] */
/* Buffer used to hold an NFC NDEF message. */
uint8_t m_ndef_msg_buf[256];

/**
 * @brief Callback function for handling NFC events.
 */
static void nfc_callback(void *p_context, nfc_t2t_event_t event, const uint8_t *p_data, size_t data_length) {
    (void) p_context;

    switch (event) {
        case NFC_T2T_EVENT_FIELD_ON:
            //bsp_board_led_on(BSP_BOARD_LED_0);
            NRF_LOG_INFO("NFC Field ON");
            break;
        case NFC_T2T_EVENT_FIELD_OFF:
            //bsp_board_led_off(BSP_BOARD_LED_0);
            NRF_LOG_INFO("NFC Field OFF");
            break;
        default:
            break;
    }
}

static ret_code_t welcome_msg_encode(uint8_t *p_buffer, uint32_t *p_len) {
    /** @snippet [NFC text usage_2] */
    ret_code_t err_code;

    /* Create NFC NDEF text record description in English */
    NFC_NDEF_TEXT_RECORD_DESC_DEF(nfc_en_text_rec,
                                  UTF_8,
                                  en_code,
                                  sizeof(en_code),
                                  en_payload,
                                  sizeof(en_payload));
    /** @snippet [NFC text usage_2] */


    /* Create NFC NDEF message description, capacity - MAX_REC_COUNT records */
    /** @snippet [NFC text usage_3] */
    NFC_NDEF_MSG_DEF(nfc_text_msg, MAX_REC_COUNT);
    /** @snippet [NFC text usage_3] */

    /* Add text records to NDEF text message */
    /** @snippet [NFC text usage_4] */
    err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_text_msg),
                                       &NFC_NDEF_TEXT_RECORD_DESC(nfc_en_text_rec));
    VERIFY_SUCCESS(err_code);

    /** @snippet [NFC text usage_5] */
    err_code = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_text_msg),
                                   p_buffer,
                                   p_len);
    return err_code;
    /** @snippet [NFC text usage_5] */
}


int main() {
    uint32_t len = sizeof(m_ndef_msg_buf);

    ret_code_t err_code = 0;
    // uncomment this and the NFC won't work anymore
    err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    //Set up NFC
    err_code = nfc_t2t_setup(nfc_callback, NULL);
    APP_ERROR_CHECK(err_code);

    //Encode welcome message
    err_code = welcome_msg_encode(m_ndef_msg_buf, &len);
    APP_ERROR_CHECK(err_code);

    //Set created message as the NFC payload
    err_code = nfc_t2t_payload_set(m_ndef_msg_buf, len);
    APP_ERROR_CHECK(err_code);

    //Start sensing NFC field
    err_code = nfc_t2t_emulation_start();
    APP_ERROR_CHECK(err_code);


    NRF_LOG_INFO("in done...");

    while (1) {}
}

I found a similar issue here [1] but the fix doesn't work for me.

There is my linker script file:

/* Linker script to configure memory regions. */

SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)

MEMORY
{
  FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xc9000
  RAM (rwx) :  ORIGIN = 0x20002C00, LENGTH = 0x3d400
  uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4
}

SECTIONS
{
  . = ALIGN(4);
  .uicr_bootloader_start_address :
  {
    PROVIDE(__start_uicr_bootloader_start_address = .);
    KEEP(*(SORT(.uicr_bootloader_start_address*)))
    PROVIDE(__stop_uicr_bootloader_start_address = .);
  } > uicr_bootloader_start_address
}

SECTIONS
{
  . = ALIGN(4);
  .mem_section_dummy_ram :
  {
  }
  .log_dynamic_data :
  {
    PROVIDE(__start_log_dynamic_data = .);
    KEEP(*(SORT(.log_dynamic_data*)))
    PROVIDE(__stop_log_dynamic_data = .);
  } > RAM
  .log_filter_data :
  {
    PROVIDE(__start_log_filter_data = .);
    KEEP(*(SORT(.log_filter_data*)))
    PROVIDE(__stop_log_filter_data = .);
  } > RAM
  .fs_data :
  {
    PROVIDE(__start_fs_data = .);
    KEEP(*(.fs_data))
    PROVIDE(__stop_fs_data = .);
  } > RAM

} INSERT AFTER .data;

SECTIONS
{
  .mem_section_dummy_rom :
  {
  }
  .sdh_ble_observers :
  {
    PROVIDE(__start_sdh_ble_observers = .);
    KEEP(*(SORT(.sdh_ble_observers*)))
    PROVIDE(__stop_sdh_ble_observers = .);
  } > FLASH
  .sdh_soc_observers :
  {
    PROVIDE(__start_sdh_soc_observers = .);
    KEEP(*(SORT(.sdh_soc_observers*)))
    PROVIDE(__stop_sdh_soc_observers = .);
  } > FLASH
  .pwr_mgmt_data :
  {
    PROVIDE(__start_pwr_mgmt_data = .);
    KEEP(*(SORT(.pwr_mgmt_data*)))
    PROVIDE(__stop_pwr_mgmt_data = .);
  } > FLASH
  .log_const_data :
  {
    PROVIDE(__start_log_const_data = .);
    KEEP(*(SORT(.log_const_data*)))
    PROVIDE(__stop_log_const_data = .);
  } > FLASH
  .sdh_req_observers :
  {
    PROVIDE(__start_sdh_req_observers = .);
    KEEP(*(SORT(.sdh_req_observers*)))
    PROVIDE(__stop_sdh_req_observers = .);
  } > FLASH
  .sdh_state_observers :
  {
    PROVIDE(__start_sdh_state_observers = .);
    KEEP(*(SORT(.sdh_state_observers*)))
    PROVIDE(__stop_sdh_state_observers = .);
  } > FLASH
  .sdh_stack_observers :
  {
    PROVIDE(__start_sdh_stack_observers = .);
    KEEP(*(SORT(.sdh_stack_observers*)))
    PROVIDE(__stop_sdh_stack_observers = .);
  } > FLASH
  .log_backends :
  {
    PROVIDE(__start_log_backends = .);
    KEEP(*(SORT(.log_backends*)))
    PROVIDE(__stop_log_backends = .);
  } > FLASH
    .nrf_balloc :
  {
    PROVIDE(__start_nrf_balloc = .);
    KEEP(*(.nrf_balloc))
    PROVIDE(__stop_nrf_balloc = .);
  } > FLASH

} INSERT AFTER .text


INCLUDE "nrf_common.ld"

I still do not understand if I need to register soc event with NRF_SDH_BLE_OBSERVER. Do the nfc_t2t handle it?

[1] https://devzone.nordicsemi.com/f/nordic-q-a/42141/nrf52832---nfc-stops-working-when-softdevice-is-enabled

Best,

Joël

  • For now I can see, when the softdevice is not enabled, the NRFX_NFCT_EVT_ACTIVE(SELECTED) event is met in the NFCT irq handler. But when the softdevice is enabled this event doesn't appear. I can only see the FIELDDETECTED event in this case.

  • I'm not sure it is related but I can see, when SD is enabled, the clock IRQ events are not raised.

    The nfc_platform_event_handler is called by the nfc_t2t library and performs a  nrf_drv_clock_hfclk_request. This request will try to start the hfclk either with nrfc_clock_hfclk_start when the SD is not enabled or via sd_clock_hfclk_request. When sd_clock_hfclk_request is called, the clock irq handler (nrfx_clock_irq_handler) is not called, and the workaround for anomaly 201 is not trigger.

    My guess for now is that we should have the HFCLKSTARTED event once sd_clock_hfclk_request as been called.

    Why clock IRQs are not raised when the SD is enabled ?

  • Hello Joël,

    Due to public holidays in Norway, our experts are out of office until Tuesday. We will come back to you as soon as possible.

    I apologise for any inconvenience caused.

    Regards,

    Markus

  • Hi,

    We have multiple examples using NFC and BLE. e.g. Experimental: BLE Pairing Using NFC - Peripheral Reference Example I could suggest that you try to compare your project with one of the examples to see how to add NFC to BLE. Or maybe just modify one of the example projects to function like a tag.

  • Okay I found something fun....

    For the context, I'm using CMake for my project and I usually create a static library with the nrf sdk and I link my application against this library. I have a bunch of very different features in the project and I'm using some nrf functionalities (queues, sdh, ble, block device, usb, i2c, spi, uart) and everything is working except the nfc tag part.

    I tried to modify the example you suggest to make it work as an nfc tag and it worked very quickly and smoothly... So I've dig into both projects to find some differences related to the project configuration: compile options, compile definitions, sdk_config, sources files and I found that if I'm not creating a static library with the sdk, the nfc tag works. Which mean if I compile the sdk sources in the same target as my firmware, everything works...

    I really don't know why because all compile/link options and definitions are injected in both targes (library and application).

    I understand you'll not provide support for CMake - and I don't ask for it - , but if someone has an idea...

    Best,

Related