在循环冗余校验系统中利用_较为广泛的循环冗余校验技术

在嵌入式产品的应用中,经常需要处理系统数据在存储或传输过程中的完整性问题。

完整性是指数据在其生命周期中的准确性和一致性。这些数据可能存储在EEPROM/FLASH中或基于通信协议传输,也可能因外部干扰或程序错误,甚至系统入侵而被破坏。如果在使用前没有检查这些数据,产品功能可能无效。在某些特定领域,严重时可能危及用户的财产甚至生命安全。

本文将谈谈在STM32中广泛使用的循环冗余校验技术和一些具体的经验。

CRC:循环冗余校验(CRC)是一种错误检测算法,通常用于通信协议或存储设备中,检测原始数据的意外变化。可以简单理解为按照一定的算法计算出有用数据后提取一个特征值,并附加到有用数据上。在应用中,根据特定算法从有用数据中提取的特征值与预先存储的特征值进行比较。如果相等,则验证通过,否则验证失败,以识别数据是否异常。

为什么要检查数据完整性?

数据在存储和传输过程中可能会发生变化。以数据通信应用场景为例,常见错误大致有两种故障模式:

单比特错误:只有一个数据比特有错误,如下图所示:

BurstError:码流中有两个或两个以上的数据位有错误,如下图所示:

为什么可能出现这些位错误?对于电子系统通信,涉及物理层、链路层、通信介质等。物理层主要是利用一定的编解码原理对原始的二进制数据进行调制,然后将调制后的信号通过发送电路传输到传输介质上,接收端利用接收电路进行接收和解调,从而将信息还原成二进制码流。在这个过程中,介质可能受到干扰,接收电路、发射电路、调制电路、解调电路都可能因为一些干扰原因而无法工作,产生误码。这时,如果没有一个好的机制来保证数据的正确性,比如某个飞控系统中的一些控制命令,某个车载系统中的CAN报文数据,系统直接利用这些错误的数据来控制被控对象(比如电机、发动机),严重时会造成不可估量的生命财产灾难。

存储系统中的数据也是如此。一般来说,系统在开机时会从物理存储介质中加载系统参数,如一些校准数据。如果介质的某些位损坏或者软件bug导致数据被误用而没有进行数据完整性检测,这样的数据会直接应用于系统控制,同样会造成安全隐患。

因此,数据完整性检测的重要性不言而喻。常见的数据完整性算法有很多,如简单的异或校验、CRC循环冗余校验、FEC前向纠错算法等。循环冗余校验广泛应用于嵌入式系统中,如通信协议制定、数据存储、压缩和解压缩算法等。

循环冗余校验使用二进制除法作为算法原理,具有强大的错误检测机制。二进制除法可以用少量的硬件逻辑电路实现。对于软件代码的实现,有两种思路和策略:查表法和移位计算法。查表法以空间换时间,位移法以时间换空间。

什么是循环冗余校验?

循环冗余校验的核心数学算法原理是基于循环码,在不增加原始数据信息的情况下扩充信息,以极小的存储代价存储其冗余特性。该算法是W. Wesley Peterson在1961年发明的。

这里的n位二进制数据是有效的信息载荷。(它可能是传输或存储的有用信息)

根据CRC算法,计算M位冗余码,即根据CRC校验多项式结合CRC算法,从以前的有效数据中提取特征冗余码,这才是真正意义上的冗余。

实际传输或存储的是n m位二进制数据。

这里引出一个概念:多项式,在CRC校验算法中可以这样理解和表达:

它的本质是十进制的数学表示,这里是二进制,所以X是2。

基本算法处理过程如下所示:

假设要发送的有效数据是一个二元多项式M(x),校验多项式P(x)是发送方和接收方约定的,双方都知道。这里介绍几个多项式表示的意义和相关的处理流程:

接收器在接收到数据后执行CRC校验。余数为0,检查通过。

其实CRC的本质是用二进制多项式除法寻找冗余码的计算过程,无论软件查表法、移位计算法还是纯硬件逻辑电路实现,本质都是一样的。对数字逻辑电路使用移位运算更有利,因为它几乎不占用CPU时间。

常见CRC校验多项式

常见的CRC校验多项式运算符有哪些?

不同的校验多项式复杂度不同,但从应用的角度看又有什么区别呢?从应用角度来看,主要体现在错误诊断率上。我们来看看CRC-16和CRC-CCITT的检错效果:

可以完全检测单比特和双比特错误。

奇数比特错误

可以检测长度为16位或更少的突发错误。

可以以99.997%的概率检测到长度为17位或更长的错误。

选择不同的校验多项式算子,误码诊断的成功率不同,当然计算代价也不同。我们来查一下权威的IEC标准。下图取自《IEC61508-7》。

从上面可以看出,CRC-8可以诊断出99.6%的误码率,而CRC-16可以将误码率提高到99.998%。

注意:IEC61508是电气/电子/可编程电子安全相关系统的功能安全。

随着技术的发展,各行各业都使用了大量不同的校验多项式生成器。

STM32的CRC硬件外设

