本帖最后由 caizhiwei 于 2020-12-8 22:47 编辑
CRC是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。
图2:来自手册
STM32 全系列产品都具有 CRC 外设,对 CRC 的计算提供硬件支持,节省了应用代码存储空间。CRC 校验值既可以用于传输中的数据正确性验证,也可用于数据存储时的完整性检查。在 IEC60335 中,也接受通过 CRC 校验对 FLASH 的完整性进行检查。在对 FLASH 完整性检查的应用中,需要事先计算出整个 FLASH 的 CRC 校验值(不包括最后保存CRC 值的字节),放在FLASH 的末尾。在程序启动或者运行的过程中重新用同样的方法计算整个 FLASH 的 CRC 校验值,然后与保存在 FLASH 末尾地址空间的 CRC 值进行比较。 EWARM 从 v5.5 版本之后开始支持 STM32 芯片的 CRC计算。计算整个 FLASH的 CRC 校验值并保存在 FLASH末尾的过程,可以在 IAR 中完成。通过配置EWARM 的 CRC 计算参数,自动对整个 FLASH 空间进行 CRC 计算,并将计算结果放到 内部FLASH空间 的末尾。 或许你会问,这有什么应用价值呢?不妨以基于MCU程序的升级为例。在代码升级过程中,如果不对bootloader升级接口传入的二进制程序文件做校验,就无法及时发现升级过程中发生的代码错误。相反,如果原始代码添加了校验码,升级程序在接受到升级文件后做校验计算,并与待升级文件末尾的校验码进行比对,如果不匹配则放弃升级,这样就不至于将无效的甚至有安全隐患的代码写进芯片。 参考代码如下: /*-1- 配置CRC外设 */
CrcHandle.Instance = CRC;
/* 默认二进制多项式使能 */
CrcHandle.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
/* 默认初值设置 */
CrcHandle.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
/* 输入数据不反转 */
CrcHandle.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
/* 输出数据不反转 */
CrcHandle.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLED;
/* 输入数据基本单元长度为32bit */
CrcHandle.InputDataFormat = CRC_INPUTDATA_FORMAT_WORDS;
if (HAL_CRC_Init(&CrcHandle) != HAL_OK)
{
/* 初始化错误 */
Error_Handler();
}
pdata = (uint32_t*)ROM_START;
/*##-2- 调用HAL库利用硬件CRC外设对ROM区计算CRC-32校验码*/
uwCRCValue = HAL_CRC_Calculate(&CrcHandle, pdata, ROM_SIZEinWORDS);
对于CRC应用,还可以根据多项式算子编写纯软件方案,网上有很多现成的代码。其基本思路无外乎查表法以及移位计算法。差异在于一个牺牲存储空间以换取计算效率,一个牺牲计算时间而节省存储空间,至于如何选择,则根据所设计的系统综合考虑,一般根据应用场景来定。 将块数据利用CRC算法计算出冗余码,有的**、标准称这个冗余码为签名。实际应用时计算有效数据所得校验码与预存校验码进行比较,相等则校验通过,反之则失败。当然,也可以将原数据与所存校验码一起传入校验算法,所得结果为0则校验通过,反之失败。 对于数据通信,一般会在报文的尾部添加有效数据的校验码,再由接收方校验收到报文的数据完整性。 学习资料附件:
How_to_calculate_CRC_value_in_IAR_and_KEIL.pdf
(834.48 KB)
|