|
粉丝分享 | 图说CRC原理应用及STM32硬件CRC外设 ' ~- j: s3 O& C9 h5 r/ ^在嵌入式产品应用中,常常需要应对系统数据在存储或者传输过程中的完整性问题。 0 u+ ~$ u! a6 w) H 所谓完整性是指数据在其生命周期中的准确性和一致性。这些数据可能存储在EEPROM/FLASH里,或者基于通信协议进行传输,它们有可能因为外界干扰或者程序错误,甚至系统入侵而导致被破坏。如果这些数据在使用前不做校验,产品功能可能失效。在一些特定领域,严重时可能会危及用户财产甚至生命安全。! t: c1 V+ R1 l7 y2 S3 j / [ C# ?* C. `: C5 j 本文就来聊聊使用较为广泛的循环冗余校验技术,以及在STM32中的一些具体使用体会。 0 L% T9 B* K5 `5 |$ X 所谓循环冗余校验(CRC:Cyclic Redundancy Check)是一种错误检测算法,通常在通信协议中或存储设备中用于检测原始数据的意外变动。可以简单理解成对有用数据按照一定的算法进行计算后,提取出一个特征值,并附加在有用数据后。在应用中将有用数据按照特定的算法提取特征值与预先存储的特征值进行比对,如相等则校验通过,反之校验失败,从而识别出数据是否异常。 : [) @ t& K/ ], V. w2 E 为何要校验数据完整性(Data Integrity)? 2 p# Q0 O% J5 S. O7 L% U i$ ?' q数据在存储以及传输的过程中可能发生异动。以数据通信应用场景为例,常见的错误大致有两种失效模式:6 b0 p- o3 m. @+ n" k 单个位错误(Single Bit Error):仅仅某一个数据位出现错误,如图:% s% e4 C* L. `3 r
% i5 ?8 ^2 c6 t( b: C1 m- L' d$ K $ ]7 i: m& N- X7 t. } 存储系统中的数据也是一样。一般来说,系统在上电运行时会从物理存储介质装载系统参数,比如一些校准数据。如果由于介质的某些位被破坏,或者软件bug导致数据被误操作了,而没有数据完整性检测,这样的数据直接被应用于系统控制,一样会造成安全隐患。 . Q) e. L6 [( `$ N+ ?) B . w! w4 R$ f6 x: {; L# R0 u0 r; I 所以,对于数据完整性检测的重要性不言而喻。常见的数据完整性算法有很多种,比如简单的异或校验、CRC循环冗余校验、FEC前向纠错算法等等。而循环冗余校验在嵌入式系统中应用非常广泛,在通信协议制定、数据存储、压缩解压算法等都有广泛的应用。+ J& c5 v+ x2 Z6 [ 2 D5 }' R9 D) V) G: x) o 循环冗余校验使用二进制除法作为算法原理,具有强大的错误检测机制。对于二进制除法使用少量的硬件逻辑电路就可实现。至于软件代码实现,有查表法和移位计算两种思路及策略。查表法以空间换时间,移位计算法以时间换空间。7 b+ C2 e& o2 T& x3 w! @: y5 \& x $ D& k7 T6 R+ G! n f! F# u, g 何为循环冗余校验? 循环冗余校验的核心数学算法原理基于循环码,在不增加原始数据的信息基础上扩展了信息,以极小的存储代价存储其冗余特征。该算法是W. Wesley Peterson 于1961年发明的。9 [2 m/ P& U4 J/ Y% f$ F. ? @7 b
·根据CRC算法计算出m位冗余码,即根据该CRC校验多项式结合CRC算法从前面有效数据中提取出特征冗余码,这就是冗余的真实含义。! A' B% ^! }+ }7 _ ·实际传输或者存储的就是n+m位二进制数据。 ( o: l/ x' N( i& R) h) [% o6 C ! W2 N4 w& P# [% @ m 这里引出一个概念:多项式,在CRC校验算法中多项式可做如下理解及表示:! {9 G0 v7 t3 |% V5 l/ E
5 F3 @: {/ b1 j0 K. ~- D 其基本的算法处理过程示意如下:
其实CRC的本质就是二进制多项式除法求取冗余码的计算过程,无论软件的查表法、移位计算法,还是纯硬件逻辑电路实现,本质都是一样的。对于数字逻辑电路利用移位计算则更具优势,因为几乎不占用CPU时间。: [ \' D5 ^. ?! y # `1 i& U% M. A- u ^$ T; C# H; ~+ O 常见的CRC校验多项式 " F6 g, b# b ], C O 常见的CRC校验多项式算子有哪些?( J! L6 r3 Q6 K/ F* o
不同的校验多项式,除了复杂度有差异外,从应用角度看有什么差异呢?从应用角度看主要体现在错误诊断率。不妨看看CRC-16以及CRC-CCITT的错误检测效果: 2 ^7 ?) x- z" g/ J % J, C: ?1 ]' a- z; [9 X 可完全检测出单bit及双bit错误 奇数个位错误/ c5 @2 @% }: H+ r; ~ ' g7 o. ^8 k& @& o, T 能检测出16位长度及小于16的突发错误1 s0 q; g) C6 M; h' x: e5 D ' Y" Z" ?. q" Q6 X+ @5 Q' x 能以99.997%的概率检测出长度为17位及以上的错误 0 R4 Y+ I4 L/ B0 d- r: x 选择不同的校验多项式算子,其位错误诊断成功率是不一样的,当然其计算开销也不一样。我们来查查权威的IEC标准看看。下图截自《IEC61508-7》。
+ P' [% A- U. z. G 注:IEC61508是国际电工委员会功能安全标准(Functional safety of electrical/electronic/programmable electronicsafety-related systems)。 2 u ~$ h0 Z' Z2 N 技术发展至今,已有大量不同的校验多项式生成器被各行各业使用。下面是来自wikipedia截图,供大家参考:
STM32的CRC硬件外设 ( i9 l) \! N; X 如下图,STM32内置了一个CRC-32硬件计算单元,实现了一个固定多项式0x4C11DB7(16进制表示),可应用于以太网报文校验码计算。# L( w+ \" z" s
EWARM 从 v5.5 版本之后开始支持 STM32 芯片的 CRC计算。计算整个 FLASH的 CRC 校验值并保存在 FLASH末尾的过程,可以在 IAR 中完成。通过配置EWARM 的 CRC 计算参数,自动对整个 FLASH 空间进行 CRC 计算,并将计算结果放到 内部FLASH空间 的末尾。 8 O, B# [) _% x# F9 S( r 或许你会问,这有什么应用价值呢?不妨以基于MCU程序的升级为例。在代码升级过程中,如果不对bootloader升级接口传入的二进制程序文件做校验,就无法及时发现升级过程中发生的代码错误。相反,如果原始代码添加了校验码,升级程序在接受到升级文件后做校验计算,并与待升级文件末尾的校验码进行比对,如果不匹配则放弃升级,这样就不至于将无效的甚至有安全隐患的代码写进芯片。 ' l# X' D6 j7 P$ V, T/ `7 Z) k 2 S0 e1 g. q* @8 `. L% Z" M, _3 } 修改 Link 文件,指定 checksum 在FLASH 中的存储位置,在 Link 文件中增加下面语句。# v9 a2 {! p8 L5 N ], n/ C
3 u# {7 X+ o: K- z/ y 8 e/ a3 R9 O. Z1 ?, ?$ U' T; [' r 配置 Checksum 页面的参数 2 O+ a H' u" }. M+ ~ ( g+ J# L6 J% ?3 y) @ IAR Checksum 页说明(v6.4 及以上)/ Z- R4 a1 i" ^; I% |) \3 w6 _6 s
4 F$ n) a' l. R# \) c; R 红线圈出的部分:定义了FLASH 中需要计算 CRC 的范围和空闲字节填充值。/ P& P5 _/ g1 K; R* e# K+ ] 3 H- F- H8 [ x! ~( p 9 K; i) T: ?* w) G% S8 L- q# R% W/ b checksum 计算参数的设定部分:4 |* ~$ y( W. a* X% ` Checksum size :选择 checksum 的大小(字节数). h: s `% B k, @* L4 s5 n Alignment:指定 checksum 的对齐方式。不填的话默认 2 字节对齐。 : u1 x+ ~9 `+ X) l8 P4 O1 M8 J Algorithm:选择 checksum 的算法 / P% ], N0 P" V0 a ( e( z/ F+ V% L6 c, H( t Complement:是否需要进行补码计算。选择“As is”就是不进行补码计算。2 F' V9 T5 W8 q4 t2 l . _* w3 u; T. K2 O Bit order:位输出的顺序。MSB first,每个字节的高位在前。LSB first,每个字节的低位在前。 5 L6 J+ [% U* \2 R9 @ Reverse byte order within word:对于输入数据,在一个字内反转各个字节的顺序。& q) k' C7 z: G" J; \7 f: U& R : z1 [2 }7 b8 @& ~* F Initial value:checksum 计算的初始化值 * e* ?8 F8 o9 g- c9 D : x; b! {. X! a0 m3 V6 K2 g5 d# K Checksum unit size :选择进行迭代的单元大小,按 8-bit,16-bit 还是 32-bit 进行迭代。 T' s! e. z0 k / D1 ]( K! S2 _" g 5 k! J8 a' L) w' ]# I8 g( v STM32 CRC 外设使用默认配置时 IAR 的配置/ `( R8 v- M) j1 M. M0 b' G 8 Y* X( H6 h8 c- { STM32CRC 外设的配置: ·POLY= 0x4C11DB7(CRC32) 1 T% [3 a" U d# h% O1 q- F ·Initial_Crc = 0Xffffffff 0 d9 C. \& c- b3 t" k% U ·输入/输出数据不反转 ·输入数据:0x08000000~0x0801FFFB。(最后 4 个字节用来放计算出的 CRC 值) * y' B* e: F" S # ]: K, E7 Q. L. K3 L2 F6 \. o 在实验的过程发现, ”Alignment ”似乎对计算出的 CRC 值没有影响。但“Reverse byte order within word ”与“Checksumunit size ”这两项的配置有一定关系。如果后者选择 32-bit,则不能勾选前者;反之如果后者选择 8-bit,则一定要勾选上“ Reverse byte order within word ”。也可以参照下图进行设置:
代码怎么写? 如前文描述,这个应用可以用于对Flash中数据进行校验,参考代码如下:
小结 , g6 L% B Q2 w9 ^' t2 U, K$ K+ ~9 @9 p( x N8 Z 对于CRC应用,还可以根据多项式算子编写纯软件方案,网上有很多现成的代码。其基本思路无外乎查表法以及移位计算法。差异在于一个牺牲存储空间以换取计算效率,一个牺牲计算时间而节省存储空间,至于如何选择,则根据所设计的系统综合考虑,一般根据应用场景来定。 将块数据利用CRC算法计算出冗余码,有的文章、标准称这个冗余码为签名。实际应用时计算有效数据所得校验码与预存校验码进行比较,相等则校验通过,反之则失败。当然,也可以将原数据与所存校验码一起传入校验算法,所得结果为0则校验通过,反之失败。* c0 k7 d# M/ e6 L& B 对于数据通信,一般会在报文的尾部添加有效数据的校验码,再由接收方校验收到报文的数据完整性。) r8 M' ^4 T) K; q+ { 2 H' r0 g6 p% W 8 T, u2 C6 Y, d4 m. l9 Y1 r # a5 @' L! o( U& Y7 g3 A U# E |
| 谢谢分享~~ |
| 谢谢分享~~ |
| 好资料,就是看得有点懵圈 |
| 谢谢分享!! |
无刷直流电机控制应用+基于STM8S系列单片机---电子书
MCSDK FOC应用详解
STM32F10xxx 正交编码器接口应用笔记 及源代码
基于STM32定时器ETR信号的应用示例
《无刷直流电机控制应用 基于STM8S系列单片机》
STM32定时器触发SPI逐字收发之应用示例
【银杏科技ARM+FPGA双核心应用】STM32H7系列10——ADC
【银杏科技ARM+FPGA双核心应用】STM32H7系列57——MDK_FLM
【STM32图书分享之九】—《STM32F 32位ARM微控制器应用设计与实践》
STM32 USB的程序,包含固件、驱动和测试用的应用程序
微信公众号
手机版