如下图所示,STM32内置了CRC-32硬件计算单元,实现了固定多项式0x4c11db7(十六进制表示),可应用于以太网报文校验码的计算。

所有STM32产品都有CRC外设,为CRC计算提供硬件支持,节省应用代码的存储空间。CRC校验值可用于验证传输中数据的正确性,并检查存储中数据的完整性。在IEC60335,也接受CRC校验来检查闪存的完整性。在FLASH完整性校验的应用中,需要预先计算整个FLASH的CRC校验值(不包括CRC值的最后一个字节),放在FLASH的末尾。在程序启动或运行的过程中,整个FLASH的CRC校验值用同样的方法再计算一次,然后与FLASH末尾地址空间中存储的CRC值进行比较。

EWARM从v5.5版本开始就支持STM32芯片的CRC计算。计算整个FLASH的CRC校验值并在FLASH结束时保存的过程可以在IAR中完成。通过配置EWARM的CRC计算参数,自动进行整个FLASH空间的CRC计算,计算结果放在内部FLASH空间的末尾。

也许你会问,这有什么应用价值?以基于单片机程序的升级为例。在代码升级过程中,如果不检查bootloader升级接口传入的二进制程序文件,就不能及时发现升级过程中的代码错误。相反,如果在原代码中加入校验码,升级程序在收到升级文件后会做校验计算,并与待升级文件末尾的校验码进行比较。如果不匹配,就放弃升级,这样就不会把无效甚至潜在的安全隐患写入芯片。

修改链接文件,指定校验和在FLASH中的存储位置,并在链接文件中添加以下语句。

放在ROM _ region { ro section }的末尾。校验和};

该语句指定CRC的值放在闪存空间的末尾。是整个FLASH空间的结尾,而不是应用程序代码的结尾。这样,CRC值的位置是固定的,不会随着码长而改变。

配置校验和页面的参数。

IAR校验和页面描述(6.4及以上版本)

IAR的校验和页面分为两部分:

红线圈出的部分:定义需要计算CRC的范围和FLASH中空闲字节的填充值。

校验和计算参数设置部分:

校验和大小:选择校验和的大小(字节数)。

对齐:指定校验和的对齐方式。如果不填写,默认为2字节对齐。

算法:选择校验和的算法。

补码:是否需要补码计算。选择“原样”意味着不执行补码计算。

位顺序:位输出的顺序。MSB优先,每个字节的高位优先。LSB优先,各字节低位优先。

反转字内字节顺序:对于输入数据,反转字内每个字节的顺序。

初始值:由校验和计算出的初始值。

校验和单元大小:选择迭代的单元大小,按8位、16位或32位迭代。

STM 32 CRC外设使用默认配置时的IAR配置。

STM32CRC外设配置:

POLY=0x4C11DB7(CRC32)

Initial_Crc=0Xffffffff

输入/输出数据不反转。

输入数据:0x08000000~0x0801FFFB。(最后4个字节用于存放计算出的CRC值)

在实验过程中,发现“对齐”似乎对计算的CRC值没有影响。但是“字内字节顺序反转”的配置和“校验和单位大小”有一定的关系。如果后者选择32位,则前者无法检查;另一方面,如果后者选择8位,则必须检查“word中的反向字节顺序”。也可以参考下图进行设置:

在6.4版之前,IAR没有“校验和单位大小”选项.参考配置如下:

如何编写代码

如上所述,该应用可用于验证Flash中的数据,参考代码如下:

克钱德尔。Instance=CRC

克钱德尔。init . defaultpolynomial use=DEFAULT _多项式_ ENABLE

克钱德尔。INIT . DefaultInitValueUse=DEFAULT _ INIT _ VALUE _ ENABLE;

克钱德尔。init . InputDataInversionMode=CRC _ input data _ INVERSION _ NONE;

克钱德尔。init . OutputDataInversionMode=CRC _ output data _ INVERSION _ DISABLED;

克钱德尔。input data FORMAT=CRC _ input data _ FORMAT _ WORDS;

if (HAL_CRC_Init(CrcHandle)!=HAL_OK)

{

Error_Handler()。

}

pdata=(uint 32 _ t *)ROM _ START;

uwCRCValue=HAL _ CRC _ Calculate(CrcHandle,pdata,ROM _ SIZEinWORDS);

总结

对于CRC应用,你也可以根据多项式算子写一个纯软件方案,网上有很多现成的代码。其基本思想无非是查表法和移位计算法。区别在于,一个为了计算效率牺牲存储空间,一个为了节省存储空间牺牲计算时间。至于如何选择,要看设计的系统,一般要看应用场景。

块数据是通过CRC算法计算出来的,有些文章和标准把这种冗余码称为签名。在实际应用中,将计算有效数据得到的校验码与预存的校验码进行比较,如果相等,则校验通过,否则校验失败。当然,原始数据和存储的校验码也可以传入校验算法,如果结果为0,则校验通过,否则校验失败。

对于数据通信,通常在消息的末尾添加有效数据的校验码,然后接收方检查接收到的消息的数据完整性。

审计和安