2017-06-07 09:46 AM
I need to have a PC algorithm that produces the same result as the hardware CRC (using an F0 chip).
I can produce identical results between hardware and software when doing a byte by byte crc calculation.
I would like to use the word based calculation since it is much faster.
However, the result produced using the word by word in the hardware CRC is different than the one produced using the byte by byte option. I've tried all combinations of bit and byte ordering on the word value in the software based calculation (taking 4 bytes at a time and re-ordering bits and bytes) but I haven't come up with a combination that works.
It isn't necessary for me to have the hardware word vs byte calculation produce the same result (would be good if it did though). However the software and hardware calculations must obviously match.
Does anyone have any tips to share on this?
Solved! Go to Solution.
2017-06-13 07:50 AM
The real problem is more likely the fact that the STM32's
0x04C11DB7
polynomial is applied 32-bit at a time with a byte ordering which is backward compared to the architecture. Thus applying 8-bit at a time in the normal sense results in a different output. It is unrelated to bit-reversal or inversion.A significant subset of the parts don't support a configurable/programmable CRC peripheral.
2017-06-12 12:32 PM
Give us the details, code you used both for the hw and sw calculation, and example inputs/outputs.
JW
2017-06-12 12:37 PM
For the default 32-bit implementation of the STM32 family
Otherwise be MORE specific, there are dozens of CRC polynomials, shift directions, endian orders and sizes
2017-06-13 03:38 AM
hi, Lorne!
I guess you just confused by the parameters of a crc-32 (and its relatives)calculation.
I think,
once you figure out the correspondence between these parameters and STM32s' hardware setting,
you can find out bunch of algorithms in the internet.
------------------------------------------------------------
Usually, parameters for a CRC-32 (
and its relatives)
includes:CRC Polynomial
Initial Values
Reflected Input
Reflected Ouput
Final Exclusive Or
If you input a word 0x1A2B3C4D to a crc-32 related algorithm, with all these params, we can make a table like this
NameResultPolynomialInital ValueReflect InputReflect OutputFinal Xor Out
CRC-320x51668534
0x04C11DB7
0xFFFFFFFF
truetrue0xFFFFFFFF
CRC-32/MPEG-2
0xB88C78300x04C11DB7
0xFFFFFFFF
falsefalse0x
00000000
CRC-32b0x477387CF
0x04C11DB7
0xFFFFFFFF
falseflase0xFFFFFFFF
CRC-32c
0xB6985EB70x1EDC6F41
0xFFFFFFFF
truetrue0xFFFFFFFF
CRC-32d
0x8412194D0xA833982B
0xFFFFFFFF
truetrue0xFFFFFFFF
CRC-32q
0x26F7D0140x814141AB
0x00000000
false false0x
00000000
so, here take stm32F09x for example , and suppose you are using HAL library.
(Note that not every stm32 implement all these parameter, i.e. some param are fixed to default, and some param are modifiable.)
CRC_HandleTypeDef hcrc;
CRC-32 ParametersSTM32 Hardware config
CRC Polynomial
Default polynomial is
0x04C11DB7
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE
Initial Value
Default is 0xFFFFFFFF
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE
Reflected Input
true ==> hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE
false ==> hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE
Reflected Output
true==> hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE
false==> hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE
Final Exclusive orhere hardware NOT implemented, equivalent to Exclusive with 0x00000000
So, let's end this tedious long story with some examples,
If you set up your crc handle like this:
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENALBE;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_WORDS;
HAL_CRC_Init(&hcrc);
then you get
CRC-32/MPEG-2.
Similarly, if you set up like this
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENALBE;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_WORDS;
HAL_CRC_Init(&hcrc);
and you finally Xor the result with 0xFFFFFFFF (simply take a negation) by your software,
then you get your dream CRC-32 !!
:)
----------------------------------------------------------------------------------------
Hope I didn't miss anything,
the above tables are copied from my code snippets few months ago.
----------------------------------------------------------------------------------------
2017-06-13 07:50 AM
The real problem is more likely the fact that the STM32's
0x04C11DB7
polynomial is applied 32-bit at a time with a byte ordering which is backward compared to the architecture. Thus applying 8-bit at a time in the normal sense results in a different output. It is unrelated to bit-reversal or inversion.A significant subset of the parts don't support a configurable/programmable CRC peripheral.
2017-06-13 08:41 AM
In the version of the HAL library I was using there was an option in the CRC init to do the calculation byte by byte or by 32 bit word at a time. I assumed originally that setting translated to a hardware setting in the CRC module but when I examined the HAL library code I found out that the library code was converting the byte by byte stream into big-endian 32 bit words to feed into the CRC calculation register. When I changed the library code to use little-endian then the results matched between the two.
What really threw me off originally is that the big endian byte by byte calculation result matched the software routine I was using so I assumed it was correct and I couldn't figure out how to change the word by word calculation to get the same result - it was impossible.
For the benefit of others this is the calculation that I use that matches the result of the hardware CRC:
u32 ccitt32_updcrcWord(u32 crc, const void *pDataV, int byteQty)
{
const u8 *pC = pDataV;
int n = 3;
while(byteQty--) {
crc = (crc<<8) ^ crc32_tableCCIT[(crc>>24) ^ pC[n]];
if ( !n-- )
{
n = 3;
pC += 4;
}
}
return crc;
}
... and the table is the one that starts with these values...static const u32 crc32_tableCCIT[256] =
{ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,