cancel
Showing results for 
Search instead for 
Did you mean: 

How do I calculate the SPI CRC-16 in C?

MSipo
Senior II

How do I calculate the SPI CRC-16 in C? I have an STM32F429 sending me SPI data.

These are the SPI settings:

0693W00000NrJmMQAV.pngHow do I implement a CRC-16 check implemented in C (not using STM32)?

It is 16-bit data with LSB first. Polynomial X1+X3

1 ACCEPTED SOLUTION

Accepted Solutions

Thank you (I thought this solved it but no). I need more help. Possible STM32 bug.

I tried your example with polynomial 5, I got CRC = 0x9D68 on my logic analyzer and the same on the CRC calculator page:

0693W00000NrRYwQAN.png0693W00000NrRZ1QAN.pngBut when I change to polynomial 10 it doesn't work. I got CRC = 0x1692 on my logic analyzer but 0x3ADA on the CRC page:

0693W00000NrRZLQA3.png0693W00000NrRbHQAV.pngI tried it also with another polynomial 0xed2f and that one worked also. Got CRC = 0xD087 on the logic analyzer and on the CRC page:

0693W00000NrRbRQAV.png0693W00000NrRbbQAF.pngMy theory is that the CRC unit has a bug when the lower bit in the polynomial is not set to 1?

I have also tested the CRC in Python and got the same results as on the CRC page.

I found this later:

0693W00000NrRgWQAV.png 

View solution in original post

5 REPLIES 5
MSipo
Senior II

Is the polynomial X1+X3 same as x^16+x^3+x^1. And what about initial value? What byte order should I input the 16-bit data? Should I reverse the bits?

All good questions, CRC's are complicate, and detail specific. There's a whole bunch of shift direction, and endian ordering considerations.

Do you have a collection of good test patterns for the specific application you're using? Ideally ones from a standards document, and definitely ones from the device, or a device, that's compliant and working.

Notionally the polynomial is 0x10009 or 0x12001

The STM32 SPI implementation is also super awkward, in generation you have to manage the CRC bytes/word after the data. In a ideal would the CRC reception should be a feed-thru, where the remainder/residual goes to zero as it divides thru itself.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

To get the CRC samples, just set up that SPI as master, and then play with it in the debugger:

(gdb) set SPI2->CRCPR=0x5   // is this the poly you are after?
(gdb) set SPI2->CR1=0x2b44   // LSB bit = 0, i.e. MSB first, master 16-bit, CRC enabled
(gdb) p /x *SPI2                      // checking - note TXCRCR = 0, that's the initial value
$37 = {CR1 = 0x2b44, CR2 = 0x0, SR = 0x2, DR = 0xffff, CRCPR = 0x5,
  RXCRCR = 0x0, TXCRCR = 0x0, I2SCFGR = 0x0, I2SPR = 0x2}
(gdb) set SPI2->DR=0x1234     // just Tx something
(gdb) p /x *SPI2
$38 = {CR1 = 0x2b44, CR2 = 0x0, SR = 0x3, DR = 0xffff, CRCPR = 0x5,
  RXCRCR = 0xc, TXCRCR = 0x5ae4, I2SCFGR = 0x0, I2SPR = 0x2}

compare TXCRC=0x5ae4 to calculation on web calculator:

0693W00000NrMY3QAN.pngNow let's try the same thing just LSB first:

(gdb) set SPI2->CR1=0  // switch off SPI
(gdb) p /x *SPI2
$39 = {CR1 = 0x0, CR2 = 0x0, SR = 0x2, DR = 0xffff, CRCPR = 0x5,
 RXCRCR = 0xc, TXCRCR = 0x5ae4, I2SCFGR = 0x0, I2SPR = 0x2}
(gdb) set SPI2->CR1=0x2bc4  // same setup except LSB set
(gdb) p /x *SPI2
$40 = {CR1 = 0x2bc4, CR2 = 0x0, SR = 0x2, DR = 0xffff, CRCPR = 0x5,
 RXCRCR = 0x0, TXCRCR = 0x0, I2SCFGR = 0x0, I2SPR = 0x2}
(gdb) set SPI2->DR=0x1234   // same data
(gdb) p /x *SPI2
$41 = {CR1 = 0x2bc4, CR2 = 0x0, SR = 0x3, DR = 0xffff, CRCPR = 0x5,
 RXCRCR = 0xc, TXCRCR = 0x9d68, I2SCFGR = 0x0, I2SPR = 0x2}
(gdb)

Note, that now we had to reverse both bit order and bytes order (the web-calculator feeds byte-wise):

0693W00000NrMXAQA3.png 

JW

Thank you (I thought this solved it but no). I need more help. Possible STM32 bug.

I tried your example with polynomial 5, I got CRC = 0x9D68 on my logic analyzer and the same on the CRC calculator page:

0693W00000NrRYwQAN.png0693W00000NrRZ1QAN.pngBut when I change to polynomial 10 it doesn't work. I got CRC = 0x1692 on my logic analyzer but 0x3ADA on the CRC page:

0693W00000NrRZLQA3.png0693W00000NrRbHQAV.pngI tried it also with another polynomial 0xed2f and that one worked also. Got CRC = 0xD087 on the logic analyzer and on the CRC page:

0693W00000NrRbRQAV.png0693W00000NrRbbQAF.pngMy theory is that the CRC unit has a bug when the lower bit in the polynomial is not set to 1?

I have also tested the CRC in Python and got the same results as on the CRC page.

I found this later:

0693W00000NrRgWQAV.png