精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式軟件可靠性設(shè)計(jì)的編程要點(diǎn)

工程師進(jìn)階筆記 ? 來(lái)源:csdn ? 2023-05-16 09:39 ? 次閱讀

設(shè)備的可靠性涉及多個(gè)方面:穩(wěn)定的硬件、優(yōu)秀的軟件架構(gòu)、嚴(yán)格的測(cè)試以及市場(chǎng)和時(shí)間的檢驗(yàn)等等。這里著重談一下作者自己對(duì)嵌入式軟件可靠性設(shè)計(jì)的一些理解,通過(guò)一定的技巧和方法提高軟件可靠性。

1、判錯(cuò)

工欲善其事必先利其器。判錯(cuò)的最終目的是用來(lái)暴露設(shè)計(jì)中的Bug并加以改正,所以將錯(cuò)誤信息提供給編程者是必要的。

有時(shí)候需要將故障信息儲(chǔ)存于非易失性存儲(chǔ)器中,便于查看。這里以使用串口打印錯(cuò)誤信息到PC顯示屏為例,來(lái)說(shuō)明一般需要顯示什么信息。

編寫(xiě)或移植一個(gè)類(lèi)似C標(biāo)準(zhǔn)庫(kù)中的printf函數(shù),可以格式化打印字符、字符串、十進(jìn)制整數(shù)、十六進(jìn)制整數(shù)。這里稱(chēng)為UARTprintf()。

