CRC errors receiving packets with Coded PHY and S=2

Code running on nRF52833 devkit version 1.0.0 that continuously sends an empty 500 kbit/s radio packet:

int main(void) {
    uint8_t packet[3] = {0, 0, 0};

    NRF_CLOCK->TASKS_HFCLKSTART = 1;
    while (!NRF_CLOCK->EVENTS_HFCLKSTARTED) {
    }

    // Radio config
    NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_Pos4dBm << RADIO_TXPOWER_TXPOWER_Pos);
    NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos) | (RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos);
    NRF_RADIO->TXADDRESS = 0x00UL;
    NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) | (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos);
    NRF_RADIO->CRCPOLY = 0x0000065B;
    
    // Radio address config
    uint32_t aa = 0x53abcdef;
    NRF_RADIO->PREFIX0 = aa >> 24;
    NRF_RADIO->BASE0 = aa << 8;

    // Packet configuration
    NRF_RADIO->PCNF0 = (1                           << RADIO_PCNF0_S0LEN_Pos) |
                       (0                           << RADIO_PCNF0_S1LEN_Pos) |
                       (RADIO_PCNF0_S1INCL_Include  << RADIO_PCNF0_S1INCL_Pos) |
                       (8                           << RADIO_PCNF0_LFLEN_Pos) |
                       (2                           << RADIO_PCNF0_CILEN_Pos) |
                       (RADIO_PCNF0_PLEN_LongRange  << RADIO_PCNF0_PLEN_Pos) |
                       (3                           << RADIO_PCNF0_TERMLEN_Pos);

    // Packet configuration
    NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Enabled  << RADIO_PCNF1_WHITEEN_Pos) |
                       (RADIO_PCNF1_ENDIAN_Little    << RADIO_PCNF1_ENDIAN_Pos)  |
                       (3                            << RADIO_PCNF1_BALEN_Pos)   |
                       (0                            << RADIO_PCNF1_STATLEN_Pos) |
                       (255                          << RADIO_PCNF1_MAXLEN_Pos);
    
    NRF_RADIO->CRCINIT = 0x00555555;

    NRF_RADIO->FREQUENCY = 10;
    NRF_RADIO->DATAWHITEIV = 3;

    NRF_RADIO->PACKETPTR = (uintptr_t)packet;

    NRF_RADIO->MODE      = (RADIO_MODE_MODE_Ble_LR500Kbit << RADIO_MODE_MODE_Pos);

    NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
    NRF_TIMER0->PRESCALER = 4;

    NRF_RADIO->SHORTS = RADIO_SHORTS_TXREADY_START_Msk | RADIO_SHORTS_PHYEND_DISABLE_Msk;

    NRF_TIMER0->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk;
    NRF_TIMER0->CC[0] = 45000;

    NRF_PPI->CH[0].EEP = (uintptr_t)&NRF_TIMER0->EVENTS_COMPARE[0];
    NRF_PPI->CH[0].TEP = (uintptr_t)&NRF_RADIO->TASKS_TXEN;
    NRF_PPI->CHENSET = PPI_CHENSET_CH0_Msk;

    NRF_TIMER0->TASKS_START = 1;
    for (;;) {
        __WFI();
    }
}

Code running on nRF54L15 devkit version 0.8.1 with chip revision QFAABB 2433AA that on every packet receipt prints CRC status to the console as well as showing LED indicating CRC ok/error:

