3.7 處理錯誤
**的生命週期讓我震驚。因為有時侯好像我們總在以不同的方式重寫同樣的舊**,有一天我們可能會發現自己在10年前入門階段寫的一段**正在被乙個財富500強公司使用。既然**工作的如此之好,為什麼還要修復其中那些隱藏很深的問題呢?
在某些時候,**將失效。這一點可能讓人會感到可怕。乙個錯誤的發生,要麼是由於**本身,要麼是由於環境中乙個意想不到的情況。有兩種方法來處理錯誤。首先,該系統可以進入優雅降級的狀態,在這個狀態中軟體會盡可能做到最好。或者,系統可能會優雅地立即失效。長期執行的感測器型別的系統需要採用前乙個方法,醫療系統則要求後者。無論哪種方式,系統必須安全地失效。
但如何實現其中之一的方法?更重要的是,應該採用什麼標準來確定哪些子系統應該實現哪一種錯誤處理方法?具體怎麼做取決於不同的產品要求,我們需要在設計期間思考錯誤處理問題。
3.7.1 一致的方法
函式應竭盡所能地處理錯誤。例如,如果乙個變數可能超出範圍,那麼這個範圍應當固定,並適當記錄錯誤。函式可以返回錯誤以允許呼叫者處理這些問題。呼叫者應該檢查並處理錯誤,這意味著可能進一步將其向上傳遞到乙個多層的應用程式。在許多情況下,如果錯誤不是那麼重要,就不需要對其進行檢查,那麼同樣不需要將它返回。另一方面,在有些情況下,只需要返回乙個僅用於測試的診斷**。可以在注釋中指出返回的錯誤**不是給正常執行的程式使用的,或只用於在assert()函式呼叫中。
並不是所有的嵌入式系統都實現了assert()函式,但以適合於系統的方法去實現它並不難。可以輸出到除錯控制台的訊息、輸出到系統控制台或者日誌的訊息,乙個斷點指令(如bkpt),或者甚至在錯誤發生時觸發乙個輸入/輸出線或led。輸出會改變嵌入式系統的時序,因此將錯誤通訊函式分離出來以允許用其他輸出方法(如led),這樣做往往是有益的。
乙個應用程式或者系統的錯誤返回**應該在**庫上進行標準化。可以建立乙個高層errorcodes.**件(或類似的),以列舉的格式提供一致的錯誤**定義。建議的錯誤**包括:
沒有錯誤(應該總是為0)。
未知的錯誤(或無法識別的錯誤)。
錯誤的引數。
錯誤的索引(指標超出範圍或者為空)。
未初始化的變數或子系統。
災難性的失效(這可能會導致處理器復位,除非它在開發模式下,在這種情況下,它可能會引發乙個斷點或自旋迴圈)。
應該有乙個最小數量的錯誤(一般性錯誤),這樣應用程式可以解釋它們。雖然在將特異性丟棄(uart_failed_to_init_because_second_parameter_was_too_high)的同時,泛化使得錯誤處理和使用更容易(如果parmeter_bad錯誤發生在某個子系統中,那麼就已經有了乙個合適的地方可以開始尋找這個錯誤)。從本質上講,讓它保持盡可能簡單,確保將重要的資訊(某個錯誤)提供給開發者,這樣除錯時就可以進一步挖掘錯誤發生的地方和原因。
3.7.2 錯誤處理庫
錯誤處理庫也是乙個不錯的想法。實現它的方式之一就是讓每個函式返回乙個錯誤**。不用再像下面這樣呼叫函式和檢查結果:
error = functionfoo();
if (error != no_error)
呼叫錯誤檢查函式中的函式:
errorset(&globalerrorcode, functionfoo());
如果這個函式沒有返回任何錯誤,那麼errorset函式不會覆蓋以前的錯誤條件。允許一次呼叫多個函式,並在最後檢查錯誤,而不是在每個函式呼叫之後都去檢查。
在這樣的錯誤處理庫中,將有四個函式這四個函式對應用程式有意義:errorset、errorget、errorprint和errorclear。這個庫應該設計得便於除錯和測試,雖然這個機制即使在開發結束後也應當保留在程式裡。比如,errorprint可能會從向串列埠寫日誌資訊轉變為只是觸發輸入/輸出線的乙個小函式。這不終端使用者需要處理的錯誤,這個是當產品單元不能正常工作時,開發者應當處理的錯誤。
3.7.3 除錯時序錯誤
在除錯硬體/軟體之間的互動行為(或者任何時間關鍵的軟體)時,日誌或者printf之類的序列輸出會改變**的時序。在大多數情況下,乙個與時序相關的問題是否出現(或者消失)取決於輸出語句以及(或者)斷點的位置。而當工具和問題相互作用時,除錯變得尤其困難。
使用錯誤處理庫(或者如第2章所述的日誌庫)的好處之一,就是我們可以不用實際輸出資料,而將資料儲存在ram中,這是乙個很快的方法。事實上,如果遇到時序上的麻煩,考慮使用乙個小的緩衝區(4~16位元組,取決於可用ram的大小)來儲存來自軟體的訊號(1~2位元組)。在**中,在感興趣的觸發點(例如,assert或者errorset)填充這個緩衝區。當**退出時間關鍵區域之後,再將緩衝區的內容轉儲出來。如果需要對最新發生的錯誤資訊進行處理,則可以使用乙個環形緩衝區持續不斷地捕獲最近發生的一些事件(在第6章中討論環形緩衝區)。
或者,如果在設計電路板的時候有輸入,我強烈推薦在電路板上預留多餘的處理器i/o引腳,並可以容易地通過標頭檔案進行訪問。它們可以在除錯的時候派上用場(特別是複雜的時序問題,如序列輸出破壞時序),用於顯示被測試的系統狀態,並獲取處理器週期剖面。
嵌入式系統設計與實踐
嵌入式系統設計與實踐 基本資訊 原書名 embedded systems 譯者 餘水清 叢書名 o reilly精品圖書系列 出版社 機械工業出版社 isbn 9787111415848 出版日期 2013 年5月 開本 16開 頁碼 1 版次 1 1 所屬分類 計算機 更多關於 嵌入式系統設計與實...
嵌入式系統設計與實踐
嵌入式系統設計與實踐 基本資訊 原書名 embedded systems 譯者 餘水清 叢書名 o reilly精品圖書系列 出版社 機械工業出版社 isbn 9787111415848 出版日期 2013 年5月 開本 16開 頁碼 1 版次 1 1 所屬分類 計算機 更多關於 嵌入式系統設計與實...
《 嵌入式系統設計與實踐》一一第1章 導論 1 0
第1章 導論 不同的人對嵌入式系統有不同的理解。對於從事伺服器開發的人來說,在手機上開發的應用程式就是乙個嵌入式系統。對於為8位微處理器寫過程式的人來說,任何執行在作業系統上的應用程式都不是嵌入式的。我要告訴非技術人員的是,嵌入式系統就像微波爐或者汽車,雖然執行軟體但不是計算機 大多數人認為計算機是...