unsignedintWriteData(unsignedintaddr)
{
if((addr>=BASE_ADDR)&&(addr<=END_ADDR))?
????{
????????…/*地址合法,進(jìn)行處理*/
?}?
????else?
????{?/*地址錯(cuò)誤,打印錯(cuò)誤信息*/
??UARTprintf?("文件%s的第?%d?行寫(xiě)數(shù)據(jù)時(shí)發(fā)生地址錯(cuò)誤,錯(cuò)誤地址為:0x%x
",__FILE__,__LINE__,addr);
??…/*錯(cuò)誤處理代碼*/
?}

假設(shè)UARTprintf()函數(shù)位于main.c模塊的第256行,并且WriteData()函數(shù)在讀數(shù)據(jù)時(shí)傳遞了錯(cuò)誤地址0x00000011,則會(huì)執(zhí)行UARTprintf()函數(shù),打印如下所示的信息:

文件main.c的第256行寫(xiě)數(shù)據(jù)時(shí)發(fā)生地址錯(cuò)誤,錯(cuò)誤地址為:0x00000011。類(lèi)似這樣的信息會(huì)有助于程序員定位分析錯(cuò)誤產(chǎn)生的根源,更快的消除Bug。

2、判斷實(shí)參是否合法

程序員可能無(wú)意識(shí)的傳遞了錯(cuò)誤參數(shù);外界的強(qiáng)干擾可能將傳遞的參數(shù)修改掉,或者使用隨機(jī)參數(shù)意外的調(diào)用函數(shù),因此在執(zhí)行函數(shù)主體前,需要先確定實(shí)參是否合法。

intexam_fun(unsignedchar*str)
{
if(str!=NULL)
{//檢查“假設(shè)指針不為空”這個(gè)條件

...//正常處理代碼
}
else
{
UARTprintf(…);//打印錯(cuò)誤信息
…//處理錯(cuò)誤代碼
}
}

3、仔細(xì)檢查函數(shù)的返回值

對(duì)函數(shù)返回的錯(cuò)誤碼,要進(jìn)行全面仔細(xì)處理,必要時(shí)做錯(cuò)誤記錄。

char*DoSomething(…)
{
char*p;
p=malloc(1024);
if(p==NULL)
{/*對(duì)函數(shù)返回值作出判斷*/
UARTprintf(…);/*打印錯(cuò)誤信息*/
returnNULL;
}
retuenp;
}

4、防止指針越界

如果動(dòng)態(tài)計(jì)算一個(gè)地址時(shí),要保證被計(jì)算的地址是合理的并指向某個(gè)有意義的地方。特別對(duì)于指向一個(gè)結(jié)構(gòu)或數(shù)組的內(nèi)部的指針,當(dāng)指針增加或者改變后仍然指向同一個(gè)結(jié)構(gòu)或數(shù)組。

5、防止數(shù)組越界

數(shù)組越界的問(wèn)題前文已經(jīng)講述的很多了,由于C不會(huì)對(duì)數(shù)組進(jìn)行有效的檢測(cè),因此必須在應(yīng)用中顯式的檢測(cè)數(shù)組越界問(wèn)題。下面的例子可用于中斷接收通訊數(shù)據(jù)。

#defineREC_BUF_LEN100
unsignedcharRecBuf[REC_BUF_LEN];
…//其它代碼
voidUart_IRQHandler(void)
{
staticRecCount=0;//接收數(shù)據(jù)長(zhǎng)度計(jì)數(shù)器
…//其它代碼
if(RecCount

在使用一些庫(kù)函數(shù)時(shí),同樣需要對(duì)邊界進(jìn)行檢查:

#defineREC_BUF_LEN100
unsignedcharRecBuf[REC_BUF_LEN];

if(len

6、數(shù)學(xué)算數(shù)運(yùn)算

檢測(cè)除數(shù)是否為零

檢測(cè)運(yùn)算溢出情況

「有符號(hào)整數(shù)除法,僅檢測(cè)除數(shù)為零就夠了嗎?」

兩個(gè)整數(shù)相除,除了要檢測(cè)除數(shù)是否為零外,還要檢測(cè)除法是否溢出。對(duì)于一個(gè)signed long類(lèi)型變量,它能表示的數(shù)值范圍為:-2147483648 ~ +2147483647,如果讓-2147483648 / -1,那么結(jié)果應(yīng)該是+ 2147483648,但是這個(gè)結(jié)果已經(jīng)超出了signed long所能表示的范圍了。

#include
signedlongsl1,sl2,result;
/*初始化sl1和sl2*/
if((sl2==0)||((sl1==LONG_MIN)&&(sl2==-1)))
{
//處理錯(cuò)誤
}
else
{
result=sl1/sl2;
}

「加法溢出檢測(cè):」

a)無(wú)符號(hào)加法

#include
unsignedinta,b,result;
/*初始化a,b*/
if(UINT_MAX-a

b)有符號(hào)加法

#include
signedinta,b,result;
/*初始化a,b*/
if((a>0&&INT_MAX-ab))
{
//處理溢出
}
else
{
result=a+b;
}

「乘法溢出檢測(cè):」

a)無(wú)符號(hào)乘法

#include
unsignedinta,b,result;
/*初始化a,b*/
if((a!=0)&&(UINT_MAX/a

b)有符號(hào)乘法

#include
signedinta,b,tmp,result;
/*初始化a,b*/
tmp=a*b;
if(a!=0&&tmp/a!=b)
{
//
}
else
{
result=tmp;
}

7、其它可能出現(xiàn)運(yùn)行時(shí)錯(cuò)誤的地方

運(yùn)行時(shí)錯(cuò)誤檢查是C 程序員需要加以特別的注意的,這是因?yàn)?a href="http://www.nxhydt.com/v/tag/1743/" target="_blank">C語(yǔ)言在提供任何運(yùn)行時(shí)檢測(cè)方面能力較弱。對(duì)于要求可靠性較高的軟件來(lái)說(shuō),動(dòng)態(tài)檢測(cè)是必需的。

因此C 程序員需要謹(jǐn)慎考慮的問(wèn)題是,在任何可能出現(xiàn)運(yùn)行時(shí)錯(cuò)誤的地方增加代碼的動(dòng)態(tài)檢測(cè)。大多數(shù)的動(dòng)態(tài)檢測(cè)與應(yīng)用緊密相關(guān),在程序設(shè)計(jì)過(guò)程中要根據(jù)系統(tǒng)需求設(shè)置動(dòng)態(tài)代碼檢測(cè)。

8、編譯器語(yǔ)義檢查

為了更簡(jiǎn)單的設(shè)計(jì)編譯器,目前幾乎所有編譯器的語(yǔ)義檢查都比較弱小,加之為了獲得更快的執(zhí)行效率,C語(yǔ)言被設(shè)計(jì)的足夠靈活且?guī)缀醪贿M(jìn)行任何運(yùn)行時(shí)檢查,比如數(shù)組越界、指針是否合法、運(yùn)算結(jié)果是否溢出等等。

C語(yǔ)言足夠靈活,對(duì)于一個(gè)數(shù)組a[30],它允許使用像a[-1]這樣的形式來(lái)快速獲取數(shù)組首元素所在地址前面的數(shù)據(jù);允許將一個(gè)常數(shù)強(qiáng)制轉(zhuǎn)換為函數(shù)指針,使用代碼( * ((void( * )())0))()來(lái)調(diào)用位于0地址的函數(shù)。

C語(yǔ)言給了程序員足夠的自由,但也由程序員承擔(dān)濫用自由帶來(lái)的責(zé)任。下面的兩個(gè)例子都是死循環(huán),如果在不常用分支中出現(xiàn)類(lèi)似代碼,將會(huì)造成看似莫名其妙的死機(jī)或者重啟。

a.unsignedchari;
for(i=0;i<256;i++)??{…?}??????????????
b.?unsigned?chari;
???for(i=10;i>=0;i--){…}

對(duì)于無(wú)符號(hào)char類(lèi)型,表示的范圍為0~255,所以無(wú)符號(hào)char類(lèi)型變量i永遠(yuǎn)小于256(第一個(gè)for循環(huán)無(wú)限執(zhí)行),永遠(yuǎn)大于等于0(第二個(gè)for循環(huán)無(wú)線執(zhí)行)。需要說(shuō)明的是,賦值代碼i=256是被C語(yǔ)言允許的,即使這個(gè)初值已經(jīng)超出了變量i可以表示的范圍。C語(yǔ)言會(huì)千方百計(jì)的為程序員創(chuàng)造出錯(cuò)的機(jī)會(huì),可見(jiàn)一斑。

假如你在if語(yǔ)句后誤加了一個(gè)分號(hào)改變了程序邏輯,編譯器也會(huì)很配合的幫忙掩蓋,甚至連警告都不提示。代碼如下:

if(a>b);//這里誤加了一個(gè)分號(hào)
a=b;//這句代碼一直被執(zhí)行

不但如此,編譯器還會(huì)忽略掉多余的空格符和換行符,就像下面的代碼也不會(huì)給出足夠提示:

if(n<3)
return????//這里少加了一個(gè)分號(hào)
logrec.data=x[0];
logrec.time=x[1];
logrec.code=x[2];

這段代碼的本意是n<3時(shí)程序直接返回,由于程序員的失誤,return少了一個(gè)結(jié)束分號(hào)。編譯器將它翻譯成返回表達(dá)式logrec.data=x[0]的結(jié)果,return后面即使是一個(gè)表達(dá)式也是C語(yǔ)言允許的。這樣當(dāng)n>=3時(shí),表達(dá)式logrec.data=x[0];就不會(huì)被執(zhí)行,給程序埋下了隱患。

可以毫不客氣的說(shuō),弱小的編譯器語(yǔ)義檢查在很大程度上縱容了不可靠代碼可以肆無(wú)忌憚的存在。

上文曾提到數(shù)組常常是引起程序不穩(wěn)定的重要因素,程序員往往不經(jīng)意間就會(huì)寫(xiě)數(shù)組越界。一位同事的代碼在硬件上運(yùn)行,一段時(shí)間后就會(huì)發(fā)現(xiàn)LCD顯示屏上的一個(gè)數(shù)字不正常的被改變。經(jīng)過(guò)一段時(shí)間的調(diào)試,問(wèn)題被定位到下面的一段代碼中:

intSensorData[30];
for(i=30;i>0;i--)
{
SensorData[i]=…;
…
}

這里聲明了擁有30個(gè)元素的數(shù)組,不幸的是for循環(huán)代碼中誤用了本不存在的數(shù)組元素SensorData[30],但C語(yǔ)言卻默許這么使用,并欣然的按照代碼改變了數(shù)組元素SensorData[30]所在位置的值。

SensorData[30]所在的位置原本是一個(gè)LCD顯示變量,這正是顯示屏上的那個(gè)值不正常被改變的原因。真慶幸這么輕而易舉的發(fā)現(xiàn)了這個(gè)Bug。

9、關(guān)鍵數(shù)據(jù)多區(qū)備份,取數(shù)據(jù)采用“表決法”

RAM中的數(shù)據(jù)在受到干擾情況下有可能被改變,對(duì)于系統(tǒng)關(guān)鍵數(shù)據(jù)必須進(jìn)行保護(hù)。關(guān)鍵數(shù)據(jù)包括全局變量、靜態(tài)變量以及需要保護(hù)的數(shù)據(jù)區(qū)域。數(shù)據(jù)備份與原數(shù)據(jù)不應(yīng)該處于相鄰位置,因此不應(yīng)由編譯器默認(rèn)分配備份數(shù)據(jù)位置,而應(yīng)該由程序員指定區(qū)域存儲(chǔ)。

可以將RAM分為3個(gè)區(qū)域,第一個(gè)區(qū)域保存原碼,第二個(gè)區(qū)域保存反碼,第三個(gè)區(qū)域保存異或碼,區(qū)域之間預(yù)留一定量的“空白”RAM作為隔離。

可以使用編譯器的“分散加載”機(jī)制將變量分別存儲(chǔ)在這些區(qū)域。需要進(jìn)行讀取時(shí),同時(shí)讀出3份數(shù)據(jù)并進(jìn)行表決,取至少有兩個(gè)相同的那個(gè)值。

假如設(shè)備的RAM從0x1000_0000開(kāi)始,我需要在RAM的0x1000_0000~0x10007FFF內(nèi)存儲(chǔ)原碼,在0x1000_9000~0x10009FFF內(nèi)存儲(chǔ)反碼,在0x1000_B000~0x1000BFFF內(nèi)存儲(chǔ)0xAA的異或碼,編譯器的分散加載可以設(shè)置為:

LR_IROM10x000000000x00080000{;loadregionsize_region
ER_IROM10x000000000x00080000{;loadaddress=executionaddress
*.o(RESET,+First)
*(InRoot$$Sections)
.ANY(+RO)
}

RW_IRAM10x100000000x00008000{;保存原碼
.ANY(+RW+ZI)
}

RW_IRAM30x100090000x00001000{;保存反碼
.ANY(MY_BK1)
}

RW_IRAM20x1000B0000x00001000{;保存異或碼
.ANY(MY_BK2)
}
}

如果一個(gè)關(guān)鍵變量需要多處備份,可以按照下面方式定義變量,將三個(gè)變量分別指定到三個(gè)不連續(xù)的RAM區(qū)中,并在定義時(shí)按照原碼、反碼、0xAA的異或碼進(jìn)行初始化。

uint32plc_pc=0;//原碼
__attribute__((section("MY_BK1")))uint32plc_pc_not=~0x0;//反碼
__attribute__((section("MY_BK2")))uint32plc_pc_xor=0x0^0xAAAAAAAA;//異或碼

當(dāng)需要寫(xiě)這個(gè)變量時(shí),這三個(gè)位置都要更新;讀取變量時(shí),讀取三個(gè)值做判斷,取至少有兩個(gè)相同的那個(gè)值。

為什么選取異或碼而不是補(bǔ)碼?這是因?yàn)镸DK的整數(shù)是按照補(bǔ)碼存儲(chǔ)的,正數(shù)的補(bǔ)碼與原碼相同,在這種情況下,原碼和補(bǔ)碼是一致的,不但起不到冗余作用,反而對(duì)可靠性有害。

比如存儲(chǔ)的一個(gè)非零整數(shù)區(qū)因?yàn)楦蓴_,RAM都被清零,由于原碼和補(bǔ)碼一致,按照3取2的“表決法”,會(huì)將干擾值0當(dāng)做正確的數(shù)據(jù)。