void test_rx(void) {
    uint8_t packet[3 + 255];

    NRF_RADIO->RXADDRESSES = 0x01UL;
    NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) | (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos);
    NRF_RADIO->CRCPOLY = 0x0000065B;

    NRF_RADIO->MODE = (RADIO_MODE_MODE_Ble_LR125Kbit << RADIO_MODE_MODE_Pos);

    // Packet configuration
    NRF_RADIO->PCNF0 = (1                           << RADIO_PCNF0_S0LEN_Pos) |
                       (0                           << RADIO_PCNF0_S1LEN_Pos) |
                       (RADIO_PCNF0_S1INCL_Include  << RADIO_PCNF0_S1INCL_Pos) |
                       (8                           << RADIO_PCNF0_LFLEN_Pos) |
                       (2                           << RADIO_PCNF0_CILEN_Pos) |
                       (RADIO_PCNF0_PLEN_LongRange  << RADIO_PCNF0_PLEN_Pos) |
                       (3                           << RADIO_PCNF0_TERMLEN_Pos);

    // Packet configuration
    NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Enabled  << RADIO_PCNF1_WHITEEN_Pos) |
                       (RADIO_PCNF1_ENDIAN_Little    << RADIO_PCNF1_ENDIAN_Pos)  |
                       (3                            << RADIO_PCNF1_BALEN_Pos)   |
                       (0                            << RADIO_PCNF1_STATLEN_Pos) |
                       (255                          << RADIO_PCNF1_MAXLEN_Pos);

    NRF_RADIO->CRCINIT = 0x00555555;

    NRF_RADIO->PACKETPTR = (uintptr_t)packet;

    NRF_RADIO->FREQUENCY = 10;
    NRF_RADIO->DATAWHITE = ((0x40 | 3) << RADIO_DATAWHITE_IV_Pos) | (0x89 << RADIO_DATAWHITE_POLY_Pos);

    uint32_t aa = 0x53abcdef;
    NRF_RADIO->PREFIX0 = aa >> 24;
    NRF_RADIO->BASE0 = aa << 8;

    NRF_CLOCK->TASKS_PLLSTART = 1;
    NRF_CLOCK->TASKS_XOSTOP = 1;
    NRF_CLOCK->EVENTS_XOTUNED = 0;
    NRF_CLOCK->TASKS_XOSTART = 1;
    while (!NRF_CLOCK->EVENTS_XOTUNED) {
    }

    NRF_RADIO->EVENTS_RXREADY = 0;
    NRF_RADIO->TASKS_RXEN = 1;
    while (!NRF_RADIO->EVENTS_RXREADY) {
    }

    NRF_P1->PIN_CNF[10] = (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos);
    NRF_P1->PIN_CNF[14] = (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos);

    unsigned int cnt = 0;
    for (;;) {
        NRF_RADIO->EVENTS_END = 0;
        NRF_RADIO->TASKS_START = 1;
        while (!NRF_RADIO->EVENTS_END) {
        }
        unsigned int crc_ok = NRF_RADIO->CRCSTATUS;
        printf("%u %u\n", ++cnt, crc_ok);
        NRF_P1->OUTSET = 1U << (crc_ok ? 10 : 14);
        for (volatile int i = 0; i < 10000; i++);
        NRF_P1->OUTCLR = 1U << (crc_ok ? 10 : 14);
    }
}

nRF Connect SDK version is 2.8.0.

Result:

The first packet received has CRC status ok. The subsequent packets typically have CRC status error. If stepping through the code with a debugger line by line, the CRC ok rate increases a bit.

Running similar RX code on an nRF52 device, the code works as expected and CRC status is typically always ok.

If TX mode is changed to Coded PHY 125kbit/s instead, the problem disappears when receiving on nRF54L15 and CRC is typically always ok.

Question: why is this happening? I think I have followed the radio peripheral documentation correctly.

Parents
  • Hi,

    I want to start by double checking, so that I get this right.

    You test with sending:

    1. Coded PHY 500kbit/s packets from a nRF52833 to a nRF54L15. This gives CRC errors.
    2. Coded PHY 125kbit/s packets from a nRF52833 to a nRF54L15. This works
    3. Coded PHY 500kbit/s packets from a nRF52833 to a nRF52833. This works

    You tested both using your custom low-level implementation and using Zephyr. Does that mean using the BLE stack, including the SoftDvice Controller?

  • Almost correct, for 3., that works as expected without CRC errors. Since the code works if the receiver is an nRF52, that means that the sender is working properly and that the problem lies within the nRF54 when that one is the receiver.

    I tested in a blank VS code "Create a new application" -> "Create a blank application" with NCS 2.8.0, using nrf54l15dk/nrf54l15/cpuapp. Then just put the code I posted in the main.c file and call test_rx() from the main() function.

Reply
  • Almost correct, for 3., that works as expected without CRC errors. Since the code works if the receiver is an nRF52, that means that the sender is working properly and that the problem lies within the nRF54 when that one is the receiver.

    I tested in a blank VS code "Create a new application" -> "Create a blank application" with NCS 2.8.0, using nrf54l15dk/nrf54l15/cpuapp. Then just put the code I posted in the main.c file and call test_rx() from the main() function.

Children
Related