使用微控制器的電子產品如今變得如此復雜,以至于它們通常使用實時操作系統(RTOS)。RTOS可以管理低級資源和時間,從而提高系統的實時性能并簡化應用程序。
嵌入式開發團隊可能會遇到的一個問題是有100多種不同的RTOS可供選擇!對于一個團隊來說,開始使用一個產品,但6個月后決定使用另一個產品的情況并不罕見。當這種情況發生時,如果開發人員在他們的應用程序中直接使用了RTOS,他們必須返回并更改大量代碼。
另一種方法是使用操作系統抽象層(OSAL)。OSAL創建一組對應于每個RTOS中的公共特征的API。OSAL允許應用程序通過將依賴關系轉移到抽象層來打破對RTOS的依賴。應用程序不再關心你使用的RTOS,只關心抽象層。
在今天的帖子中,我們將探討為嵌入式應用創建RTOS抽象層的五個技巧。
技巧1:跨操作系統標準化操作系統抽象層(OSAL)API
OSAL的目標不是將RTOS縮小到最小公分母。相反,我們的目標是通過一個單一的標準API提供通用部分,以消除對RTOS的依賴,并改善測試和可移植性。你將需要研究流行的RTOS并確定共同的特性。
例如,如果你查看像FreeRTOS、Azure RTOS和Zephyr這樣的流行RTOS,你可能會發現它們具有以下標準功能:
線程創建
信號量的創建、獲取和放置
互斥體的創建、鎖定和解鎖
等等。
你希望識別這些標準特性,然后創建一個接口來封裝你可能使用的任何RTOS的創建細節,同時將應用程序與RTOS分離。
技巧2:選擇正確的抽象層次
當你開始為你的應用程序開發OSAL時,創建最終的抽象是很有誘惑力的。不要陷入這個陷阱!每個RTOS都有你想要利用的獨特功能,如果你把它們隔離開來,你會帶來更多的問題而不是好處。你必須選擇正確的抽象層次。
正確的抽象水平將是一個基本的標準特性。一個很好的例子是檢查CMSIS RTOSv2 OSAL。你會注意到他們抽象出的唯一特性是標準特性。你看不到他們實現定制的低功耗設置或類似的東西。相反,他們正在尋找每個RTOS提供的抽象標準功能。
技巧3:對特定于操作系統的特性使用包裝器
一旦你有了通用的API,你可能會認為你已經將RTOS簡化為通用的特性,并且你將只使用這些特性。這不是準確的想法,會有一些不常見的特性可能對你的應用程序有用。問題是,如果你直接調用這些特性,你將把你的應用程序緊密耦合到RTOS,這正是我們需要避免的!
使用RTOS特有特性的解決方案是包裝這些特性。你可能有一個覆蓋通用特性的OSAL,但是你最終會得到覆蓋RTOS特有特性的包裝器。包裝器將為應用程序提供對定制特性的訪問,同時維護允許脫離目標測試和模擬的依賴樹。
你不能忽略RTOS的競爭優勢,但你也不能抽象它們。這就是為什么使用包裝器是一個很好的選擇。如果你更改了RTOS,如果新的RTOS沒有這個特性,你可以移除包裝器并編寫任何需要的gap代碼來覆蓋缺失的功能。
技巧4:優雅地處理特定于操作系統的限制
當你開發一個OSAL時,你需要意識到你必須管理的局限性。例如,一個RTOS的最大線程數可能與另一個不同。不同RTOS的優先級排序可能會有所不同。(隨著數值越來越遠離0,FreeRTOS任務具有更高的優先級。ThreadX設置0優先級最高,數字越高優先級越低!)
你需要確保你的抽象層能夠成功地管理這些差異,而不會影響應用程序的性能。你還需要確保不會因為RTOS實現中的這些微小差異而導致系統崩潰或錯誤。
技巧5:利用單元測試工具來驗證實現
編寫自己的OSAL時,你可以采用的最佳實踐之一是使用測試驅動開發(TDD)。TDD的一部分將是你寫你的測試用例,讓它失敗,然后讓它通過。這和OSAL有什么關系?如果你編寫測試用例來驗證你的OSAL,那么當你將一個RTOS連接到你的OSAL時,你可以驗證它是否正確和成功地完成了!
如果你犯了一個實現錯誤,單元測試應該會發現它!你會立刻知道你有問題,并在它變成bug之前著手解決它。這樣做當然需要更多的工作,但是最終你會發現你會得到一個更加健壯的OSAL。
結論
并非所有應用程序的RTOS都需要OSAL。但是,如果你正在開發一個將使用五年或更長時間的應用程序框架或平臺,那么擁有一個OSAL是個好主意。嵌入式技術變化很快,你希望確保你不是在圍繞五年后可能會改變或不存在的軟件設計框架。返工軟件可能很耗時,而且會引入錯誤。使用OSAL可以確保打破這種依賴性,并且可以在抽象之后加入任何RTOS。