10、非易失性存儲(chǔ)器的數(shù)據(jù)存儲(chǔ)

非易失性存儲(chǔ)器包括但不限于Flash、EEPROM、鐵電。僅僅將寫(xiě)入非易失性存儲(chǔ)器中的數(shù)據(jù)再讀出校驗(yàn)是不夠的。強(qiáng)干擾情況下可能導(dǎo)致非易失性存儲(chǔ)器內(nèi)的數(shù)據(jù)錯(cuò)誤,在寫(xiě)非易失性存儲(chǔ)器的期間系統(tǒng)掉電將導(dǎo)致數(shù)據(jù)丟失,因干擾導(dǎo)致程序跑飛到寫(xiě)非易失性存儲(chǔ)器函數(shù)中,將導(dǎo)致數(shù)據(jù)存儲(chǔ)紊亂。

一種可靠的辦法是將非易失性存儲(chǔ)器分成多個(gè)區(qū),每個(gè)數(shù)據(jù)都將按照不同的形式寫(xiě)入到這些分區(qū)中,需要進(jìn)行讀取時(shí),同時(shí)讀出多份數(shù)據(jù)并進(jìn)行表決,取相同數(shù)目較多的那個(gè)值。

對(duì)于因干擾導(dǎo)致程序跑飛到寫(xiě)非易失性存儲(chǔ)器函數(shù),還應(yīng)該配合軟件鎖以及嚴(yán)格的入口檢驗(yàn),單單依靠寫(xiě)數(shù)據(jù)到多個(gè)區(qū)是不夠的也是不明智的,應(yīng)該在源頭進(jìn)行阻截。

