Skip to main content
MSipo
Senior II
Jun 7, 2022 9:34 AM UTC
Solved

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

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

This topic has been closed for replies.
MSipo
MSipoBest answer
Senior II
Jun 8, 2022 10:08 AM UTC

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 

5 replies

Andrew Neil
Super User
Jun 7, 2022 10:29 AM UTC
A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
MSipo
MSipoAuthor
Senior II
Jun 7, 2022 11:06 AM UTC

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?

Tesla DeLorean
Guru
Jun 7, 2022 5:33 PM UTC

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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
waclawek.jan
Super User
Jun 7, 2022 10:53 PM UTC

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

MSipo
MSipoAuthorBest answer
Senior II
Jun 8, 2022 10:08 AM UTC

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