2022-07-12 08:32 AM
I've been implementing I2C communication between F401CCU6 and Nucleo F746ZG, while adding CRC I got different outputs, Nucleo provides configurable CRC peripheral, while F401 is by default set to 0x4C11DB7 (https://www.st.com/resource/en/reference_manual/rm0368-stm32f401xbc-and-stm32f401xde-advanced-armbased-32bit-mcus-stmicroelectronics.pdf#page=68&zoom=100,89,116)It also provides reseting initial value to 0xFFFF FFFF, ("The CRC calculator can be reset to 0xFFFF FFFF with the RESET control bit in the CRC_CR register. This operation does not affect the contents of the CRC_IDR register")
I've set Nucleo CRC polynomial, init value to match those on BlackPill. Calculated value matches with CRC-32/MPEG-2 standard (available at https://crccalc.com/ for example).
Did anyone has experienced this too?
2022-07-12 08:56 AM
Details matter.
Observe/compare exactly how do you (and any "library" you've used is now your program and your responsibility) set up and feed the CRC register in both cases. Observe/compare during execution - perhaps single-stepping in disasm, to see exactly how data are fed - how the CRC registers content changes, as being fed.
> Calculated value matches with CRC-32/MPEG-2 standard
In the 'F7 or in the 'F4? As they don't match each other, only one of them may match any "standard".
Probably, data need to be fed byte-wise to achieve this. Or, in words they have to be swapped, as the CRC peripheral is big endian (MSByte-first), unlike the common expectation.
JW
2022-07-12 09:25 AM
I've been testing it that way:
uint8_t test_crc[] = "12345";
uint32_t crc_val = HAL_CRC_Calculate(&hcrc, (uint32_t*)test_crc, sizeof(test_crc)-1);
Nucleo spits out 0xBD9AB747 as it should be according to crccalc, the point is, if F4 polynomial is 0x4C11DB7 as stated in manual, and init value was reset to 0xFFFF FFFF accordingly, then why the result is different (0x5355ffb1)?
I've used both
__HAL_RCC_CRC_CLK_ENABLE() and MX_CRC_Init() and when fed different data it
2022-07-12 09:33 AM
... and when fed different data it gives different result so i guess its working (somehow)
2022-07-12 09:38 AM
The HAL_CRC_Calculate() "BufferLength" parameter is NOT the number of BYTES, it is the number of "words". On the F401 the "word" size is fixed at 32bits. On the F7xx it is programmable/configurable to be 8, 16 or 32 bits.
So if you use the code posted above on the F4xx, you are feeding a buffer of 5 bytes but telling it to read 5 each 32-bit words (i.e. 20 bytes).
2022-07-12 09:42 AM
It expects to be feed 32-bit words, and a word count, doesn't it?
The STM32F4 and several others in the family have a very specific and inflexible implementation, ill suited to the endian ordering at a bit and byte level.
On-line calculators often have difficulty with awkward and specific implementations due to the sensitivity of the CRC's in general to bit level nuances.
2022-07-12 09:43 AM
>>On the F7xx it is programmable/configurable to be 8, 16 or 32 bits.
Yes, but often a bit of a beast to wrangle. Demonstrably usable for 7, 9 and 24-bit CRC too
2022-07-14 01:48 PM
So, for example:
uint8_t test_crc[] = "1234";
uint32_t crc_val = HAL_CRC_Calculate(&hcrc, (uint32_t*)test_crc, 1);
Should be working? Are these 4 bytes making one 32 bit word?
What would be the proper implementation of calculating CRC of any uint8_t array?
2022-07-14 02:03 PM
Which CRC?
The default STM32 one processes this in the 4 3 2 1 sense
uint32_t Crc32(uint32_t Crc, uint32_t Data)
{
int i;
Crc = Crc ^ Data;
for(i=0; i<32; i++)
if (Crc & 0x80000000)
Crc = (Crc << 1) ^ 0x04C11DB7; // Polynomial used in STM32
else
Crc = (Crc << 1);
return(Crc);
} // sourcer32@gmail.com
ie 0x34333231 in a leftward shifting sense, would expect it to yield 0x050DC953 or 0xC2091428 depending on if the initial value were 0 or 0xFFFFFFFF
2022-07-14 02:18 PM
>>What would be the proper implementation of calculating CRC of any uint8_t array?
I've got a lot of posts on these topics.
If you want to use the hardware here, to do say a CRC-32 matching those of PKZIP, you need to process all the words, feeding each as a bit-reversed form (there's a Cortex-M instruction for that), and then handle the remaining bytes via a software method.