1 汽车的功能安全要求不低于飞机
线控系统(xbywire)是指用电信号直接指挥电驱动器,实现控制的目的,由于信息共享容易实现、复杂的各种计算和逻辑功能可添加,可达到精确的直接或间接地控制目标。另外,由于省去液压或及气动能源制备系统,管线也被电缆代替,成本和重量有可能下降,减少了漏油等环境污染风险。但是由于难以实现机械后备,在可能发生安全事故时少了人为干预的手段,可信赖性全要靠系统保证,这就对系统和各组成部分提出了严格的要求。这种要求现在已用功能安全来表达。
飞机上采用线控系统已有较长历史,当汽车应用线控系统时,人们往往以为它的要求低于飞机,从成本考虑,希望用较为简单的方案来实现,现在看来很难达到目标。要从两方面来分析。
ISO61508标准的出发点是根据事故发生的后果造成的人身、财产损失大小,以及可能发生事故的平均概率来确定功能完整性等级,即功能安全设计的目标。虽然设计目标是针对单个被控设备与相应控制装置设定的,没有考虑保护的系统的绝对数量,但是从人类的整体而言,笔者认为系统的绝对数量是一个需要考虑的因素,否则积累的伤害与损失会很大。从这个角度看,汽车的保有量可能是飞机的一万倍,虽然一次飞机事故的损失可能是汽车的一千倍,但是同样的线控系统失效概率下,汽车对社会造成的损失将是飞机的10倍。
关于汽车线控系统的功能安全要求是否比飞机低,以前笔者认为汽车在地上,大不了停下来,对功能安全的要求自然比飞机低,这是片面的理解。汽车的工作环境有其区别于飞机的地方。例如在高速公路上以100 km/h开动时,它与邻车或路沿的距离只有1 m,一旦发生故障,偏航这1 m可能只是几十ms的事。也就是说,可能的安全措施必须在这几十ms内产生作用。相比之下,飞机在空中相距甚远,即使发动机停转,重启在数秒内完成也没太大问题。当然,飞机在着落时也有类似的要求。但是汽车可能连续几小时都在这种状态下工作,而飞机只是在起降的10 min内有这种要求,假定线控系统的平均失效概率相同,那么时长的不同使汽车就更容易出事。另外,飞机每次起飞前的检查使出事的概率会下降很多。
从这两点来讲,可能需要投入更多的精力去研究汽车的线控技术,取得的成果也可以在飞机上使用,这为一般民用企业进入高科技行业提出一种新的可能。
2 安全用CPU的进展和问题
线控系统加上安全措施才能实现功能安全要求,一般来说,一个系统由信号输入,经计算处理、输出到执行器,再经过被控对象形成闭环。如果某一环节出错,则无法闭环,所以要加冗余,让正常的部分继续工作。现在计算处理部分是由微处理器完成的,由于微处理器复杂性很高,它的失效物理位置往往难以百分之百地确定,除了尽量具体追溯外,还要根据行为结果的合理性判断错误是否已经发生。
为了满足汽车线控系统的功能安全要求,一些汽车电子半导体厂家推出了专门的CPU芯片,例如Freescale的MPC5643L、TI的TMS570。它们的共同特点是采用双核结构,锁步运行,然后对双核的计算结果进行比较,如果不同,就表示有一个核的中间步骤出错了,立即通知错误处理单元,用户可以在软件中设计出错的处理方案。
为了避免共因失效,TI的TMS570在芯片的布图上使两个核相互垂直,指令执行上差2个时钟节拍。
两种芯片对存放数据和程序的RAM、FLASH采用了错误校正编码(ECC),如果有1位错就直接校正,如果超过1个,则通知错误处理单元。
两种芯片都设计了内置的自诊断单元(BIST),电源、ADC定时诊断,出错时通知错误处理单元,例如MPC5643L可以每10 ms进行一次自诊断。
对于系统设计者而言,这样的CPU虽然有两个核,但是其工作方式表现在它的输出上,要么是正确地输出结果,要么是报错而停止输出。例如MPC5643L[1]告诉用户,芯片只提供失效静默(failsilent)或失效指示(failindication)功能。图1把常规的单CPU结构与MPC5643L进行了比较。
图1 两种1oo1D结构
图1(a)中是通常在一个CPU时为了计算可靠,常常采用指令复执的方法,几次对同一输入进行重复计算,选择合理的结果作为输出。计算的方法可以是同一程序执行几次,直到结果相同,或者3中取2的方法,也可以采用不同的程序甚至算法,计算结果的异常则按重复出错、出错超时甚至应用的相关知识判断。异常时可以阻断输出并报告管理部分,即实现了失效静默和失效指示的功能。
图1(b)是MPC5643L两个核锁步运行的情况,它把以前单核的串行复执变成了并行的复执。两个核锁步运行实际上只是一种扩大诊断覆盖面的措施。当然,它加快了执行速度,减少了原来串行执行时中间结果存取可能带来的新的出错源。但从本质上讲,它是一个1oo1D子系统。moutofn代表一种冗余的硬件架构,可以实现n选m,1oo1是从一个工作通道里选出一个正确结果。
1oo1D是一个带诊断的单通道子系统,它是没有硬件冗余的,因为失效时静默,所以不能提供原定的服务。对于简单的功能,安全状态也简单。有了失效指示,系统设计者就可以安排一个替代的导致安全状态的输出。例如,失效时关电源,或者重启系统。汽车比较复杂,仅有失效指示是不够的。为了达到容许一个硬件错,我们需要1oo2D系统,现在的可靠性和功能安全研究已经确定1oo2D系统可以达到ASID的汽车功能安全完整性最高等级,不一定需要更贵的2oo3系统。所谓1oo2D系统是指有两个计算处理的通道,带有诊断,有一个通道被诊断出失效时,该通道的输出被禁止,另一个通道的输出维持正常的功能,所以它可以容许有一个硬件错。而用两个MPC5643L的1oo1D系统并联就可以构成1oo2D系统,此时,实际上的核(signal processing engine)及其RAM、FLASH已经达到4组,从经济上讲比2oo3系统已无优势。
用1oo1D来构成1oo2D时也需要同步机制,当有一个通道出错后,需要有一个恢复工作的机制,这里涉及功能安全应用的分类。一种应用属于偶尔使用(on demand),例如化工对象的过压保护,它的保护系统必须在过压时正常工作,此时保护系统内即使遇到错误,也要正常工作。保护系统启动后,对象进入安全状态。对象要恢复正常工作,往往伴随整个设备与保护系统的大修,或安全完整性的测试,保护系统内的错误被积累下来的概率很小。另一类是应用要连续工作,保护系统也要连续工作,它内部的错误如果不能及时消除,就有可能积累下来,从而突破1oo2D只能对付一个错误的极限,造成失效。
对于空间粒子轰击或电源干扰引起的RAM和FLASH内位翻转现象(single event upset),MPC5643L和TMS570采用了ECC编码,可以纠正1位错和多位错的报错,但是内核的保护是不足的,对于同为触发器的内核中的寄存器可能的翻转未有保护,这样造成的计算出错也许可以在1oo1D诊断中发现,但是错误的纠正比较困难。例如MPC5643L有两个CPU内核e200z4,CPU中的通用寄存器GPR0~GPR31大量用于指令中的变址[2],如果出错,则取数存数的目的地址就会出错,这种错误会潜伏下来,不一定在当前输出中反映出来,即1oo1D未必能发现这个错误,用现在功能安全的术语讲就是残留故障(residual fault)。当别的应用从这个地址取数时,就会南辕北辙。假如在本任务中用到这个数,即使在当前输出中反映出来,1oo1D可以报错,但是只有两个内核的通用寄存器GPR的值仍无法判断谁对谁错,只能等待该通用寄存器的下一次刷新。然而在刷新的周期之前,很难说不会有新的错误发生。此时用1oo1D构成的1oo2D的两个通道就可能同时失效了。
MCU经历了无代码和数据保护阶段,到MC9S12P128对代码加ECC保护的阶段,再到MPC5643L对代码和数据加ECC保护的阶段,还将进入对代码、数据和寄存器加保护的阶段。实际上有人早已做了这些工作,只是现在对民用应用的安全要求不断提高,才使这些研究显得重要了。内核的保护可以有各种方案,例如欧洲航天局(European Space Agency)2001年完成的32位基于SPARC V8的容错的芯片LEON[4],它对触发器只用了3次冗余的表决方案,在不断的时钟刷新中,依靠表决结果,使错误立即被刷掉。
如果要在两片MPC5643L构成的1oo2D系统中实现通用寄存器纠错,理论上是有可能的,因为第一个错误发生时存在正确运行的一片MPC5643L,需要做的是把发生错误时涉及的通用寄存器内容复制过去。不过,这要求设计完整的同步机制,并考虑时间开销是否影响性能,难度较大。
3 安全状态的确定是根本
嵌入式仪表/装置要达到的功能安全是要与应用一起考虑的,即所谓的safety instrumented system。一个仪表的安全失效概率足够小,并不代表用它的系统就一定安全,这与用法有密切关系。不能说一个仪表是达到某安全完整性等级的仪表,甚至不能说和以前的仪表有什么不同故而叫它安全仪表,这是个基本概念,所以不宜译为安全仪表系统。一个系统有它原来要完成的功能,现在要添加一些措施,使完成基本功能中出错时(操作人员的错误、硬件失效或环境变化)仍然是安全的,要保证安全性。“instrumented”是杜撰的词,字典里都没有,笔者理解为借助于工具或措施,所以可以译为保障了安全性的系统。
所有功能安全的方法目的都是在有故障时把系统导向安全状态,硬软件的安全完整性等级往往只考虑失效概率,而失效属于何种性质与应用有着密切的关系,有的被划为安全失效的部分可能实际上并不安全,所以安全状态的确定是根本。通过从上而下的分解过程才能获得下面子系统或部件必需的安全状态。这里故障恢复时间也是一个重要的因素,也许非常短时间的故障沉默可以忽略不计,但这是要仔细分析以后才能判断的,最令人担心的是在故障沉默期间又发生新的故障,而破坏时间短可忽略不计的假设。
例如,汽车主要运送人或货物,它的工作环境是高速公路和一般道路。在高速公路上发动机、变速箱、刹车系如发生故障,则突然停车就会有追尾的危险,在一般道路上突然加速会有追尾的危险。2010年丰田车突然加速致使人员伤亡,2013年大众车行驶中突然失去动力,变速箱挡位显示的“死亡闪烁”引起恐慌,这表明不安全状态与工作环境的密切关系。这两件事的事故原因现在尚无定论,也不在这里讨论。如果突然加速,则此时的安全状态就不是立即停车,因为有突然减速的追尾风险,在原有车速初始条件下逐渐减速可能才是安全状态。如果发生机械故障可能伤及变速器,也不应立即进入空档,在人与物的伤害中要两害相权取其轻。
历史上作为软件工程典型案例的Therac 25放射治疗仪事件[5],由于设备或操作上的意外故障,造成病人受到超剂量的照射,最终死亡。其中总结了很多系统性的软件功能安全的必要做法,这与现在ISO61508的功能安全概念是一致的。安全状态是每一个局部出错时都要顾到的“纲”,纲举才能目张。例如我们常常在程序的空闲部分添加空指令和跳转到重启入口的命令,以防止受干扰后程序意外跳转,落入原有指令的半截之中,错误解释构成非法循环。简单地这样处理是不够的,缺少了对安全状态的考虑,因为重启未必是安全状态,还必须有全部设备状态的还原,医疗设备重启可能要走消毒过程,可能要把消毒剂送到未退出病人的设备中甚至体内。另一方面,设备状态还原也不一定是对病人安全的。在Therac 25案中就有4个例子重启造成过量的例子,在那里设备与人没有直接约束,但是主要的工作流程中积分函数照射剂量是积分,重启必须顾及已有的积分量,这就涉及关键数据的保护,断点再入地址的保护等内容。
回到第2节讨论的安全用CPU,MPC5643L对故障的响应是这样的[3]:所有由硬件手段检测到的错误(例如冗余检查器、自检、ECC、电压和时钟监视)将报告到中央故障收集和处理单元,后者将器件引导到相应的组态好的fail save状态,防止故障扩展到系统级。它的failsafe状态是下述的二者之一:器件处在关断或reset时I/O为三态;对关键性错误,输出一个报错信号。在正常运行和reset之间不断切换,且不带关断是不算作failsafe的。
CPU关断时,I/O为三态可能不是系统出错时的安全状态,这与应用有密切的关系。子系统只是大系统的一部分,子系统故障沉默的特性只适合部分系统,而安全状态是要子系统故障继续工作的应用,需要更周密的设计。