Calculation of CRC in Frame Check Sequence (FCS) field of IEEE 802.15.4

Hello Devzone Community,

I try to redo the CRC check of an incoming IEEE 802.15.4 frame in software after manipulating certain positions.

Since the check of the Frame Check Sequences (FCS) is done in HW directly at the arrival of the frame, I extract the content of the RXCRC register.

However, I had to realize that I was not able to reproduce the FCS values from my sample frames.

Here is what I get as FCS for different sample payloads:

Payload FCS (decimal) FCS (hex)
0x01 37256 0x9188
0x02 18628 0x48C4
0x0123 33360 0x8250

I am using the default IEEE 802.15.4 configuration according to specification Section 6.20.12.5 (https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.1.pdf), i.e.,

/* 16-bit CRC with ITU-T polynomial with 0 as start condition*/

write_reg(NRFRADIO_REG(CRCCNF), 0x202);

write_reg(NRFRADIO_REG(CRCPOLY), 0x11021);

write_reg(NRFRADIO_REG(CRCINIT), 0);

I have tried out many different CRC algorithms (https://reveng.sourceforge.io/crc-catalogue/16.htm) to reproduce the values from the table, but I did not succeed.

From my understanding, the ITU-T CRC16 algorithm should be used with seed set to 0x0000.

Interestingly, I found out that on the nRF the FCS computed for the sample payload 0x02 is half of the value as for 0x01.

For the tried out CRC algorithms, this was the opposite, i.e., for payload 0x02, the resulting FCS was double the FCS as for 0x01.

Can someboy please provide me a reference implementation of the CRC algorithm used on the nRF52840?

Thanks in advance!

Parents
  • Hello,

    As you write, this is handled in hardware and not something we usually are much involved in. Tyically we configure the radio, and the hardware does the rest. I don't have any indication this is done wrong. The common problem with calculating crc in software is related to endianess, seed and what data it should be calculated over (e.g. should the address be included, is there any data related to length that is not directly part of the payload etc). 

    So for instance a payload of 0x01 might be either 0000 0001 or 1000 0000 depending on endianess on bit level.

    Kenneth 

  • Hello Kenneth,

    Thanks for the fast response. I was able to solve my issue and it was indeed related to endianess on bit level!

    Furthermore, I have found a different blog post about the CRC topic on the nRF in  ESB CRC calculation 

    To re-calculate the CRC of the payloads, that I have provided in the upper table, I have tried out different algorithm implementations. However, it makes more sense to test at first with bit-symmetric payloads, i.e, 0xE7 = 11100111 or 0xFF to make sure that we don't face any endianess issues.

    With these test payloads, I identified that the big-endian version of the CRC algorithm in RIOT OS works as the one on the nRF.

    https://github.com/RIOT-OS/RIOT/blob/master/sys/checksum/ucrc16.c#L26

    (Maybe interesting ... there are corresponding unit tests demonstrating the use of the algorithm, too: https://github.com/RIOT-OS/RIOT/blob/0dc150f3fbc5cc7bf050a8bf209298d430e23bab/tests/unittests/tests-checksum/tests-checksum-ucrc16.c)

    When using this CRC16 algorithm and poly set to 0x1021 and seed set to 0x0000, I was able to reproduce the CRC values of the nRF for bit-symmetric payloads.

    Since my test-script ran on a little-endian based system, the payload had to be converted bit-wise, i.e., a 0x01 payload corresponds to 0x80 input of the algorithm.

    This helped me to re-calculate the CRC values in the FCS field of an IEEE 802.15.4 frame transmitted among nRF nodes.

Reply Children
Related