3、软件代码
软件的可靠性是随着时间的推移,可靠性逐渐增加的,这一点区别于电子可靠性、机械可靠性。电子可靠性服从指数分布,在整个生命周期内,其失效率为一个常数;机械可靠性因为磨损、腐蚀、运动等因素的存在,随时间推移可靠度会下降。因此也就有了软件可靠性设计的一个特定规律和注意事项。
既然需要通过时间推移,通过不断改进,软件可靠性得到提升。那么软件的可维护性就是一个大问题了。这也是为什么软件工程管理方面特别关注软件文档、注释的原因了。但做这些要求的人只是人云亦云,并不理解如此做法的真正动机。至于注释如何去做、变量如何命名、软件配置管理如何操作,这里面既有很常规的方法,也有一些我们司空见惯然而是错误的做法。信手举上几个值得注意的细节供参考。
变量定义时宜将变量类型的变量名程中体现于其中;如AD_result_int、Cal_result_float等。这样为的好检查,防止数据类型的强制转换或强制赋值时出现数据类型的错误;
注释要充分;
代码的布局风格宜统一,便于阅读查找;
不可出现非受控的default流程,所有数值和变量,不论是调用函数时赋予的、读取接口读进来的、还是中间变量计算出来的,在应用前都宜作数据有效性的判断,并对判定的所有可能结果均做受控的对应处理。
… …
关于软件可维护性编程方法方面的文章资料在网上是铺天盖地,不予赘述,综合采用之即可。很多文章把软件可维护性编程规范推荐做成企业的嵌入式软件可靠性设计规范,实在是有点以偏概全,有失偏颇的,用一句娱乐圈的话来说,“爱情是生活的重要内容,但它不是生活的全部”,软件可维护性编程方法亦然。
软件代码在执行中容易出现的下一个问题是跑飞,程序指针受到干扰,跳转到了一个非受控位置,执行了不该执行的代码。如果执行了不该执行的代码,如果在程序中加入了足够的变量判断、读值判断、状态检测判断等,那倒还好了,后果也不会太严重,甚至最终还是可能自己跑回来的。但有一种跑飞是比较可怕的,一般我们在ROM中存放的程序目标代码是1-3字节的指令,就是最多3条字段的目标码组成了执行动作,如果程序指针跑飞到了某个3字节指令的第2个字节上的时候,执行的后果是什么,可就真的没人知道了,即使在程序上作了足够的数据判错、逻辑跳转的防范措施,结果也不会好。而且ROM一般是不可能全部都被程序代码填满的,总有富余空间,富余空间中的默认内容是啥,这些默认字节是否也会导致一些操作呢?单片机中的默认空间是0FFH,DSP的我没查过,大家有兴趣查一下,跳到这些字段里,也是容易出麻烦的。
好了,不再罗嗦,直接给出解决方法吧,就是每隔一段程序代码或控制区域,就人为放置上几个NOP指令,在NOP指令后放置一个长跳转的ERR处理程序。注意NOP最少放置3个,这样任何的跑飞最多只能占用2个NOP,第三个NOP一样还是能把程序代码揪回来,揪回来后就执行ERR处理程序。
如果碰到安全性、可靠性等级要求比较高的程序,推荐的处理方法可以采用热备份的处理方法,即用两段代码同时执行同一个功能,执行的结果进行对比,如果一致则放行通过,如果结果不一致,咋处理就看您的喽。但是… …国人有的是办法,为了图省事,你领导不是要求我编热备份程序吗,那好,我就把原来的代码复制一遍,重新插入到某个地方,您这和明朝时代冯保太监(还是严嵩、张居正阿?拿不准了,大家有兴趣的翻看《明朝那些事儿》查阅下)玩的没啥两样,自己写奏章,自己给自己审批奏章。既然是备份就是为了防止一个人出问题,那最好的办法自然是不同的人来编这段,如果原理计算方法上也不同,数据采集通道也不同,那就过年带娶媳妇的,好上加好了。
安全性和可靠性的编程细节注意事项还有很多,窥一斑难见全豹呵,诸位仁兄一起努力钻研了。
4、数据、变量
变量的定义是为的避免各种混淆,同一程序内数据和数据的混淆、不同人读程序时对变量理解上出现的二义性、视觉效果上容易出现的错误(字母的“o”和数字的“0”,字母的“l”和数字的“1”)。这里要遵循一个“要么相同,要么迥异”的基本规则,这条规则在很多的领域都有应用,用的最绝的是朱元璋,对待贪官,要么不理你,自觉点您贪差不多了就收手吧,您自己不收手的话,做的过了直接就杀,株连几族,所以在明朝,朱元璋是杀人最多的皇帝;在结构的防呆性设计上,接插件的选型也是如此,如果一个乳白色和一个浅灰色的同类接插件,最好的选择是有很直观的视觉差异或结构的差异,或者干脆就是相同的,相同须基于一个前提,互换性要好。
用显意的符号来命名变量和语句标号。标识符的命名有明确含义,且是完整单词或易理解的缩写。短单词通过去掉“元音”形成缩写;长单词取头几个字母形成缩写;一些单词有公认的缩写。如:
Temp — tmp;
Flag — f.l.g;(*注:请去年中间的.号)
Statistic — stat;
Increment — inc;
Message — msg。
特殊约定或缩写,要有注释说明。在源文件开始处,对使用的缩写或约定注释说明。自己特有的命名风格,要自始至终保持一致。对于变量命名,禁止取单个字符(如i、j、k...);含义+变量类型、数据类型等,i、j、k作局部循环变量是允许的,但容易混淆的字母慎用。如int Liv_Width,L代表局部变量(Local)(g全局变量Global)、i代表数据类型(Interger)、 v代表 变量(Variable)(c常量Const)、Width代表变量的含义,这种命名方式可防止局部变量与全局变量重名。
禁用易混淆的标识符(R1和Rl,DO和D0等)来表示不同的变量、文件名和语句标号。
除了编译开关/头文件等特殊应用,避免使用_EXAMPLE_TEST_之类以下划线开始和结尾的定义。
全局变量是战略性资源,它决定了模块和模块间的耦合度,需在项目上提升到一个足够高的高度,慎用全局变量,不得不用的时候,要单独为每一个全局变量编写独立的操作模块或函数,在修改全局变量的时候,要检查是否有别的函数在调用它并且需要此数值保持稳定。
对变量代表某个特定含义的时候,尽量不要仅仅用位来代表什么,比如用某变量的第零位代表某个状态(0000 0001,其中仅用1代表某个内容,这样01H、03H、05H… 会有很多个组合都能代表这个状态);位容易受干扰被修改,信息出现错误的几率大很多。
也不要用00H、FFH等数据代表,就像我们面试一群人一样,第一个被面试人和最后一个被面试人容易被记住,00H和FFH亦然,系统默认状态是00和FF的时候较多,他们容易被复位或置位成这类数值。推荐以四位的二进制码的某个中间值为状态变量,如1001。
变量数据在应用之前宜作数据类型和数值范围的判断;
数据在存储过程中也容易出现问题,EEPROM、RAM等都有过类似的案例。数据出错时避免不了的,解决的办法是学花旗银行等美国金融企业,之所以在9.11后他们能很快恢复业务,基本没有数据方面的损失,原因何在?因为他们有异地容灾数据备份系统,知里面有两个关键词,异地、备份。我们的信息也同样,首先选择存在不同的介质中、或相同的介质但迥异的存放环境和位置下,双重备份的结局是两边不一致的时候,数据被怀疑并拒绝反映执行,但嵌入式软件很多时候是要靠数据来推动执行机构的,即使发现数据有问题也不允许行政不作为,这种情况下,作为我们也很难办,2个不同的数据,有明显问题的还好排除,都在有限范围内可如何判定哈?这种时候没办法只好三备份,少数服从多数是唯一的选择了。石头剪刀布的方式不好用,葛优的分歧终端机也不适用,就只好选择这种最原始最有效的办法了,唯一需要注意的是数据宜存放于三种不同的备份环境下,不然岂不成了你家哥俩儿,咋表决都占便宜啊。
以上仅就嵌入式软件可靠性的关注方面分了几大类,进行了基本的描述,实际应用中,需要关注的点还有很多很多,如果是准备自行制定设计规范的话,以上的思路应该也可以给与一些启迪了。(全文完)
《嵌入式软件可靠性设计要注意的问题》(上)
另外作者本人通过整理,完成了一份《嵌入式软件可靠性设计规范》,doc版本的25 页,也是呕心沥血了,另有一个ppt的培训课程讲义,诸位读者如果有兴趣的话,可以联系400-6800-965或wuyeqing@rdcoo.com,参加培训的话这两部分都可以提供,不过这可是收费的欧。希望读者不要骂我,兄弟闯荡江湖也不容易,也有一帮小弟等着吃饭呢,见谅见谅。
用户1505428 2013-5-28 18:41
用户1011588 2010-8-9 13:48
用户1563499 2010-8-9 09:05
tamkay_819533976 2010-8-7 14:07
wuyeqing_363494696 2010-6-21 07:12
hjh_hope_694608189 2010-6-18 17:30
用户1494310 2010-6-18 12:31
用户1476573 2010-6-18 11:26
用户1109607 2010-6-18 09:26
用户1357307 2010-6-18 09:00