cancel
Showing results for 
Search instead for 
Did you mean: 

How do I resolve the different hardware CRC calculation when using word vs byte option

Lorne Vaasjo
Associate II
Posted on June 07, 2017 at 18:46

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?

1 ACCEPTED SOLUTION

Accepted Solutions
Posted on June 13, 2017 at 14:50

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.

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

View solution in original post

5 REPLIES 5
Posted on June 12, 2017 at 21:32

Give us the details, code you used both for the hw and sw calculation, and example inputs/outputs.

JW

Posted on June 12, 2017 at 21:37

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

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Zt Liu
Senior III
Posted on June 13, 2017 at 12:38

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

truetrue

0xFFFFFFFF

CRC-32/MPEG-2

0xB88C7830

0x04C11DB7

0xFFFFFFFF

falsefalse

0x

00000000

CRC-32b0x477387CF

0x04C11DB7

0xFFFFFFFF

falseflase

0xFFFFFFFF

CRC-32c

0xB6985EB7

0x1EDC6F41

0xFFFFFFFF

truetrue

0xFFFFFFFF

CRC-32d

0x8412194D

0xA833982B

0xFFFFFFFF

truetrue

0xFFFFFFFF

CRC-32q

0x26F7D014

0x814141AB

0x00000000

false false

0x

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.

----------------------------------------------------------------------------------------

Posted on June 13, 2017 at 14:50

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 13, 2017 at 15:41

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,