11、軟件鎖

軟件鎖可以實(shí)現(xiàn)但不局限于環(huán)環(huán)相扣。對(duì)于初始化序列或者有一定先后順序的函數(shù)調(diào)用,為了保證調(diào)用順序或者確保每個(gè)函數(shù)都被調(diào)用,我們可以使用環(huán)環(huán)相扣,實(shí)質(zhì)上這也是一種軟件鎖。此外對(duì)于一些安全關(guān)鍵代碼語(yǔ)句(是語(yǔ)句,而不是函數(shù)),可以給它們?cè)O(shè)置軟件鎖,只有持有特定鑰匙的,才可以訪問(wèn)這些關(guān)鍵代碼。

比如,向Flash寫(xiě)一個(gè)數(shù)據(jù),我們會(huì)判斷數(shù)據(jù)是否合法、寫(xiě)入的地址是否合法,計(jì)算要寫(xiě)入的扇區(qū)。之后調(diào)用寫(xiě)Flash子程序,在這個(gè)子程序中,判斷扇區(qū)地址是否合法、數(shù)據(jù)長(zhǎng)度是否合法,之后就要將數(shù)據(jù)寫(xiě)入Flash。

由于寫(xiě)Flash語(yǔ)句是安全關(guān)鍵代碼,所以程序給這些語(yǔ)句上鎖:必須具有正確的鑰匙才可以寫(xiě)Flash。這樣即使是程序跑飛到寫(xiě)Flash子程序,也能大大降低誤寫(xiě)的風(fēng)險(xiǎn)。

