本帖最后由 Flower1 于 2017-12-28 16:43 编辑
1 发生错的原因与现有对策
MCU在工作时会受到干扰,在一些空间场合,可能遇到粒子轰击而产生稳态的翻转,即所谓single event upset。而一般工业场合是电源传导干扰,受干扰时,电源电压会瞬间超出或者略微超出MCU的名义工作电压,线路的稳定性就无法保证。由于各单个逻辑电路工艺过程中总会有微小差异,电源电压的略微超出会在最弱的逻辑电路中造成指令读错误和数据读写错误。这种错误最终表现为数据的错误。 国外对DRAM出错的研究已做得很多,在参考文献中转述了出错的概率:“谷歌(Google)使用了大量服务器,2009年的大规模统计。出错的概率是2.5~7×10-11error/bit/h。”即8G RAM每小时会有5个错。 现在对于有功能安全要求的系统,安全等级为SIL2时,出错的概率应小于10-7”/h。现在控制器所用的MCU的Flash与RAM的大小已达128 K~1 Mb,参考上述概率,如果缺少程序的保护,将会有1M×7×10-11 error/h=7×10-5 error/h,这远大于功能安全要求的出错概率。 从功能安全的角度,系统中任何影响功能的错误都是应该被检测出来的,如果这个错误危及人类生命或造成设备的重大损失,那么就必须有防范的措施,必要时就必须纠正错误。然而要达到这种要求是很难的,需要付出很大的代价。以数据错误为例,人们常常重复计算多次,然后把占多数的结果代表正确的结果。这样,数据分享前的结果都要经表决,否则发现错会太晚,影响一致性。这就需要更多的硬件资源与开发成本。即便如此,如果作为表决器的环节仍是MCU的一个程序,它仍然可能会受错误指令的干扰,未能完全拦住错误。 为了节省成本,更多的应用并没有采用这种冗余与表决的方法。它们往往以不死机作为目标,只要不死机,由控制对象来的新信息就可以重算出新的正确结果。即使上一次算出的错了,其后果也只延续了一个采样周期。这种策略对有累积效应的应用是无效的,就像参考文献中讨论的积分功能会失败。又如运行结果与过程密切相关的应用,例如可编程控制器(PLC),数据的错误会导致控制逻辑的混乱。 保证不死机的主要措施是采用看门狗技术,如果程序走飞,在一定时间内没有复位计时器,计时器就会溢出,产生MCU的重新启动,重新初始化可以纠正损坏了的数据。看门狗技术是不管数据正确性的,因为指令错了程序未必走飞,而指令错了数据错的可能性极大。 2 错误现象与错误校正方案 MCU的指令在读取时发生错误就会产生不同的执行结果,在参考文献中以8051的MOV指令为例,当有一位读错时就变成跳转、除法、减法、交换、增1等等指令。实际上大部分MCU都会有指令错而执行结果错的问题,因为这些指令内没有检验错的机制。MC68HC11的LDA指令有1位错时可能转为加法、减法、送立即数到累加器B、送状态存器、送堆栈指针等指令,如表1所列。
虽然笔者注意到这种出错的可能性比较早(1990年),但是在写参考文献时(2008年)并不知道Freescale公司(2005年)的16位[url=]单片机[/url]中已经有了对指令添加检错与纠错的措施。参考文献中提到:“当系统遇到强干扰时,CPU在读取指令或数据时可能出现错误,如果指令或数据仅仅是某一位出现错误,ECC模块会自动纠正这一位的错误,使系统照常运行,如果出现二位或二位以上的错误,则ECC会以中断方式通知CPU,出现了读程序错或读数据错。” 根据参考文献,Freescale公司的16位[url=]单片机[/url]MC9S12P128的Flash部分32位的程序有7位特征,构成纠错编码(error correction code),可以纠正1位错和发现2位错。Flash部分16位的数据有6位特征,构成纠错编码ECC,可以纠正1位错和发现2位错。因此对指令的检错纠错已经是批量使用了。最近AMD也推出了G系列嵌入式SoC平台,它也采用了ECC技术。 ECC技术在企业级服务器中使用比较早,它考虑了DRAM的特点,例如内存插条中由多个芯片构成,就从每个芯片的对应位集合起来,再加校验位。然后又有对应的诊断设计,可以找出出错多的内存条,以便更换。所以它与[url=]单片机[/url]上的使用情况还是有区别的(更换是不可能的),直接照抄是不必要的。 从Freescale公司的ECC可知,它的海明距离HD=3,而且采用了纠错措施。如果仅仅检错,那么实现起来更简单一点。检测出错后的处理措施就比较容易设计,例如产生中断,把该指令重取,由于是硬件中的措施,不必考虑添加入栈/出栈保护现场的动作,开销很少。如果必要,还可以在另外的地方保存出错统计信息,以及触发更复杂的保护措施。 3 简化报错与纠错方案 从现在单片机的发展趋势来看,因为32位单片机价格的下降,市场将分化为8位与32位两极。在中国8位机主要是8051体系,已经培育了较大的市场和大量熟悉的人才,而且也有自制8051的能力,所以在8051上添加检验码是合理的选择。如果增加了这一功能,无疑会提高使用8051系统的可信赖性,提升产品档次,延长产品的寿命周期。另一方面,其实现也比较简单,相信基于ARM的32位机也会添加这种指令检验机制,成本也要上升。 对MCU程序加保护的厂家还不多见,即使是Freescale公司也还没有对所有的MCU添加保护,因为添加保护是要增加成本的,所以添加保护的方法是值得研究的课题。 对于8位指令代码检错,可以选择低阶次的CRC。由参考文献可知可以选4位CRC,其生成多项式是G=X4+X+1。它可以保证HD=3的数据字长为11位,已超过所需的8位。这里因为数据字8位是一次取出,所以CRC是并行计算的,由数据字到CRC的求取的方法推导如图1所示。
假定数据字用D表示,生成多项式用G表示,Gm为最高阶的系数,等于1。那么习惯的做法在除到Dn位时,判断Dn值。若Dn=1,则将G和D的对应位对齐,用模2加法求取余数,Mn-i=Dn-i+Gm-i,用余数Mn-i代替原来的Dn-i移位。如果Dn=0,则不做加法,Mn-i=Dn-i,然后移位,也可以说用余数Mn-i代替原来的Dn-i移位。我们的目的是直接由D来产生余数,所以做了修改。修改方法是,当对齐后的Gm- i=1时,取Mn-i=Dn-i+Dn。当Gm-i=0时,对应项不做模2加。现在证明这两种方法是等效的: Dn=0,Gm-i=0时,习惯方法Mn-i=Dn-i;修改方法Mn-i=Dn-i。 Dn=0,Gm-i=1时,习惯方法Mn-i=Dn-i;修改方法Mn-i=Dn-i+Dn=Dn-i。 Dn=1,Gm-i=0时,习惯方法Mn-i=Dn-i+Gm-i=Dn-i;修改方法Mn-i=Dn-i。 Dn=1,Gm-i=1时,习惯方法Mn-i=Dn-i+Gm-i=Dn-i+1;修改方法Mn-i=Dn-i+Dn=Dn-i+1。 现在对G=X4+X+1时8位指令的数据字用修改方法求取CRC各位的值,为了阅读方便,将数据字的各位用数字代表,例如7代表D7。参与模2加的各位就以各数字连写在一起。例如CRC的最高一位是7 532,它代表D7、D5、D3、D2的模2加法结果。通过建立真值表,它们最后都可以用组合逻辑来实现,所以在取指完成后就立即可以判出是否有错。求取并行解CRC逻辑的过程如图2所示。
这种推导[url=]并行CRC[/url]值的方法也可以用于较长的指令,当然,为了避免手算的错误,应该以程序来求,这不是难事。 8位指令用4位CRC保护开销是大了一点,但是它的保护强度也大了,对于16位的指令程序,用二次8位保护,有4个错是肯定可以检测出来的,如果像Freescale技术用掉6位保护,只能保证有2个错可以检测出来。所以这是折中的方法。 对于16位指令,可以用5位CRC保护,参考文献中G=X5+X2+1可以在26位数据字长上获得HD=3。对于32位指令,可以用6位CRC保护,参考文献中G=X6+X+1可以在57位数据字长上获得HD=3。由此可见,如果仅检错而靠重传作纠错,校验项比Freescale都要省一位,用重取指令的方法可以节省开销。 |