嵌入式控制系統設計/從失敗中學習
工程師必須牢記,他們建立的每臺裝置最終都會失效。應盡一切手段避免災難性故障,因為這會導致人員受傷甚至死亡。工程故障的一些主要原因是知識不足、低估影響以及無知或疏忽。
本章列舉了一些災難性故障的例子。透過研究這些例子,工程師可以學習如何在自己的設計中避免故障。
1991 年 2 月 25 日,在海灣戰爭期間,一枚駐紮在沙烏地阿拉伯達蘭的美軍愛國者導彈未能攔截一枚來襲的伊拉克飛毛腿導彈 [1]。這次失敗導致 28 名美軍士兵死亡。
問題的根源在於負責追蹤來襲飛毛腿導彈的計算機。這臺計算機以十分之一秒為單位將時間儲存為整數,並將時間儲存在長度為 24 位的暫存器中。之後,將這個值乘以一個 24 位的定點表示的 0.1,以獲得一個 48 位浮點表示的以秒為單位的時間值。
故障是由 2 進製表示的 24 位 0.1 引起的。0.1 在 2 進制中的表示是非終止的:0.0001100110011001100110011001100.... 愛國者導彈中的 24 位暫存器儲存了 0.00011001100110011001100,引入了 0.0000000000000000000000011001100... 的二進位制誤差,大約為 0.000000095 十進位制。這意味著時間的準確性降低了 0.0001%。
然而,導彈的追蹤並不依賴於絕對時鐘時間,而是依賴於兩次不同雷達脈衝之間的時間差。由於這個時間差非常小,0.0001% 的誤差實際上是微不足道的。這無法解釋愛國者導彈的偏離,但還有第二個問題。
計算機使用的軟體是在 20 年前用匯編語言編寫的。為了應對該系統最初並非為其設計的高速彈道導彈,軟體經過多次更新。其中一個更新包含一個子程式,可以更精確地將時鐘時間轉換為浮點數。然而,該子程式並沒有插入到它需要的每個地方。因此,由於一個雷達脈衝的不太精確的截斷時間減去另一個雷達脈衝的更精確的時間,誤差不再抵消。
飛毛腿導彈到達時,計算機已經運行了 100 個小時,因此計算出的經過時間誤差為 0.000000095×100×60×60×10=0.34 秒。飛毛腿導彈的速度約為每秒 1676 米,因此在這個誤差時間內會移動超過半公里。這足以使來襲的飛毛腿導彈位於愛國者導彈的“射程範圍”之外。
這個問題的解決方案在事故發生之前就已經提出。透過使用更多位來提高時間表示的精度。然而,這個解決方案只是避免了問題發生,並沒有解決問題。如果計算機在幾年內沒有重啟,相同的故障仍然可能發生。
有一個更好的方法。只需測量兩次雷達脈衝之間的相對時間。時鐘應始終在第一個脈衝時復位,並在第二個脈衝時停止。這避免了兩個幾乎相同的大的數字之間的減法,以及它的數值問題。
- 應該重寫一個演算法,該演算法使用大型數字進行減法以避免這種數值精度損失。
- 在設計中分析用於表示物理引數(例如時間)的位數非常重要。
- 系統設計者需要對所使用的所有元件進行非常詳細的規格說明。
1997 年 7 月 4 日,火星探路者成功降落在火星表面。然而,在執行任務開始後的幾天,由於多次系統復位,探路者開始丟失資訊。該問題的根源在於探路者使用的嵌入式系統核心。
航天器的任務以執行緒的形式執行,這些執行緒具有優先順序,反映了每個任務的緊急程度。執行緒有 3 種類型
- 高優先順序執行緒,例如匯流排管理任務。
- 中等優先順序執行緒,例如通訊任務。
- 低優先順序執行緒,例如氣象資料收集任務。
在執行匯流排管理任務期間,它會將資料進出資訊匯流排(連線航天器所有元件的匯流排)。對該匯流排的訪問與互斥鎖同步。氣象資料收集任務使用資訊匯流排釋出其資料。在釋出時,它會獲取一個互斥鎖,寫入匯流排,然後釋放該互斥鎖。使用互斥鎖可確保每個匯流排執行緒等待前一個執行緒完成。
通常,具有優先順序的執行緒系統和使用互斥鎖的匯流排管理工作得很好。但是,會發生一個稱為優先順序反轉的問題。假設當高優先順序匯流排管理任務因等待低優先順序氣象資料執行緒而被阻塞時,排程了一箇中等優先順序的通訊任務。通訊任務的優先順序高於氣象任務,將阻止氣象任務執行,從而阻止被阻塞的匯流排管理任務執行。由於通訊任務是一個長時間執行的任務,一個看門狗定時器最終會超時,注意到資料匯流排任務已經有一段時間沒有執行了。看門狗任務將得出結論,認為發生了一些錯誤,並啟動系統總重置。此重置類似於家用電腦的重啟;它清除暫存器,以便系統可以無錯誤地重新啟動。
這個問題有幾個解決方案。其中之一稱為優先順序繼承。氣象執行緒將繼承匯流排管理任務的優先順序,使其被安排的優先順序高於通訊任務。
幸運的是,VxWorks 包含一個 C 語言直譯器,旨在允許開發人員在系統除錯期間動態輸入 C 表示式和函式以執行。在將正確的程式上傳到航天器以更改其軟體後,問題得到了解決。
重要的是要認識到優先順序繼承不是解決此問題的最佳方案。在複雜的系統中,數十個匯流排任務相互互動,所有任務最終將獲得最高優先順序,問題仍然存在。然而,在探路者的情況下,它就足夠了。
- 使用優先順序協調任務不是最佳方法。這種間接方式將所有責任都交給了排程器。最好將協調納入系統本身[2].
- 當發生不可預見的錯誤時,提供干預支援很重要。
- 看門狗:每個 ECS 都應該包含一個看門狗任務,因為系統塊永遠不能被排除。
- 現場除錯設施:如果沒有在現場修改系統的能力,問題就無法得到糾正。
- 不可能完全測試每種情況。如果時間(協調)很重要,位元組數很重要……,除錯總是可能需要的。
- 好的理論很重要:解決此問題的理論解決方案早在幾年前就發表在論文中。
- 正確性很重要:工程師最初的分析“資料匯流排任務執行非常頻繁且時間緊迫——我們不應該花額外的時間來執行優先順序繼承”是錯誤的。正是這種時間緊迫且重要的場景,正確性非常重要,即使需要一些額外的效能成本。
阿麗亞娜 5 號 501 航班於 1996 年 6 月 4 日發射,是歐洲第一次不成功的測試飛行。由於控制軟體故障,火箭在發射後 37 秒偏離了飛行軌跡,並被其自動自毀系統摧毀,當時高氣動力導致運載工具核心解體。這是歷史上最臭名昭著的計算機錯誤之一。阿麗亞娜 5 號首飛突然改變飛行軌跡的原因是什麼?當然,在沒有進行模擬的情況下重複使用與之前阿麗亞娜 4 號專案類似的軟體程式碼是一個重大錯誤。
由於一個稱為 BH(水平偏差)的內部對齊函式結果的意外高值,發生了運算元錯誤,該結果與平臺感測到的水平速度有關。該值計算為隨時間推移的對齊精度的指示器。BH 的值遠高於預期,因為阿麗亞娜 5 號的早期軌跡與阿麗亞娜 4 號不同,導致水平速度值明顯更高。從64 位浮點數 到16 位 有符號整數的執行資料轉換期間發生了內部軟體異常。轉換的浮點數的值大於 16 位有符號整數可以表示的值。這導致運算元錯誤,導致機載計算機發送診斷資料而不是實際飛行資料。此診斷資料命令噴嘴突然偏轉,並引起高迎角。(有關更詳細的資訊,請參閱阿麗亞娜 5 號報告)
整個軌跡的模擬(靜態程式碼分析)應該會立即指出溢位錯誤。此步驟應該在設計過程中的架構設計或實現(原型製作)階段執行。
此示例說明了資料溢位軟體故障的嚴重後果,其中機載計算機僅接收診斷資訊而不是實際飛行資料。雖然阿麗亞娜 5 號的故障部件有備份系統,但由於備份系統使用了相同的軟體程式碼,因此無法防止故障。在 501 航班事故發生後,人們吸取了一些教訓
- 準備一個測試設施,包括儘可能多的真實裝置,注入真實的輸入資料,並對整個系統進行完整的閉環測試:雖然一個(軟體)子系統在以前的嵌入式控制系統中執行良好,但它仍然可能作為新嵌入式系統中的子系統而失敗,即:始終質疑子系統的可重用性。在本例中,軟體在阿麗亞娜 5 號上失敗,而在之前的阿麗亞娜 4 號火箭上執行良好!事故發生後,靜態程式碼分析痛苦地顯示了溢位。
另請參閱#Therac-25,瞭解另一個由於重複使用軟體而導致的故障。
- 感測器必須在任何情況下都能返回可靠的資料:在本例中,IRS(慣性參考系統)由於 16 位有符號整數值的溢位而返回診斷資料而不是實際飛行資料。在某些情況下,感測器最好什麼也不返回(或僅返回警告訊號),而不是返回不可靠的資料。
- 與複雜計算系統相關的巨大風險引起了公眾、政界人士和高管的注意,導致人們更加支援確保安全關鍵系統可靠性的研究。隨後對阿麗亞娜程式碼的自動分析是透過抽象解釋進行大規模靜態程式碼分析的第一個例子。
注意:在實踐中,安全性、經濟性(環境)……方面之間始終存在權衡。例如:在上面的例子中,感測器是安全地將宇航員送回地球的關鍵元件,而作為傳送帶系統一部分的感測器對生命威脅要小得多。通常,安全性在航空、航空航天和核能領域具有最高優先順序!
在第 10 次太空飛行中,挑戰者號太空梭在發射後 73 秒解體。7 名宇航員遇難。這次事故的原因不僅是機械性的,也是心理性的,即所謂的群體思維!
鑑於美國國家航空航天局 (NASA) 的成功歷史,NASA 團隊的官員決定在無視工程師的警告的情況下發射航天器,他們有一種不可戰勝的感覺。該團隊長期緊密合作,他們承受著巨大壓力,要求在沒有進一步延遲的情況下發射太空梭,因此他們集體同意發射決定。然而,工程師們知道推進劑火箭的橡膠密封件(一個O 型環)在冰點溫度下無法正常工作。1986 年 1 月 28 日的低溫導致 O 型環洩漏熱流,因此是造成 7 人死亡的可以避免的原因。
這個例子展示了一種硬體故障模式:溫度對材料變形的影響。在大多數情況下,系統的所有元件都可以完美地協同工作,但在惡劣環境條件下會發生故障,例如本例中的冰點條件。
另一個重要的結論浮出水面。糟糕的設計並不總是故障的唯一原因。心理因素也很重要。這就是工程師在任何情況下都必須保持批判性,不要屈服於同伴壓力的地方。特別是在使用嵌入式控制系統的階段,操作員必須在啟動系統之前檢查環境條件是否在設計特性範圍內。由於此類心理因素造成的故障往往難以克服,可以被視為操作性故障原因。
腐蝕通常是一種難以克服的硬體故障模式。很多時候,災難發生在材料因腐蝕而坍塌時。下面介紹了其中兩個。
- 埃裡卡號的沉沒
埃裡卡號是一艘 1975 年建造的油輪,1999 年 12 月 13 日在法國海岸 70 公里處沉沒。數噸重油最終流入大海,造成世界上最嚴重的生態災難之一。事故的經濟後果在該地區得到了深刻的體現:旅遊收入下降、捕魚收入損失以及對包括牡蠣和螃蟹在內的海產品的貿易禁令加劇了人們的不適。
至少從 1994 年起,埃裡卡號的腐蝕問題就已顯而易見。此外,它的消防系統和惰性氣體系統存在許多缺陷,造成爆炸風險。勞埃德船級社報道稱,在事故發生前幾周,人們發現了嚴重的腐蝕。然而,並沒有採取任何立即的補救措施。
- 阿羅哈事件
1988 年 4 月 28 日,執行該航班的阿羅哈波音 737 飛機在飛行中發生爆炸性減壓後遭到嚴重損壞,但能夠安全降落在毛伊島的卡胡魯伊機場。一名空姐不幸遇難,她被吹出了飛機,另外 65 名乘客和機組人員受傷。在飛機上,發現了多個部位存在疲勞損傷,導致結構性破壞。國家運輸安全委員會在 1989 年釋出的調查報告將事故歸咎於運營商的維護計劃未能發現腐蝕損傷。由於老舊飛機通常不會被銷燬,很可能最終會在另一家運營商手中繼續服役,因此工程師需要充分了解老舊飛機的安全問題,並需要持續地實施安全計劃。
在產品測試階段,老化效應和材料腐蝕不可見,但必須不可避免地予以考慮!在設計大型嵌入式控制系統時,工程師應該具有長遠的眼光,因此應從公司設計流程中的不同角度進行考慮。售後服務、維護和測試可以作為大型嵌入式系統的解決方案,可以防止公司長期聲譽受損。
Therac-25 是一款計算機控制的放射治療機,在 1985 年至 1987 年期間,它嚴重超劑量照射了 6 人。其中 3 人死亡。對 Therac-25 的案例研究將揭示以下設計難題
- 軟體可能會發生故障
- 測試可能很困難,但必不可少
- 軟體重用可能很危險
- 安全性與可用性是相互矛盾的設計標準
在本例中,錯誤在於重用和信任舊軟體。這通常是在高階設計中犯的錯誤。
本文將首先討論該機器的背景。在接下來的部分中,將描述一些相關的意外事故。接下來,本文將重點介紹與事故相關的某些軟體問題。在最後的部分中,將討論從事故中可以吸取的一些工程教訓。
Therac-25 由加拿大原子能有限公司 (AECL) 和 CGR 生產,是一種醫療線性加速器。這類加速器產生高能束流,以便在對周圍健康組織的影響最小的情況下破壞腫瘤。Therac-6 只能產生X 射線,而 Therac-20 是一種雙模式(X 射線或電子束)加速器,是 Therac-25 的前身。這兩臺機器都是 CGR 老式機器的版本,這些機器已經具有臨床使用歷史,並增加了小型計算機。它們都具有有限的軟體功能:計算機只是為現有硬體增加了便利性。老式機器的硬體安全功能得以保留。
幾年後,AECL 開發了一種新的加速概念(“雙程”),它需要的空間更少,使用更方便,生產成本更低。這種概念應用於 Therac-25 雙模式線性加速器。
在每種模式(電子或 X 射線)下,用於建立合適束流的必要工具都安裝在轉檯上,轉檯旋轉裝置進入束流。因此,Therac-25 的正常執行取決於轉檯的位置。在 X 射線模式下,安裝在轉檯上的一個束流整形器用於建立均勻的治療場。為了產生與電子模式輸出相當的輸出,這需要很高的輸入劑量率。轉檯位置錯誤會導致整形器位置錯誤,從而導致高輸出劑量。顯然,在使用雙模式機器時,這是一個嚴重的危害。
雖然 Therac-25 受與 Therac-6 和 Therac-20 相同的計算機控制,但它們之間也存在一些差異。Therac-6 和 Therac-20 的硬體能夠獨立執行(例如,機械聯鎖,確保安全執行)。然而,Therac-25 的軟體承擔了更多維護安全方面的責任:機器更多地依賴於軟體,而不是硬體安全機制。在 Therac-25 的軟體設計中,Therac-6 的設計特性和模組被重複使用。該軟體還包含一些 Therac-20 例程。
在 Therac-25 中,軟體的任務是控制和檢查轉檯的位置。然而,該軟體並不完美,導致 6 人接受了大量超劑量照射。這在意外事故部分中有更詳細的解釋。
當軟體檢測到錯誤時,機器可以透過兩種方式關閉
- 治療暫停:需要重置機器才能重啟
- 治療暫停:只需要一個按鍵命令即可重啟機器。
當發生“治療暫停”時,操作員只需按“P”鍵“繼續”即可恢復治療,無需重新輸入治療資料。如果該功能被呼叫 5 次,機器將自動暫停治療。
1985 年 7 月,安大略省(加拿大)
Therac-25 啟用後約 5 秒,機器關閉。它顯示“治療暫停”,並且沒有進行劑量照射。操作員嘗試透過按下“P”鍵進行第二次治療,但機器連續關閉了 4 次,直到進入“治療暫停”。治療結束後,患者抱怨治療區域有灼痛感。實際上,患者接受了大量的超劑量照射,約為預期劑量的 100 倍。正常的單次治療劑量約為 200 拉德。如果對全身照射 1000 拉德的劑量,甚至會致命。
在調查這起事故後,AECL 發現了一些弱點和機械問題,但無法重現發生的故障。隨後,AECL 對一些機制進行了重新設計,並修改了軟體以解決這些問題。在這些改進之後,AECL 聲稱“對新解決方案的風險率分析表明,與舊系統相比,其風險率至少提高了五個數量級”。然而,風險分析似乎沒有考慮計算機故障。因此,發生了更多事故。
1986 年 3 月,東德克薩斯癌症中心 (ETCC)
操作員對機器有豐富的操作經驗,可以快速輸入處方資料。她想輸入“e”(代表電子模式),但她錯誤地按下了“x”鍵(代表 X 射線)。為了糾正錯誤,她使用了“向上鍵”,並快速更改了模式輸入。其他治療引數保持不變。為了開始治療,她按下了“B 鍵”(光束開啟)。片刻後,機器關閉並顯示錯誤資訊:“故障 54”,該資訊未在機器手冊中解釋或提及。機器進入“治療暫停”狀態,這表明存在低優先順序問題。機器顯示劑量不足,因此操作員按下了“P 鍵”以繼續治療。機器再次關閉,並顯示故障 54 錯誤。病人抱怨他感到像觸電一樣,並立即接受檢查。然而,醫生沒有懷疑到任何嚴重問題。實際上,病人接受了大量的過量照射。事後估計,實際劑量為 16500 到 25000 勒德。五個月後,病人死於過量照射併發症。
1986 年 4 月,東德克薩斯癌症中心 (ETCC)
在 ETCC 首次事故發生三週後,再次發生類似事故。同一操作員發現模式輸入錯誤,並使用“向上鍵”進行更正。機器再次顯示故障 54 錯誤。這名病人於事故發生三週後死於過量照射。ETTC 物理學家在第二次事故發生後立即將機器停用,並自行調查了該錯誤。記住自己操作步驟的操作員與他一起進行了調查。經過大量努力,他們成功地重現了故障 54 錯誤。重現該錯誤的關鍵因素是資料輸入速度:如果資料輸入速度過快,就會出現錯誤。
Therac-20 中存在相同的計算機錯誤。但由於 Therac-20 具有獨立的硬體保護電路,因此該問題只是一個麻煩。
我們將研究軟體的一小部分,但這足以展示整體設計缺陷。
事故中涉及的兩個基本錯誤是
- 糟糕的軟體工程實踐
- 構建依賴軟體進行安全操作的機器
競爭條件 可能是由於多工實現造成的。以下原因說明了為什麼
- 允許併發訪問共享記憶體
- 除了儲存在共享變數中的資料之外,沒有真正的同步
- 共享變數的“測試”和“設定”不能分成兩個單獨的操作。
這些競爭條件在事故中發揮了重要作用。

