Showing results for 
Search instead for 
Did you mean: 

Generate Hardware CRC from MCU and validate on other software system.

Associate II

I have to generate CRC on MCU (STM32L476VG). I am using code as below for generating CRC.

uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
      uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
      for (index = 0U; index < BufferLength; index++)
             hcrc->Instance->DR = pBuffer[index];
        temp = hcrc->Instance->DR;
       /* Change CRC peripheral state */
       hcrc->State = HAL_CRC_STATE_READY;
       /* Return the CRC computed value */
    return temp;

Can you give some reference code for validating this CRC on another machine (OS environment) .

My data packet and CRC as per below.

072300210c000001f900000000000a0001001e000000000000012c0000 3a7040ef

|----------------------------------Data Packet-------------------------------------------|----CRC----|

Please let me know if you need any further information.

Thank you,


Associate II

Please help me to identify What's wrong in attached code snippet . As i have to pass as a byte array.

I have read you suggestion . But could not figure out. What's is wrong here: As i don't know about crc generation method. ( if you not comfortable with Qt data types then suggest equivalent c++ code snippet )

unsigned int Dialog::Bytearraycrc32bCalculate(QByteArray message, size_t l)
    size_t i, j;
    unsigned int msb;
    quint32 calcrc = 0xFFFFFFFF;
    for(i = 0; i < l; i++) {
       // xor next byte to upper bits of crc
       qDebug() << QString::number((unsigned int), 16);
       calcrc ^= (((unsigned int)<<24);
       for (j = 0; j < 8; j++) {    // Do eight times.
             msb = calcrc>>31;
             calcrc <<= 1;
             calcrc ^= (0 - msb) & 0x04C11DB7;
    qDebug() << QString::number(calcrc, 16);
    return calcrc;         // don't complement crc on output

How exactly did you generate the example data in your first post?

Try a simpler/shorter packet. Try to show us in the settings producing the expected values.


The default STM32 method consumes 32-bits at a time, not 8-bits, and does so with unhelpful endian ordering.

Your example data is 29 bytes long, this is not divisible by 4, and clearly not going to work with the code in your top-post.

Perhaps show the calling method, and try with another pattern that's suitably sized.

The CRC from your second code example is


uint8_t data[] = {


0x00,0x01,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x2c,0x00,0x00 };

uint32_t user_example(uint32_t crc, uint8_t *message, size_t length)
  size_t i, j;
  for(i=0; i<length; i++)
    crc^= message[i] << 24;
    for(j=0; j<8; j++)
      uint32_t msb = crc>>31;
      crc <<= 1;
      crc ^= (0 - msb) & 0x04C11DB7;

Or faster

uint32_t Crc32Fast(uint32_t Crc, uint8_t *Data, size_t Length)
  static const uint32_t CrcTable[16] = { // Nibble lookup table for 0x04C11DB7 polynomial
    0x2608EDB8,0x22C9F00F,0x2F8AD6D6,0x2B4BCB61,0x350C9B64,0x31CD86D3,0x3C8EA00A,0x384FBDBD }; //
    Crc = Crc ^ ((uint32_t)*Data++ << 24); // Apply 8-bits
    // Process 8-bits, 4 at a time, or 2 rounds
    Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // Assumes 32-bit reg, masking index to 4-bits
    Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; //  0x04C11DB7 Polynomial

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

@Community member​ does this link capable of calculating hardware generated CRC by STM32.

@Community member​  Are you trying to explain that code with HAL_CRC_Calculate() function is not appropriate?

If HAL_CRC_Calculate() function is appropriate then please give some crc calculation portal like this.

This portal help me to do further debug.

The CRC unit in STM32 is configurable, its configurability depending on the particular model.

However, as Clive (TeslaDeLorean) said, if you write data by words, they are treated as big endian, which is not a configurable item. I took the data from your initial post, omitted the last byte (so that I had only 28 bytes = 7 words), swapped endianity and fed it to to get the above result:


Luckily, in 'L4, you can write data into CRC_DR byte by byte, doing that you can bypass the problem of endianity. It appears that CubeL4 supports this by setting hcrc->InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES


@Community member​  yes, this is what i want.

Can you please provide equivalent c++ code for that or give some reference for it.

You're not using it appropriately.

The problem with online-calculators (portals) is that CRC's are relatively complex, and have multiple valid implementations that can be architecture specific. They are also, by their nature, very sensitivity to bit/byte ordering through the feedback/polynomial terms, they are designed to catch subtle bit level variations in relative long streams of data bits. Tens of thousands of ways to fail, one or two ways to succeed.

The performance of the STM32 32-bit CRC is undefined when your data doesn't fit cleanly, and you need manage that with strongly defined behaviour about how you pad data, rather than pull extraneous bytes out of memory which aren't part of the message/data dispatched to the other end doing the checking/validation.

I don't use the online methods as I have a reasonable grasp of the underlying methods/math. I've posted C code to multiple threads showing an STM32 compatible calculation method.

As I recall the L4 has a programmable CRC peripheral so other more standard/normative methods can be implemented. Your might want to consider more standard/accepted protocols and usage patterns rather than crowbar the poor STM32 default method into applications for which it is a poor fit.

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

I don't use Cube.

Read UM1884, HAL CRC Generic Driver chapter.