幾十年前,嵌入式行業將重心從匯編轉移到了C編程。更快的處理器和更好的編譯器允許提高抽象層次,以提高嵌入式開發效率和質量。
我們現在正處于固件開發技術的新的重大轉變之中。實時操作系統(RTOSes)的廣泛使用代表了第三代嵌入式軟件開發。RTOSes引入了一個新的抽象層次,支持更復雜的應用程序,但也不是沒有復雜性。
RTOS是一種用于嵌入式和物聯網應用的快速、確定性操作系統。這些操作系統通常非常小,因此適合在微控制器(MCU)中使用。RTOS的主要工作是提供多線程,從而允許將軟件功能分成多個“并行”程序,這些程序被稱為“任務”RTOS通過快速切換正在執行的任務來制造并行執行的假象。與通用操作系統不同,RTOS讓開發人員能夠完全控制多線程,因此支持確定性的實時行為。
使用RTOS有很多好處,但它本身并不是一個解決方案,而且會帶來新的挑戰。許多開發商已經一頭扎進了RTOS的設計中,但往往沒有完全意識到其中的含義;他們使用的開發工具對基于RTOS的開發沒有適當的支持;由于這個原因,在嵌入式開發中,他們可能在調試和驗證方面遇到了很大的困難。
RTOS趨勢
RTOS自20世紀80年代初就已經存在,但是由于多種原因,它們變得越來越普遍。嵌入式應用變得越來越復雜、互聯和事件驅動,使用高級外設和中間件堆棧,所有這些都需要并行管理。使用RTOS大大簡化了這一過程。使用RTOS的替代方法是使用自定義狀態和邏輯自己實現某種執行控制。對于更復雜的應用程序,這往往會變得復雜,容易出錯,并且難以維護。通過使用RTOS,你將執行控制委托給高度優化的RTOS內核,該內核已經過全面的測試并在使用中得到驗證。
雖然使用RTOS意味著較小的處理開銷,但基于RTOS的設計通常比傳統的超級循環設計更有效。這是因為RTOS任務可以在不浪費處理器時間的情況下等待激活事件,并且由于較短的ISR(中斷服務例程)和搶先調度,響應時間可以更快。此外,今天的MCU通常具有快速的32位內核和大量的閃存和RAM內存,使RTOS足跡不再是一個問題。
在嵌入式開發中,免費提供的開源實時操作系統越來越受歡迎,這使得基于RTOS的設計更容易獲得,并創建了大型用戶社區——一種作為正反饋循環的“臨界質量”。RTOS不再像10-15年前那樣被大肆宣傳,而是被廣泛用于各種嵌入式應用中。倡導基于RTOS的設計的不僅僅是RTOS的商業供應商;現在,許多MCU廠商的軟件開發套件中都包含了RTOS。
盡管RTOS并不是解決所有問題的“靈丹妙藥”,而且可能不適合某些系統,但實時操作系統的日益使用無疑是當今的一個主要趨勢,而且可能會繼續下去。
使用RTOS的挑戰
那么是什么讓RTOS如此特別,可以被稱為固件設計中的第三代呢?RTOS是一個非常特殊的軟件組件,因為它控制了程序的執行,并以任務的形式帶來了新的抽象層次。當使用RTOS時,程序的控制流從源代碼中不再明顯,因為RTOS決定在任何給定時刻執行哪個任務。這是一個根本性的變化,類似于從匯編到C編程的轉變,因為它允許使用更高的抽象來提高生產率,但也意味著對細節的控制更少。
這是一把雙刃劍。它可以使設計復雜的應用程序變得更加容易,但是這些應用程序隨后可能會變得難以驗證和調試。雖然RTOS可以降低應用程序源代碼的復雜性,但它不會降低應用程序本身固有的復雜性。當作為一個系統一起執行時,一組看似簡單的RTOS任務可能導致驚人復雜的運行時行為。
如前所述,RTOS本身并不是一個解決方案,對于不小心的人來說還有很多陷阱。嵌入式開發人員需要確定任務如何使用RTOS服務進行交互和共享數據。此外,開發人員需要決定重要的RTOS參數,如任務優先級(相對緊急程度),這些參數可能遠非顯而易見。即使你已經根據基于RTOS的設計的最佳實踐編寫了所有代碼,系統的其他部分(內部或第三方組件)也可能運行在相同的RTOS環境中,但可能不遵循相同的原則。
使基于RTOS的設計變得困難的根本問題是RTOS任務不是孤立的實體。任務之間至少有一種依賴關系——它們共享的處理器時間。使用固定優先級搶先調度,較高優先級的任務可以在幾乎任何時間點醒來并接管執行,從而延遲較低優先級任務的執行,直到所有較高優先級的任務都已完成。
其他類型的共享資源(如全局數據或硬件外設)也會導致任務之間的依賴性,因為必要的同步可能會阻止任務在需要時執行。如果設計不正確,這可能會導致不可預測的延遲,與任務優先級無關。
當高優先級任務(任務H)試圖訪問當前正被較低優先級任務(任務L)使用的共享資源(例如通信接口)時,可能發生優先級反轉。通常,任務H會被阻塞一小段時間,直到任務L返回共享資源。如果此時一個中等優先級的任務(任務M)恰好搶占了任務L,就會發生優先級反轉。任務H的阻塞變得更長,這都是因為一個不相關的任務具有更低的調度優先級。在NASA探路者的例子中,這導致看門狗定時器超時并重置系統。
像日程安排和共享資源這樣的任務依賴性受時間的影響;例如執行時間和輸入時間。這種定時屬性在源代碼中是不可見的,并且往往會根據系統狀態和情況而變化。在嵌入式開發中,這使得僅僅從源代碼來預測基于RTOS的系統的實時行為幾乎是不可能的。取決于許多因素,任務可能執行得比預期的慢,有隨機的意外延遲,或者根本不執行。即使系統看起來像在實驗室中預期的那樣運行,也可能有無數其他執行場景在時間上有或多或少的顯著差異,其中一些可能會導致問題。在最糟糕的情況下,系統通過了測試,但是對于你的客戶來說,系統會在隨機的情況下崩潰。這樣的問題在系統級測試中很容易被忽略。此外,除非你能夠獲得與問題相關的詳細診斷信息,否則重現它們進行分析可能是一場噩夢。
調試基于RTOS的系統
想在開發的時候在同一個抽象層次上進行調試是很自然的。當嵌入式行業從匯編轉向C編程時,調試工具很快就提供了源代碼級別的調試,從而使C代碼視角成為正常的調試視角。然而,調試工具并沒有響應RTOS的趨勢而發展到任何顯著的程度。一些調試器已經更新了“RTOS感知”功能,允許你在調試時檢查RTOS對象(如任務和信號量)的狀態。但這些是“第二代”源代碼級調試器的增量改進,嚴格關注源代碼和運行/暫停/單步調試。僅使用傳統的源代碼級調試器來調試基于RTOS的系統相當于在用c編程時使用匯編級調試器。
要完全理解基于RTOS的系統的運行時行為,你需要在RTOS級別觀察實時行為的能力;即具有RTOS感知的跟蹤工具。在嵌入式開發中,這是對傳統調試工具的補充,提供了RTOS級別的時間線,極大地方便了調試、驗證和性能優化。傳統調試器很像顯微鏡,用于檢查任務中的詳細執行,而跟蹤更像實時執行的慢動作視頻。
有兩種類型的跟蹤,目的略有不同:硬件生成的和軟件生成的。硬件生成的跟蹤在源代碼或匯編級別提供了詳細的執行跟蹤,但很少或沒有RTOS意識。為了記錄高速數據流,在處理器和板上都需要先進的跟蹤硬件和合適的跟蹤支持。這種跟蹤往往會在較低的抽象級別產生大量數據,這可能難以理解,并且僅限于處理器中實現的跟蹤功能。硬件生成的跟蹤主要用于覆蓋率分析和特別棘手問題的調試,在這種情況下需要指令級跟蹤。
軟件生成的跟蹤意味著將跟蹤代碼片段添加到目標軟件中,目的是記錄RTOS中的重要事件,也可以選擇記錄應用程序代碼中的重要事件。你通常不需要自己插入RTOS跟蹤代碼,因為這通常是由RTOS或工具供應商提供的。使用軟件跟蹤,任何軟件事件都可以被記錄,包括任何相關數據,基本上可以在任何處理器上記錄。缺點是跟蹤代碼的開銷,但現代32位MCU上的RTOS級跟蹤只需要處理器時間的百分之幾,因為需要記錄的數據相對較少,并且跟蹤的事件不是很頻繁。這使得使用通用調試接口或其他接口(如USB或TCP/IP)連續傳輸數據成為可能。低數據速率也允許跟蹤RAM緩沖器。僅僅幾千字節就足以獲得最近事件的像樣的跟蹤。這樣,追蹤也可以在實驗室之外使用;例如在現場測試或部署操作期間。
可視化對于理解痕跡至關重要。在嵌入式開發中,許多嵌入式系統都有或多或少的循環行為,因此大多數跟蹤數據都是“正常”行為的無關重復。有趣的部分通常是異常,但是如果你不知道具體要找什么,它們可能很難找到。然而,假設數據被正確可視化,人腦在識別視覺模式和異常方面是非凡的。
雖然一些工具可以將RTOS軌跡顯示為經典的甘特圖,但是這種可視化不適合在同一視圖中顯示其他事件;例如API調用或用戶登錄。但是,垂直執行跟蹤可以使用指向圖形執行跟蹤的文本標簽來顯示此類事件。此外,僅僅顯示執行跟蹤是非常有限的,因為可以從RTOS跟蹤中獲得更多的信息。例如,任務和ISR的交互可以表示為依賴圖,還可以顯示關注其他相關RTOS對象(如信號量、隊列和互斥體)的跟蹤視圖。
結論
RTOS趨勢在嵌入式行業非常明顯,這是有充分理由的。由于日益復雜和互聯的應用程序,越來越多的開發人員依賴RTOS。此外,隨著開發商被領先的解決方案所吸引,RTOS市場正在整合。
RTOS可以被視為第三代固件開發,因為多線程帶來了更高層次的抽象和對執行的更少細節控制。這有很大的缺陷,需要在RTOS級別提供更好的調試支持。然而,通用的調試工具并沒有響應RTOS的趨勢而得到顯著的發展;相反,它們通常只提供對傳統調試器概念的增量改進。
通過更好地了解基于RTOS的系統的實時執行,可以簡化這些系統的調試。這需要RTOS級別的跟蹤,其中可視化對于理解數據至關重要。在嵌入式開發中,一些工具可以將RTOS軌跡顯示為水平甘特圖,但這并不理想。更復雜的可視化是可能的和可用的,針對RTOS跟蹤進行了優化,這使得理解運行時系統、發現重要問題和驗證解決方案變得更加容易。