Skip to main content
Visitor II
June 7, 2017
Solved

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

  • June 7, 2017
  • 3 replies
  • 4230 views
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?

    This topic has been closed for replies.
    Best answer by Tesla DeLorean
    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.

    3 replies

    Super User
    June 12, 2017
    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

    Graduate II
    June 12, 2017
    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

    Visitor II
    June 13, 2017
    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.

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

    Graduate II
    June 13, 2017
    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.

    Visitor II
    June 13, 2017
    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,