/***************************************************************
*名稱(chēng):RamToFlash()
*功能:復(fù)制RAM的數(shù)據(jù)到FLASH,命令代碼51。
*入口參數(shù):dst 目標(biāo)地址,即FLASH起始地址。以512字節(jié)為分界
* src 源地址,即RAM地址。地址必須字對(duì)齊
*no復(fù)制字節(jié)個(gè)數(shù),為512/1024/4096/8192
*ProgStart軟件鎖標(biāo)志
*出口參數(shù):IAP返回值(paramout緩沖區(qū)) CMD_SUCCESS,SRC_ADDR_ERROR,DST_ADDR_ERROR,
SRC_ADDR_NOT_MAPPED,DST_ADDR_NOT_MAPPED,COUNT_ERROR,BUSY,未選擇扇區(qū)
****************************************************************/
voidRamToFlash(uint32dst,uint32src,uint32no,uint8ProgStart)
{
PLC_ASSERT("Sectornumber",(dst>=0x00040000)&&(dst<=0x0007FFFF));
????PLC_ASSERT("Copy?bytes?number?is?512",(no==512));
????PLC_ASSERT("ProgStart==0xA5",(ProgStart==0xA5));
????paramin[0]?=?IAP_RAMTOFLASH;?//?設(shè)置命令字
????paramin[1]?=?dst;?//?設(shè)置參數(shù)
????paramin[2]?=?src;
????paramin[3]?=?no;
????paramin[4]?=?Fcclk/1000;
????if(ProgStart==0xA5)?//只有軟件鎖標(biāo)志正確時(shí),才執(zhí)行關(guān)鍵代碼
????{
????????iap_entry(paramin,?paramout);?//?調(diào)用IAP服務(wù)程序
????????ProgStart=0;
????}
????else
????{
?????paramout[0]=PROG_UNSTART;
????}

}

該程序段是編程lpc1778內(nèi)部Flash,其中調(diào)用IAP程序的函數(shù)iap_entry(paramin, paramout)是關(guān)鍵安全代碼,所以在執(zhí)行該代碼前,先判斷一個(gè)特定設(shè)置的安全鎖標(biāo)志ProgStart,只有這個(gè)標(biāo)志符合設(shè)定值,才會(huì)執(zhí)行編程Flash操作。

如果因?yàn)橐馔獬绦蚺茱w到該函數(shù),由于ProgStart標(biāo)志不正確,是不會(huì)對(duì)Flash進(jìn)行編程的。

12、通信數(shù)據(jù)的檢錯(cuò)

通訊線上的數(shù)據(jù)誤碼相對(duì)嚴(yán)重,通訊線越長(zhǎng),所處的環(huán)境越惡劣,誤碼會(huì)越嚴(yán)重。拋開(kāi)硬件和環(huán)境的作用,我們的軟件應(yīng)能識(shí)別錯(cuò)誤的通訊數(shù)據(jù)。對(duì)此有一些應(yīng)用措施:

制定協(xié)議時(shí),限制每幀的字節(jié)數(shù);

每幀字節(jié)數(shù)越多,發(fā)生誤碼的可能性就越大,無(wú)效的數(shù)據(jù)也會(huì)越多。對(duì)此以太網(wǎng)規(guī)定每幀數(shù)據(jù)不大于1500字節(jié),高可靠性的CAN收發(fā)器規(guī)定每幀數(shù)據(jù)不得多于8字節(jié),對(duì)于RS485,基于RS485鏈路應(yīng)用最廣泛的Modbus協(xié)議一幀數(shù)據(jù)規(guī)定不超過(guò)256字節(jié)。因此,建議制定內(nèi)部通訊協(xié)議時(shí),使用RS485時(shí)規(guī)定每幀數(shù)據(jù)不超過(guò)256字節(jié);

使用多種校驗(yàn)

編寫(xiě)程序時(shí)應(yīng)使能奇偶校驗(yàn),每幀超過(guò)16字節(jié)的應(yīng)用,建議至少編寫(xiě)CRC16校驗(yàn)程序。

增加額外判斷

增加緩沖區(qū)溢出判斷。這是因?yàn)閿?shù)據(jù)接收多是在中斷中完成,編譯器檢測(cè)不出緩沖區(qū)是否溢出,需要手動(dòng)檢查,在上文介紹數(shù)據(jù)溢出一節(jié)中已經(jīng)詳細(xì)說(shuō)明。

