STM32H7硬件CRC与srec_cat生成的CRC32不匹配,求正确配置
STM32H755 Bootloader CRC32硬件校验与srec_cat结果不匹配问题
构建系统配置(Makefile片段)
# Convert ELF to BIN (fill up to 128KB - 4) $(BIN): $(ELF) | $(BUILD_DIR) $(OBJCOPY) -O binary $< $(BUILD_DIR)/tmp.bin $(SREC_CAT) $(BUILD_DIR)/tmp.bin -binary -fill 0x00 0x0000 0x1FFFC -o $@ -binary # Append CRC32 (little endian) at the last 4 bytes (0x1FFFC) $(CRC_BIN): $(BIN) | $(BUILD_DIR) $(SREC_CAT) $< -binary -crc32-l-e 0x1FFFC -o $@ -binary
CRC32校验和以4字节小端格式存储在地址0x1FFFC处。
Bootloader端校验代码(简化版)
#define APPLICATION_ADDRESS 0x08040000U #define APPLICATION_MAX_SIZE (128 * 1024) // 128 KB #define APPLICATION_CRC_ADDRESS (APPLICATION_ADDRESS + APPLICATION_MAX_SIZE - 4) static uint32_t verify_application_crc(uint32_t expected_crc) { uint32_t data_size_bytes = APPLICATION_MAX_SIZE - 4; // Compute CRC on flash contents using hardware CRC uint32_t computed_crc = HAL_CRC_Calculate(&hcrc, (uint32_t*)APPLICATION_ADDRESS, data_size_bytes); if (computed_crc != expected_crc) { printf("CRC mismatch! HW=0x%08lX, Expected=0x%08lX\n", computed_crc, expected_crc); return -1; } return 0; }
当前CRC外设配置
hcrc.Instance = CRC; hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE; // 0x04C11DB7 hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE; // 0xFFFFFFFF hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE; hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE; hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
问题现状
srec_cat -crc32-l-e生成的CRC32已通过第三方工具验证正确;- 自定义软件CRC32函数计算结果与srec_cat完全一致;
- STM32硬件CRC外设计算结果始终不匹配,已尝试调整所有HAL CRC初始化参数(多项式、初始值、输入/输出反转、数据格式),仍无法匹配。
需求
需配置STM32H7硬件CRC模块,使其计算结果匹配srec_cat -crc32-l-e生成的标准CRC-32/ISO-HDLC(多项式0x04C11DB7,初始值0xFFFFFFFF,输入/输出反射,最终异或0xFFFFFFFF)。
解决方案
1. 正确的CRC外设初始化配置
STM32H7的硬件CRC模块支持输入/输出字节级反转,需匹配CRC-32/ISO-HDLC的要求,以下是正确的初始化代码:
hcrc.Instance = CRC; hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE; // 0x04C11DB7,符合CRC-32/ISO-HDLC标准 hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE; // 0xFFFFFFFF,符合初始值要求 hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE; // 字节内位反转,对应输入反射要求 hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE; // 整体位反转,对应输出反射要求 hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; // 按字节处理数据 if (HAL_CRC_Init(&hcrc) != HAL_OK) { Error_Handler(); }
2. 硬件CRC计算后的补充处理
STM32硬件CRC模块不会自动执行最终异或0xFFFFFFFF的操作,需手动补充这一步:
static uint32_t verify_application_crc(uint32_t expected_crc) { uint32_t data_size_bytes = APPLICATION_MAX_SIZE - 4; uint32_t computed_crc = HAL_CRC_Calculate(&hcrc, (uint32_t*)APPLICATION_ADDRESS, data_size_bytes); // 执行最终异或0xFFFFFFFF,匹配CRC-32/ISO-HDLC标准 computed_crc ^= 0xFFFFFFFF; if (computed_crc != expected_crc) { printf("CRC mismatch! HW=0x%08lX, Expected=0x%08lX\n", computed_crc, expected_crc); return -1; } return 0; }
3. 关键注意点
- 输入反转模式:必须选择
CRC_INPUTDATA_INVERSION_BYTE,对应每个字节内的8位按位反转,满足CRC-32/ISO-HDLC的输入反射要求; - 输出反转模式:必须开启
CRC_OUTPUTDATA_INVERSION_ENABLE,对应硬件计算后的32位结果整体按位反转; - 最终异或:STM32硬件CRC无此默认操作,必须手动异或0xFFFFFFFF才能匹配标准结果;
- 数据长度单位:
HAL_CRC_Calculate的第三个参数长度单位由InputDataFormat决定:设置为CRC_INPUTDATA_FORMAT_BYTES时,长度为字节数,需与数据处理逻辑保持一致。
内容的提问来源于stack exchange,提问作者Shiddesh
相关产品推荐
相关产品推荐

