FEM: nrf21540 SoC 5340, ESB-Receiver mode not working

Good Day,

We build a custom board with nrf5340 & nrf21540,

NetCore DTS (below) , NetApp DTS has the gpio_fwd in place , all looks good in .config generated.
Net-core UART0 disabled in favor for SPI0. GPIO-TX/RX/PDN + MODE & ANTSEL correct wired.

The ESB sender/receiver code is tested w/o the FEM on two nrf5340DK boards, so I'm sure there is ESB signals.
The config for nmp1300 is OK, the 21540 and 5340 have 3v3 volt. I/O is 3v3.

mpsl_fem_enable() is called before the esb_start_rx()

Because the UART is disabled in the NetCore, I use JLINKRTTViewer for the logs in the netcore.
SDK version below:

*** Booting nRF Connect SDK v2.7.99-cs2-d73b286ff6d9 ***
*** Using Zephyr OS v3.6.99-3d01dcc251bf ***
[00:00:00.002,105] <inf> esb_prx: Enhanced ShockBurst Receiver NetCore
[00:00:00.002,441] <dbg> esb_prx: clocks_start: HF clock started
[00:00:00.002,746] <dbg> esb_prx: esb_fem_init: Fem require receiver setup
[00:00:00.002,746] <dbg> esb_prx: esb_fem_init: Fem require sender setup
[00:00:00.002,838] <inf> esb_prx: ESB initialized
[00:00:00.002,929] <inf> esb_prx: IPC bound complete
[00:00:00.002,929] <inf> esb_prx: Setting up for packet receiption

CONFIG_DT_HAS_NORDIC_NRF21540_FEM_ENABLED=y
CONFIG_DT_HAS_NORDIC_NRF21540_FEM_SPI_ENABLED=y
..
CONFIG_MPSL_FEM_ONLY=y
CONFIG_MPSL_FEM_ANY_SUPPORT=y
CONFIG_MPSL_FEM_NRF21540_GPIO_SUPPORT=y
CONFIG_MPSL_FEM_NRF21540_GPIO_SPI_SUPPORT=y
CONFIG_MPSL_FEM_NCS_SUPPORTED_FEM_USED=y
CONFIG_MPSL_FEM_API_AVAILABLE=y
CONFIG_MPSL_FEM=y
# CONFIG_MPSL_FEM_NRF21540_GPIO is not set
CONFIG_MPSL_FEM_NRF21540_GPIO_SPI=y
CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=10
CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB_POUTA=20
CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB_POUTB=10
CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=13
CONFIG_MPSL_FEM_NRF21540_RUNTIME_PA_GAIN_CONTROL=y
CONFIG_MPSL_FEM_POWER_MODEL=y
CONFIG_MPSL_FEM_POWER_MODEL_NRF21540_USE_BUILTIN=y
CONFIG_MPSL_FEM_BUILTIN_POWER_MODEL_UPDATE_PERIOD=2000
CONFIG_MPSL_FEM_DEVICE_CONFIG_254=y
CONFIG_MPSL_FEM_INIT_PRIORITY=50
# CONFIG_MPSL_FEM_LOG_LEVEL_OFF is not set
# CONFIG_MPSL_FEM_LOG_LEVEL_ERR is not set
# CONFIG_MPSL_FEM_LOG_LEVEL_WRN is not set
# CONFIG_MPSL_FEM_LOG_LEVEL_INF is not set
CONFIG_MPSL_FEM_LOG_LEVEL_DBG=y
# CONFIG_MPSL_FEM_LOG_LEVEL_DEFAULT is not set
CONFIG_MPSL_FEM_LOG_LEVEL=4
..
CONFIG_FEM_AL_LIB=y
CONFIG_FEM=y
CONFIG_NRF21540_FEM=y
..
CONFIG_ESB=y
CONFIG_ESB_MAX_PAYLOAD_LENGTH=32
CONFIG_ESB_TX_FIFO_SIZE=8
CONFIG_ESB_RX_FIFO_SIZE=8
CONFIG_ESB_PIPE_COUNT=8
CONFIG_ESB_RADIO_IRQ_PRIORITY=1
CONFIG_ESB_EVENT_IRQ_PRIORITY=2
..
CONFIG_ESB_SYS_TIMER2=y
CONFIG_ESB_SYS_TIMER_INSTANCE=2

And here is the problem I discovered when I measure the GPIO lines and CSN after start the ESB-receiver:

I measure the pins at nrf21540 after esb_start_rx()
RX = 3v
TX = 0v
PDN = 3v
CSN = 3v  <--- that should be 0V?

CSN  described in the Product specs 4446_194 v1.0 / 2020-08-20 Page 12 , needs driven LOW explicit mentioned

but later version of the Product Spec 4446_194 v1.2 / 2022-01-28 CSN is a non't care (striped out) and not mentioned any more.

So documentation is a bit uncertain, and this change isn't mentioned in the document history.

I add for test in my main() a loop toggle receiver on (5s) off (5s) to check the CSN signal for each state:

bool rxon=false;
   for (;;) {
       if (rxon) {
         esb_stop_rx();
       }
       else {
         esb_start_rx();
       }
       rxon = !rxon;
       LOG_DBG("RX is %s", rxon?"on":"off" );
       k_sleep(K_MSEC(5000));
   }

