How to configure STM32H7 hardware CRC to match zlib CRC32 in Python
You can configure the STM32 CRC32 peripheral to match the CRC32 algorithm used by zlib (which is available in Python’s zlib
module):
According to crccalc.com, the zlib CRC32 (there called CRC-32/ISO-HDLC
) uses Init=0xFFFFFFFF
, XorOut=0xFFFFFFFF
and byte-wise reversal of input & output.
On the STM32H7, you can use the HAL to configure the CRC peripheral to match this:
void Init_CRC32() {
__HAL_RCC_CRC_CLK_ENABLE();
// Reset CRC
_hcrc.Instance = CRC;
_hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
_hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
_hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
_hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
_hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
HAL_CRC_Init(&_hcrc);
}
uint32_t CalculateCRC32(void* data, size_t length)
{
// Compute the CRC
uint32_t crc_result = HAL_CRC_Calculate(&_hcrc, reinterpret_cast<uint32_t*>(data), length);
// Invert to obtain ZLIB CRC32
return crc_result ^ 0xFFFFFFFF;
}
The following test code can be used to validate the result
void TestCRC32() {
uint32_t crc = CalculateCRC32((void*)"DEADBEEF", 8);
printf("CRC32 of 'DEADBEEF': %08X", crc);
// When testing, always include a non-divisible-by-4 number of bytes
crc = CalculateCRC32((void*)"Hello, World!", 13);
SendLogMessageF("CRC32 of 'Hello, World!': %08X", crc);
}
Output:
CRC32 of 'DEADBEEF': E24CEE98
CRC32 of 'Hello, World!': EC4AC3D0
Equivalent Python code
The python code for this is extremely simple as it uses the built-in zlib
module:
import zlib
def calculate_crc32(data: bytes) -> int:
return zlib.crc32(data)
print(f"CRC32 of 'Hello, World!': {calculate_crc32(b'Hello, World!'):08X}")
print(f"CRC32 of 'DEADBEEF': {calculate_crc32(b'DEADBEEF'):08X}")
Output:
CRC32 of 'DEADBEEF': E24CEE98
CRC32 of 'Hello, World!': EC4AC3D0
You can even do it inline:
import zlib
print(f'{zlib.crc32(b"DEADBEEF"):08X}') # E24CEE98