ETCC 事故的軟體錯誤
圖 1 說明了治療過程。治療監控器 (Treat) 根據 Tphase 變數的值控制八個治療操作階段或子例程。子例程 Datent(資料輸入)和鍵盤處理程式任務使用共享變數(資料輸入完成標誌)相互通訊。資料輸入完成後,鍵盤處理程式任務會更改該共享變數的值,指示 Datent 更改 Tphase 的值。Datent 子例程退出返回到 Treat,Treat 將重新排程自己以啟動下一個子例程。
另一個共享變數 MEOS 包含操作員指定的模式和能量等級。MEOS 由 2 個位元組組成:一個低位位元組用於設定轉檯,一個高位位元組用於 Datent 設定多個操作引數。
操作員被迫透過資料輸入過程輸入模式和能量等級,但他們可以在之後編輯資料。當操作員在鍵盤處理程式任務設定“資料輸入完成”標誌後更改 MEOS 中的資料時,就會出現問題。Datent 此時已經退出,因此不會檢測到更改。然而,轉檯是根據 MEOS 的低位位元組設定的,因此可能與高位位元組中的資訊不一致。這種不一致顯然無法被軟體檢測到。
Datent 透過高位位元組資訊完成操作引數設定後,會呼叫子例程 Magnet,用於設定轉檯的彎曲磁鐵。以下虛擬碼展示了軟體的相關部分(摘自 Nancy Leveson 的論文,第 27 頁)
Datent
if mode/energy specified then
begin calculate table index
repeat
fetch parameter
output parameter
point to next parameter
until all parameters set
call Magnet
if mode/energy changed then return
end
if data entry is complete then set Tphase to 3
if data is not complete then
if reset commando entered then set Tphase to 0
return
Magnet
Set bending magnet flag repeat Set next magnet call Ptime if mode/energy has changed then exit until hysteresis delay has expired Clear bending magnet flag return
Ptime
repeat
if bending magnet flag is set then
if editing taking place then
if mode/energy has changed then exit
until hysteresis delay has expired
Clear bending magnet flag
return
設定磁鐵大約需要 8 秒。子例程 Ptime 用於引入此延遲。Ptime 被多次呼叫,因為需要設定多個磁鐵。為了指示正在設定彎曲磁鐵,在進入 Magnet 時會初始化一個標誌。此標誌在 Ptime 結束時被清除。當提交編輯請求時,鍵盤處理程式會設定一個共享變數,該變數由 Ptime 檢查。如果存在編輯,Ptime 會退出到 Magnet,Magnet 然後退出到 Datent。但是,此共享變數僅在設定彎曲磁鐵標誌時被檢查。但此標誌在第一次執行 Ptime 後被清除。因此,在第一次透過 Ptime 後執行的任何編輯都不會被注意到!在 ETCC 事故中,由於編輯是在 8 秒內完成的,因此發生了錯誤。因此,Datent 永遠無法檢測到更改。透過在所有磁鐵設定完畢時(在 Magnet 結束時)清除彎曲磁鐵標誌,部分解決了這個問題。
我們可以從這些事故中吸取一些教訓。
- 不要忽視或過度依賴軟體
工程師不能假設問題是由硬體引起的。需要進行軟體級別的廣泛測試和安全分析,而不僅僅是系統級別的分析。每個安全關鍵系統都應具有事故分析程式,這些程式應在即將發生可能導致事故的問題時應用。
- 謹慎使用軟體重用
軟體重用並不意味著安全,因為已經進行了廣泛的測試。在許多情況下,修改甚至重寫整個軟體可能更安全,因為每次新開發都會引入自己的(新的)錯誤。
- 針對最壞情況進行設計
正確檢測和指示錯誤(向操作員)至關重要,以便採取正確的步驟。從一開始就在軟體中設計錯誤檢測程式碼,是獲取有關錯誤的正確資訊的一種方法。在進行權衡決策時,必須優先考慮自檢、錯誤檢測和錯誤處理功能。
- 醫療裝置:Therac-25 Nancy Leveson,華盛頓大學
- 工程災難和從失敗中吸取教訓 Vasudevan Srinivasan、Gary Halada 和 JQ,紐約州立大學石溪分校材料科學與工程系
- 腐蝕災難
- L. Sha、R. Rajkumar 和 J. P. Lehoczky。優先順序繼承協議:一種
即時同步方法。在 IEEE 計算機學報,第 39 卷,第 1175-1185 頁,1990 年 9 月。