RTT-Viewer:
[00:00:55.004,821] <dbg> esb_prx: main: RX is off      ----> and the CSN pin is 0V
[00:01:00.004,974] <dbg> esb_prx: main: RX is on     -----> and the CSN pin is 3V

This is the result.

Please have a look into it.

With kind regards
Chris

  • Hi Kenneth,

    A valid point, but having the DK board without the FEM running fine. Then with the FEM: IO pins and RF is good the nRF21540 should work. There is no SPI interaction. Btw. tested the MODE enable to switch to POUTB. The MODE Pin toggle to high as expected.

    My next step, make a dump of the all registers readable. Let's find out what we have.

    Chris

  • Hi,
    Still not successful make the receiver work, all signals are correct with the GPIO only setup.

    I setup the custom board for sending now, same problem here, not RF signal output

    ESB TX event

  • Hi,

    A missing part might, that the nrf21540 must have a UICR programming cycle, even without a EFUSE burn?  That is not explicit mentioned anywhere.

    Setup the chip below.

    But still have no success yet receiving.

    #define NRF21_NODE  DT_ALIAS(femspi)
    #define SPI_OP      (SPI_WORD_SET(8) | SPI_TRANSFER_MSB)
    static struct spi_dt_spec nrf21spi = SPI_DT_SPEC_GET(NRF21_NODE, SPI_OP, 0);
    static const struct gpio_dt_spec pdn = GPIO_DT_SPEC_GET(FEM_NODE, pdn_gpios);

    #define CONFREG0 0x00
    #define CONFREG1 0x01
    #define CONFREG2 0x02
    #define CONFREG3 0x03
    #define PARTNUMBER 0x14
    #define HW_REVISION 0x15
    #define HW_ID0 0x16
    #define HW_ID1 0x17
    uint8_t baseaddr = 0x00;
    uint8_t registers[8] = {CONFREG0, CONFREG1, CONFREG2, CONFREG3, PARTNUMBER, HW_REVISION, HW_ID0, HW_ID1};

    static void uicr_setup()
    {
       int ret;
       uint8_t recv_buffer[2];
       uint8_t send_buffer[2];
       uint8_t writeop = 0x03 << 6;

       struct spi_buf tx_spi_buf       = {.buf = (void *)&send_buffer, .len = 2};
       struct spi_buf_set tx_spi_buf_set   = {.buffers = &tx_spi_buf, .count = 1};
       struct spi_buf rx_spi_bufs      = {.buf = (void *)&recv_buffer, .len = 2};
       struct spi_buf_set rx_spi_buf_set   = {.buffers = &rx_spi_bufs, .count = 1};

       int devready = spi_is_ready_dt(&nrf21spi);
       if (!devready) {
           LOG_ERR("Error: SPI device is not ready, err: %d", devready);
           return;
       }

       if (pdn.port) {
           gpio_pin_configure_dt(&pdn, GPIO_OUTPUT_INACTIVE);
           gpio_pin_set_dt(&pdn, 1);
           k_busy_wait(200);
       }
       else {
         LOG_ERR("No PDN Gpio");
         return;
       }

       send_buffer[0] = registers[1] | writeop;
       send_buffer[1] = 0x04; // enable uicr
       memset(&recv_buffer, 0, ARRAY_SIZE(recv_buffer));
       ret = spi_transceive_dt(&nrf21spi, &tx_spi_buf_set, &rx_spi_buf_set);
       if (ret<0) {

         LOG_ERR("Failed to enable UICR");
       }

       send_buffer[0] = registers[1] | writeop;
       send_buffer[1] = 0xf0;  // enter mode
       memset(&recv_buffer, 0, ARRAY_SIZE(recv_buffer));
       ret = spi_transceive_dt(&nrf21spi, &tx_spi_buf_set, &rx_spi_buf_set);
       if (ret<0) {
         LOG_ERR("Failed to enter UICR");
       }

       send_buffer[0] = registers[3] | writeop;
       send_buffer[1] = 0x1f;  // Set UICR max (31) + POUTB_PROD mode
       memset(&recv_buffer, 0, ARRAY_SIZE(recv_buffer));
       ret = spi_transceive_dt(&nrf21spi, &tx_spi_buf_set, &rx_spi_buf_set);
       if (ret<0) {
         LOG_ERR("Failed UICR CONFREG3");
       }

       send_buffer[0] = registers[2] | writeop;
       send_buffer[1] = 0x1f;  // Set UICR max (31) + POUTA_PROD mode + EFUSE IDLE
       memset(&recv_buffer, 0, ARRAY_SIZE(recv_buffer));
       ret = spi_transceive_dt(&nrf21spi, &tx_spi_buf_set, &rx_spi_buf_set);
       if (ret<0) {
         LOG_ERR("Failed UICR CONFREG3");
       }

       send_buffer[0] = registers[1] | writeop;
       send_buffer[1] = 0x00;  // exit mode
       memset(&recv_buffer, 0, ARRAY_SIZE(recv_buffer));
       ret = spi_transceive_dt(&nrf21spi, &tx_spi_buf_set, &rx_spi_buf_set);
       if (ret<0) {
         LOG_ERR("Failed to enter UICR");
       }
       gpio_pin_set_dt(&pdn, 0);
       k_busy_wait(5000);
    }

Related