增加超時(shí)判斷。當(dāng)一幀數(shù)據(jù)接收 到一半,長(zhǎng)時(shí)間接收不到剩余數(shù)據(jù),則認(rèn)為這幀數(shù)據(jù)無(wú)效,重新開(kāi)始接收。

可選,跟不同的協(xié)議有關(guān),但緩沖區(qū)溢出判斷必須實(shí)現(xiàn)。這是因?yàn)閷?duì)于需要幀頭判斷的協(xié)議,上位機(jī)可能發(fā)送完幀頭后突然斷電,重啟后上位機(jī)是從新的幀開(kāi)始發(fā)送的,但是下位機(jī)已經(jīng)接收到了上次未發(fā)送完的幀頭,所以上位機(jī)的這次幀頭會(huì)被下位機(jī)當(dāng)成正常數(shù)據(jù)接收。

這有可能造成數(shù)據(jù)長(zhǎng)度字段為一個(gè)很大的值,填滿該長(zhǎng)度的緩沖區(qū)需要相當(dāng)多的數(shù)據(jù)(比如一幀可能1000字節(jié)),影響響應(yīng)時(shí)間;另一方面,如果程序沒(méi)有緩沖區(qū)溢出判斷,那么緩沖區(qū)很可能溢出,后果是災(zāi)難性的。

重傳機(jī)制

如果檢測(cè)到通訊數(shù)據(jù)發(fā)生了錯(cuò)誤,則要有重傳機(jī)制重新發(fā)送出錯(cuò)的幀。

13、開(kāi)關(guān)量輸入的檢測(cè)、確認(rèn)

開(kāi)關(guān)量容易受到尖脈沖干擾,如果不進(jìn)行濾除,可能會(huì)造成誤動(dòng)作。一般情況下,需要對(duì)開(kāi)關(guān)量輸入信號(hào)進(jìn)行多次采樣,并進(jìn)行邏輯判斷直到確認(rèn)信號(hào)無(wú)誤為止。多次采樣之間需要有一定時(shí)間間隔,具體跟開(kāi)關(guān)量的最大切換頻率有關(guān),一般不小于1ms。

14、開(kāi)關(guān)量輸出

開(kāi)關(guān)信號(hào)簡(jiǎn)單的一次輸出是不安全的,干擾信號(hào)可能會(huì)翻轉(zhuǎn)開(kāi)關(guān)量輸出的狀態(tài)。采取重復(fù)刷新輸出可以有效防止電平的翻轉(zhuǎn)。

15、初始化信息的保存與恢復(fù)

微處理器寄存器值也可能會(huì)因外界干擾而改變,外設(shè)初始化值需要在寄存器中長(zhǎng)期保存,最容易被破壞。由于Flash中的數(shù)據(jù)相對(duì)不易被破壞,可以將初始化信息預(yù)先寫(xiě)入Flash,待程序空閑時(shí)比較與初始化相關(guān)的寄存器值是否被更改,如果發(fā)現(xiàn)非法更改則使用Flash中的值進(jìn)行恢復(fù)。

16、while循環(huán)

有時(shí)候程序員會(huì)使用while(!flag);語(yǔ)句來(lái)等待標(biāo)志flag改變,比如串口發(fā)送時(shí)用來(lái)等待一字節(jié)數(shù)據(jù)發(fā)送完成。這樣的代碼時(shí)存在風(fēng)險(xiǎn)的,如果因?yàn)槟承┰驑?biāo)志位一直不改變則會(huì)造成系統(tǒng)死機(jī)。良好冗余的程序是設(shè)置一個(gè)超時(shí)定時(shí)器,超過(guò)一定時(shí)間后,強(qiáng)制程序退出while循環(huán)。

2003年8月11日發(fā)生的W32.Blaster.Worm蠕蟲(chóng)事件導(dǎo)致全球經(jīng)濟(jì)損失高達(dá)5億美元,這個(gè)漏洞是利用了Windows分布式組件對(duì)象模型的遠(yuǎn)程過(guò)程調(diào)用接口中的一個(gè)邏輯缺陷:在調(diào)用GetMachineName()函數(shù)時(shí),循環(huán)只設(shè)置了一個(gè)不充分的結(jié)束條件。

原代碼簡(jiǎn)化如下所示:

HRESULTGetMachineName(WCHAR*pwszPath,
WCHARwszMachineName[MAX_COMPUTTERNAME_LENGTH_FQDN+1])
{
WCHAR*pwszServerName=wszMachineName;
WCHAR*pwszTemp=pwszPath+2;
while(*pwszTemp!=L’\’)/*這句代碼循環(huán)結(jié)束條件不充分*/
*pwszServerName++=*pwszTemp++;
/*…*/
}

