1. 程式人生 > >嵌入式軟體容易犯的錯誤和規避方法總結

嵌入式軟體容易犯的錯誤和規避方法總結

當今世界,放眼江湖,有電子的地方就有嵌入式軟體,有電子故障的地方,也就有嵌入式軟體設計缺陷的影子。那麼捷配小編今天就把軟體所容易犯的錯誤和規避的方法一一羅列,並給出應對之法。
嵌入式軟體的最大特點是以控制為主,軟硬結合的較多,功能性的操作較多,模組相互間呼叫的較多,外部工作環境複雜容易受到干擾或干擾別的裝置,且執行錯誤的後果不僅僅是資料錯誤而是有可能導致不可估量的災難,所以總結起來,嵌入式軟體可靠性設計需注意的問題有四個方面:
1、軟體介面
先說軟體介面中容易出問題的地方和程式設計人員容易犯的錯誤。
軟體介面呼叫一般會有資料的賦值,賦值變數的資料型別可能會存在強制的資料轉換;需加以檢查。如果為了防範出問題的話,可以新增對資料範圍和資料型別的檢查。
賦值資料的數量不對路,多了少了的都不好,會出現意外的賦值結果,不過還好,這項錯誤比較好檢查。
軟體程式設計中,會有對某一功能操作程式碼的複用,比如對某個埠的資料檢查和控制,在整個程式中只會發生兩次,為了圖省事,可能就直接把該段程式碼直接插入實際程式模組中去了,這樣,在源程式程式碼中,就出現了兩段完全相同,完成相同功能,只是服務於不同模組的程式碼,按道理來說,這樣設計其實也沒啥問題,是的,你沒錯,但你的行為會使別人無意中犯錯。就像青年男女相處,女孩子純粹是想和男孩子充分享受溫馨的氣氛和心情,並不想更深入的發生什麼,但女孩子邀請男生去的是她的家,在家裡換上了家居的睡衣,窗戶緊閉,放著的還是曖昧的音樂,然後無限哀怨地說“我沒想到結果會是這樣的”,那怪得誰來呢?在程式碼方面,您的這種做法與貌似引誘男孩上鉤的少女無異。有人會說了,我這樣寫程式碼怎麼就算引誘呢?原因是程式可能會升級,您這幾行程式碼在實際應用過程中也不能保證是盡善盡美的,發現不完善的地方後,勢必會修改,如果你還能想得起來,可能不會遺漏,如果修改此程式碼的是別的人,改了一個地方,別的地方沒改,是不是還留著隱患?那如何做呢?方法不難,把這段功能單獨做成一個模組即可,對此埠的讀取和控制賦值均由此獨立模組完成,如果資料的正確性影響大的話,還需要對埠資料的正確性進行檢查和判斷。嵌入式軟體可靠性程式設計方法的四個目的是防錯、判錯、糾錯、容錯。對埠資料的判斷屬於判錯的內容,如果資料有錯的話,糾錯和容錯的設計方法應該不用我深入講解了吧?
2、軟硬體接
硬體如男人,對外的執行都靠它來實現,一旦出現問題,執行後的後果就不可控了,周總理說過“外交無小事”。但如何注意呢?
對讀進來的硬體介面的資料要判斷其真偽;
對輸出的資料的執行效果要檢測;
對輸出的資料的可能後果要進行預防性設計,資料輸出的過程,我們從設計上要做一個分析,分析的思路是一般容易侷限在穩態過程,忽視了過渡過程。舉例說明,比如我們控制一個支路的供電,從軟體控制來說,直接給繼電器一個啟動訊號,讓開狀態的觸點閉合就可以了,非“關”即“開”,是受控繼電器的兩個穩態狀態,但事實上,在從開到閉合的過程中,支路供電的電壓並不是一個簡單0V—24V(24V為示例而已)的跳變狀態,而是一個抖動,有衝擊訊號的過程,這種情況在硬體上的防護是必不可少的,但在軟體上也不是可以事不關己、高高掛起的。
另外在邏輯上,宜將容易被幹擾和容易產生的干擾控制動作從時序上控制好,予以分開隔離。比如,控制繼電器的過程是容易產生抖動尖峰脈衝而干擾資料匯流排和控制訊號匯流排的,這時候從控制上,不宜同時實施資料的傳送和接收工作,不宜作出其他的控制動作,惹不起咱躲得起,躲過這一陣干擾的時候總可以了吧?
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”)。這裡要遵循一個“要麼相同,要麼迥異”的基本規則,這條規則在很多的領域都有應用,用的最絕的是朱元璋,對待貪官,要麼不理你,自覺點您貪差不多了就收手吧,您自己不收手的話,做的過了直接就殺,株連幾族,所以在明朝,朱元璋是殺人最多的皇帝;在結構的防呆性設計上,接外掛的選型也是如此,如果一個乳白色和一個淺灰色的同類接外掛,最好的選擇是有很直觀的視覺差異或結構的差異,或者乾脆就是相同的,相同須基於一個前提,互換性要好。更多設計交流pcb打樣
用顯意的符號來命名變數和語句標號。識別符號的命名有明確含義,且是完整單詞或易理解的縮寫。短單詞通過去掉“母音”形成縮寫;長單詞取頭幾個字母形成縮寫;一些單詞有公認的縮寫。如:
Temp — tmp;
Flag — flg;
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個不同的資料,有明顯問題的還好排除,都在有限範圍內可如何判定哈?這種時候沒辦法只好三備份,少數服從多數是唯一的選擇了。石頭剪刀布的方式不好用,葛優的分歧終端機也不適用,就只好選擇這種最原始最有效的辦法了,唯一需要注意的是資料宜存放於三種不同的備份環境下,不然豈不成了你家哥倆兒,咋表決都佔便宜阿。
以上便是捷配打樣廠家小編僅就嵌入式軟體可靠性的關注方面分了幾大類,進行了基本的描述,實際應用中,需要關注的點還有很多很多,如果是準備自行制定設計規範的話,以上的思路應該也可以給與一些啟迪了。更多關於捷配pcb打樣工廠知識www.jiepei.com/g532