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.