微軟發(fā)布的安全補(bǔ)丁MS03-026解決了這個(gè)問(wèn)題,為GetMachineName()函數(shù)設(shè)置了充分終止條件。一個(gè)解決代碼簡(jiǎn)化如下所示(并非微軟補(bǔ)丁代碼):

HRESULTGetMachineName(WCHAR*pwszPath,
WCHARwszMachineName[MAX_COMPUTTERNAME_LENGTH_FQDN+1])
{
WCHAR*pwszServerName=wszMachineName;
WCHAR*pwszTemp=pwszPath+2;
 WCHAR *end_addr = pwszServerName +MAX_COMPUTTERNAME_LENGTH_FQDN;
while((*pwszTemp!=L’\’)&&(*pwszTemp!=L’0’)
&&(pwszServerName

17、系統(tǒng)自檢

對(duì)CPU、RAM、Flash、外部掉電保存存儲(chǔ)器以及其他線路自檢。

18、其它一些編程建議:

深入理解嵌入式C語(yǔ)言以及編譯器

細(xì)致、謹(jǐn)慎的編程

使用好的風(fēng)格和合理的設(shè)計(jì)

不要倉(cāng)促編寫(xiě)代碼,寫(xiě)每一行的代碼時(shí)都要三思而后行:可能會(huì)出現(xiàn)什么樣的錯(cuò)誤?是否考慮了所有的邏輯分支?

打開(kāi)編譯器所有警告開(kāi)關(guān)

使用靜態(tài)分析工具分析代碼

安全的讀寫(xiě)數(shù)據(jù)(檢查所有數(shù)組邊界…)

檢查指針的合法性

檢查函數(shù)入口參數(shù)合法性

檢查所有返回值

在聲明變量位置初始化所有變量

合理的使用括號(hào)

謹(jǐn)慎的進(jìn)行強(qiáng)制轉(zhuǎn)換

使用好的診斷信息日志和工具

來(lái)源:https://blog.csdn.net/zhzht19861011/article/details/17117819





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7598

    瀏覽量

    136199
  • 嵌入式軟件
    +關(guān)注

    關(guān)注

    4

    文章

    240

    瀏覽量

    26618
  • LCD顯示屏
    +關(guān)注

    關(guān)注

    1

    文章

    91

    瀏覽量

    13273
  • 非易失性存儲(chǔ)器

    關(guān)注

    0

    文章

    107

    瀏覽量

    23425

原文標(biāo)題:嵌入式軟件可靠性設(shè)計(jì)的編程要點(diǎn)

文章出處:【微信號(hào):工程師進(jìn)階筆記,微信公眾號(hào):工程師進(jìn)階筆記】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    嵌入式軟件可靠性設(shè)計(jì)要注意的問(wèn)題

    )。 嵌入式系統(tǒng)應(yīng)用領(lǐng)域千差萬(wàn)別、他們對(duì)嵌入式系統(tǒng)的要求和側(cè)重點(diǎn)不盡相同,(如工業(yè)控制特別強(qiáng)調(diào)可靠性), 但基本要求嵌入式系統(tǒng)功能強(qiáng)大、性能穩(wěn)定、工作
    的頭像 發(fā)表于 10-14 11:05 ?5227次閱讀
    <b class='flag-5'>嵌入式</b><b class='flag-5'>軟件</b><b class='flag-5'>可靠性</b>設(shè)計(jì)要注意的問(wèn)題

    嵌入式軟件可靠性測(cè)試方法

    嵌入式軟件可靠性測(cè)試方法
    發(fā)表于 11-05 17:18

    淺析嵌入式系統(tǒng)軟件可靠性測(cè)試難點(diǎn)

    `目前,嵌入式軟件可靠性評(píng)價(jià)主要依賴(lài)測(cè)試,因?yàn)?b class='flag-5'>嵌入式軟件的開(kāi)發(fā)環(huán)境和軟件
    發(fā)表于 08-02 10:05

    嵌入式軟件可靠性測(cè)試與可靠性增長(zhǎng)評(píng)估

    關(guān)于嵌入式軟件可靠性、安全測(cè)試與評(píng)估的資料,希望有幫助。
    發(fā)表于 06-17 16:53

    請(qǐng)問(wèn)一下嵌入式軟件可靠性設(shè)計(jì)需注意什么?

    嵌入式軟件可靠性設(shè)計(jì)需注意什么?
    發(fā)表于 04-27 06:23

    如何對(duì)嵌入式軟件進(jìn)行可靠性測(cè)試

    摘 要 本文針對(duì)目前嵌入式軟件設(shè)計(jì)可靠性測(cè)試用例的手段主要依靠手工分析,沿用傳統(tǒng)的軟件測(cè)試用例設(shè)計(jì)方法進(jìn)行,不能夠滿足可靠性測(cè)試用例設(shè)計(jì)的基
    發(fā)表于 10-27 06:10

    嵌入式軟件可靠性測(cè)試方法是什么

    本文原文鏈接如下:https://www.jianshu.com/p/f6f5c3cd3fab目前,嵌入式軟件可靠性評(píng)價(jià)主要依賴(lài)測(cè)試,因?yàn)?b class='flag-5'>嵌入式
    發(fā)表于 12-21 07:09

    嵌入式軟件的安全可靠性控制

    不同的嵌入式系統(tǒng)對(duì)其安全可靠性的要求是不一樣的。一般說(shuō)來(lái),嵌入式系統(tǒng)對(duì)可靠性與安全的要求要高于非嵌入式
    發(fā)表于 04-22 16:49 ?21次下載

    嵌入式系統(tǒng)軟件可靠性設(shè)計(jì)

    本文分析了 嵌入式系統(tǒng)軟件的復(fù)雜度、可靠性與穩(wěn)定性之間的關(guān)系,本給出了增加嵌入式系統(tǒng)可靠性的一般方法。
    發(fā)表于 11-17 17:43 ?38次下載

    軍用嵌入式系統(tǒng)的可靠性考慮因素

    1 可靠性是軍用嵌入式系統(tǒng)的重要因素嵌入式系統(tǒng)往往工作環(huán)境惡劣、受電噪聲干擾較大,而且隨著軟件越來(lái)越復(fù)
    發(fā)表于 08-18 11:00 ?694次閱讀

    嵌入式系統(tǒng)的可靠性設(shè)計(jì)

    嵌入式應(yīng)用系統(tǒng)是一個(gè)有計(jì)算機(jī)內(nèi)核,軟、硬件整合的智能化電子系統(tǒng)。與傳統(tǒng)的激勵(lì)響應(yīng)型電子系統(tǒng)的本質(zhì)差異,是它的智力嵌入,從而形成嵌入式應(yīng)用系統(tǒng)全新的可靠性設(shè)計(jì)觀念、方法與技術(shù)。這些全新的
    發(fā)表于 11-30 10:04 ?1342次閱讀
     <b class='flag-5'>嵌入式</b>系統(tǒng)的<b class='flag-5'>可靠性</b>設(shè)計(jì)

    軍用嵌入式系統(tǒng)的可靠性考慮因素

    1 可靠性是軍用嵌入式系統(tǒng)的重要因素 嵌入式系統(tǒng)往往工作環(huán)境惡劣、受電噪聲干擾較大,而且隨著軟件越來(lái)越復(fù)雜,系統(tǒng)運(yùn)行不穩(wěn)定的現(xiàn)象愈來(lái)愈嚴(yán)重,因此,
    發(fā)表于 12-02 19:42 ?697次閱讀

    嵌入式系統(tǒng)硬件可靠性分析

    嵌入式系統(tǒng)硬件的可靠性是十分重要的,它直接關(guān)系到嵌入式系統(tǒng)的質(zhì)量和壽命。為了對(duì)嵌入式系統(tǒng)的硬件可靠性進(jìn)行分析,利用Copula方法從硬件角度
    發(fā)表于 01-17 13:46 ?1次下載
    <b class='flag-5'>嵌入式</b>系統(tǒng)硬件<b class='flag-5'>可靠性</b>分析

    嵌入式軟件怎樣測(cè)試,如何對(duì)嵌入式軟件進(jìn)行可靠性測(cè)試

    摘 要 本文針對(duì)目前嵌入式軟件設(shè)計(jì)可靠性測(cè)試用例的手段主要依靠手工分析,沿用傳統(tǒng)的軟件測(cè)試用例設(shè)計(jì)方法進(jìn)行,不能夠滿足可靠性測(cè)試用例設(shè)計(jì)的基
    發(fā)表于 10-20 15:21 ?8次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>軟件</b>怎樣測(cè)試,如何對(duì)<b class='flag-5'>嵌入式</b><b class='flag-5'>軟件</b>進(jìn)行<b class='flag-5'>可靠性</b>測(cè)試

    嵌入式軟件可靠性設(shè)計(jì)

    設(shè)備的可靠性涉及多個(gè)方面:穩(wěn)定的硬件、優(yōu)秀的軟件架構(gòu)、嚴(yán)格的測(cè)試以及市場(chǎng)和時(shí)間的檢驗(yàn)等等。這里著重談一下作者自己對(duì)嵌入式軟件可靠性設(shè)計(jì)的一些
    的頭像 發(fā)表于 06-22 10:00 ?786次閱讀