[SOLVED] STM32 CRC calculation unit - I know this is a very old question.
I could not get wanted result by using STM32F7 calculation unit. The code I borrowed for comparison was from WireShark CRC32 function. It was a table based function for speed. And I compared the STM32 CRC result with bitwise algorithm. I found out that STM32 CRC unit by default gives the same result as the named one CRC32Mpeg2.
But I failed to set STM32F7 CRC unit to give the same result of WireShark CRC32 after I tried all reasonable combinations of parameters.
I've read quite a lot online articles and there could be mistakes involved with CRC calculation. The most notorious issue comes from the shifting direction. And the table and the shifting direction mismatch, input data reflection(or inversion from STM32 datasheet), initial CRC value and so on.
And I think there are ambiguities about byte inversion and output data inversion. We can think of more than 1 operation with input data inversion and output data inversion. Especially I wonder when the output inversion is applied, every byte or end of stream? How can the CRC calculation unit know it's the end of byte stream? Or it just inverse the result with every byte or every word?
I tried to find answers to my questions here and from other sources, but I couldn't.
There are at least 6 independent parameters even if we rule out the symmetry of initial CRC and the final XOR value.
- shifting direction
- polynomial (only 0xEDB88320, 0x04C11DB7 are considered here)
- initial CRC value(usually 0xffffffff or 0x00000000. And only two values considered here)
- final XOR (usually 0xffffffff or 0x00000000. And only two values considered here)
- Input byte reflection
- Output CRC reflection
And I wrote a test program after some researches and some codes borrowed from Internet. This program is written so that I can test all six combinations with the above parameters. But the shifting direction should be done in the form of action. So I prepared two functions.
refer to attached source.
calcCRC32std() : CRC shifted right
calcCRC32stm() : CRC shifted left
And both functions accept 5 parameters of CRC as arguments.
I generated 5 kinds of named CRC(names are from http://www.sunshine2k.de/coding/javascript/crc/crc_js.html).
- CRC32 - WireShark
- CRCMPeg2 - STM32
- BZIP2
- Posix
- JAMCRC
here is the test run result.
--------- reflection test ---------
byte reflect8: 0x14 vs. 0x28
word reflect32: 0x01020408 vs. 0x10204080
poly0x04C11DB7 reflected: 0xEDB88320
test string: abcdefghijklmnopqrstuvwxyz
------------ SHIFT R/L ------------
CRC32std(0xEDB88320, 0xffffffff, onXOR, offRefIn, offRefOut) = 0x4c2750bd
CRC32stm(0x04C11DB7, 0xffffffff, offXOR, offRefIn, offRefOut) = 0x88406c69
------------ CRC32 std ------------
CRC32std(0xEDB88320, 0xffffffff, onXOR, offRefIn, offRefOut) = 0x4c2750bd
CRC32std(0xEDB88320, 0xffffffff, offXOR, onRefIn, onRefOut) = 0x88406c69
CRC32stm(0x04C11DB7, 0xffffffff, offXOR, offRefIn, offRefOut) = 0x88406c69
CRC32stm(0x04C11DB7, 0xffffffff, onXOR, onRefIn, onRefOut) = 0x4c2750bd
Derived from the two basic ones above!!!
------------ CRC32 BZIP2 ------------
CRC32std(0xEDB88320, 0xffffffff, onXOR, onRefIn, onRefOut) = 0x77bf9396
CRC32stm(0x04C11DB7, 0xffffffff, onXOR, offRefIn, offnRefOut) = 0x77bf9396
----------- CRC32 Posix -----------
CRC32std(0xEDB88320, 0x00000000, onXOR, onRefIn, onRefOut) = 0xc43d5b9c
CRC32stm(0x04C11DB7, 0x00000000, onXOR, offRefIn, offRefOut) = 0xc43d5b9c
----------- CRC32JAMCRC -----------
CRC32std(0xEDB88320, 0xffffffff, offXOR, offRefIn, offRefOut) = 0xb3d8af42
CRC32stm(0x04C11DB7, 0xffffffff, offXOR, onRefIn, onRefOut) = 0xb3d8af42The thing I would like to show is that whether the shift direction is chosen, we can get the same result with other 5 CRC parameters. So we can get all CRCs of calcCRC32std() by using calcCRC32stm(). Both are some kind of dual relationship or reciprocal, whatever you like.
The default initialization parameters for STM32F7 CRC calculation unit are
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
And I call the functions as follows.
#define CRC_TEST_STRING "abcdefghijklmnopqrstuvwxyz"
crc = HAL_CRC_Calculate(&hcrc, (uint32_t *)CRC_TEST_STRING, strlen(CRC_TEST_STRING));HAL_CRC_Calculate() gives the same result of
INF esp/apps/shell.c[92] shell running crc: 0x88406c69!!!
INF esp/apps/shell.c[93] shell XORed crc: 0x77bf9396!!!
CRC32stm(0x04C11DB7, 0xffffffff, offXOR, offRefIn, offRefOut) = 0x88406c69
And
CRC32std(0xEDB88320, 0xffffffff, offXOR, onRefIn, onRefOut) = 0x88406c69
From this I guessed that if I changed the final XOR, and input/output reflection, I will get the same CRC as that of WireShark. But STM32 CRC result didn't change at all.
------------------ will continue in answer -----------------

