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