c++stm32f4crc8

STM32F4 HAL_CRC_Calculate() gives false results


I have a STM32F429ZI (Discovery Board) and this really simple code, calculating the CRC8:

uint32_t data[5] = { 0x28, 0x4f, 0x4c, 0x43, 0x29 };
uint8_t crc = HAL_CRC_Calculate(&hcrc, data, 5);

The result of crc is 0x51. https://crccalc.com/ gives me 0xF3. I got this code from here. They also got 0xF3.

I don't understand, how the conversion from crc32 to crc8 works in this code. So i tested a crc32:

uint32_t data[5] = { 0x28, 0x4f, 0x4c, 0x43, 0x29 };
uint32_t crc = HAL_CRC_Calculate(&hcrc, data, 5);

This time I get 0x554C8351. crccalc.com gives me 0x14822BBD instead. Again a different result.

The STM32F4 doesn't have any configuration possibilities for the CRC. What am I do wrong? I want to calculate CRC8 with polynom: X8 + X2 + X + 1

I found another guy, sharing his code to calculate CRC8: https://community.st.com/t5/stm32-mcus-security/crc-calculation-for-8-bit-values/td-p/191270 But again, I couldn't match his results.

So my question:

How do I calculate the CRC8 of a uint8_t array in STM32F4xx in C++ correctly?


The CRC of the F4 can not be configured. So the initialization is directly from STM32CubeMX:

void MX_CRC_Init(void)
{
  hcrc.Instance = CRC;
  if (HAL_CRC_Init(&hcrc) != HAL_OK)
  {
    Error_Handler();
  }
}

HAL_StatusTypeDef HAL_CRC_Init(CRC_HandleTypeDef *hcrc)
{
  if (hcrc == NULL)
  {
    return HAL_ERROR;
  }

  assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));

  if (hcrc->State == HAL_CRC_STATE_RESET)
  {
    hcrc->Lock = HAL_UNLOCKED;
    HAL_CRC_MspInit(hcrc);
  }

  hcrc->State = HAL_CRC_STATE_READY;
      return HAL_OK;
}

Solution

  • If you look at the Application note by ST for the STM32 CRC hardware (AN4187), in chapter 3 you will see a table about how the hardware CRC support on STM32 is implemented.

    In that table, you can see that for the STM32F4 processor (left-most column, along with STM32F1, STM32F2 and STM32L0), it only supports CRC32, with a fixed initial value of 0xffffffff and a fixed polynomial of 0x4c11db7.

    Correction for this paragraph (doesn't change the overall picture): I've just noticed that crccalc doesn't always update properly, and the 0x51 was just a fluke coincidence. What actually happens in your case is that you call HAL_CRC_Calculate() with a vector of 5 32bit values (where each individual value fits into 8 bits). So you are effectively passing the following byte sequence into CRC32: \x00\x00\x00\x28\x00\x00\x00\x4f\x00\x00\x00\x4c\x00\x00\x00\x43\x00\x00\x00\x29. If you enter that at crccalc.com, you'll see that the CRC32/MPEG-2 variant will match the result you get on the MCU, namely 0x554C8351. If that is then truncated to an 8bit value, you'll get 0x51. And these are both the values that you see in hour code.

    On the other hand, other STM32 processors (such as STM32F0, STM32F3, etc. - see the other column in the table in chapter 3 of the application note) support programmable values in their CRC implementation. And there you can tell it to use CRC8, potentially with a different init and/or polynomial.

    This means that on your specific MCU:

    Or you could switch to one of the MCUs with fancier CRC support if you are still early enough in your project design and having hardware-accelerated CRC8 is important to what you want to do. (And your other project constraints can be met with the different model, of course.)