evading evading - 4 months ago 58x
Linux Question

Matching CRC32 from STM32F0 and zlib

I'm working on a communication link between a computer running Linux and a STM32F0. I want to use some kind of error detection for my packets and since the STM32F0 has CRC32 hw and I have zlib with CRC32 on Linux I thought it would be a good idea to use CRC32 for my project. The problem is that I won't get the same CRC value for the same data on the different platforms.

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>

uint8_t byte0 = 0x00;
uint32_t crc0 = crc32(0L, Z_NULL, 0);
crc0 = crc32(crc0, &byte0, 1);
printf("CRC32 value of %" PRIu8 " is: %08" PRIx32 "\n", byte0, crc0);

CRC32 value of 0 is: d202ef8d
which matches the result on several online calculators.

It seems though that whatever settings I use on the STM32 I can't get the same CRC.
I have found a flowchart on how the CRC hw calculates its value in an application note from ST but I can't figure out how it's done in zlib.

Does anyone know if they are compatible?

[edit 1] They both uses the same init value and polynomial.

[edit 2] The STM32 code is relatively uninteresging since it's using the hw.

/* Default values are used for init value and polynomial, see edit 1 */
CRC->DR = (uint8_t)0x00;
uint32_t crc = CRC->DR;


From the documentation, it appears that your STM32 code is not just uninteresting — it is rather incomplete. From the documentation, in order to use the CRC hardware you need to:

  1. Enable the CRC peripheral clock via the RCC peripheral.
  2. Set the CRC Data Register to the initial CRC value by configuring the Initial CRC value register (CRC_INIT).(a)
  3. Set the I/O reverse bit order through the REV_IN[1:0] and REV_OUT bits respectively in CRC Control register (CRC_CR).(a)
  4. Set the polynomial size and coefficients through the POLYSIZE[1:0] bits in CRC Control register (CRC_CR) and CRC Polynomial register (CRC_POL) respectively.(b)
  5. Reset the CRC peripheral through the Reset bit in CRC Control register (CRC_CR).
  6. Set the data to the CRC Data register.
  7. Read the content of the CRC Data register.
  8. Disable the CRC peripheral clock.

Note in particular steps 2, 3, and 4, which define the CRC being computed. They say that their example has rev_in and rev_out false, but for the zlib crc, they need to be true. Depending on the way the hardware is implemented, the polynomial will likely need to reversed as well (0xedb88320UL). The initial CRC needs to be 0xffffffff, and the final CRC inverted to match the zlib crc.