- RTOS的基本概念
實時操作系統(Real Time Operating System)的簡稱就叫做RTOS,是指具有實時性、能支持實時控制系統工作的操作系統,RTOS的首要任務就是調度所有可以利用的資源來完成實時控制任務的工作,其次才是提高工作效率。
絕大多數比較簡單的產品(中小型產品)是直接在單片機上“裸奔”的,也就是產品不需要搭載RTOS的,但是產品的各個功能想要正常工作都需要主程序來進行調度。
其實RTOS就是一段嵌入在程序中的代碼,在系統上電復位后首先被執行,可以理解為用戶的主程序,只不過用戶把產品的其他功能(子程序)都建立在RTOS之上,在RTOS中可以調用API函數為每個子程序都創建一個任務(也可以叫做線程),用戶只需要調用RTOS內核中的相關的API函數接口就可以控制子程序,而且可以為每個任務設置不同的優先級,通過RTOS的調度器進行調度,這樣就可以合理的使用CPU。
這里就涉及到產品的設計思路(裸機開發 or RTOS)以及程序的運行方式,可以分為三種:
- 輪詢式
輪詢系統指的是程序運行時,先初始化各種硬件,初始化硬件之后程序進入一個死循環中,按照事件的順序進行執行,該系統的結構非常簡單,只適用于按照順序執行事件并且沒有外部事件來打斷的情況,輪詢系統就非常可靠,但是一旦有外部事件或者外部需要檢測的信號來打斷,則會造成外部事件的缺失。
int main(){//硬件的初始化while(1){//事件1 LED//事件2 BEEP//....... KEY}}
- 前后臺
前后臺系統就是在輪詢系統的基礎上增加了中斷,進行外部事件檢測的時候就在中斷中實現,所以中斷也被稱為前臺,而其他事件還是在主程序的死循環中按照順序執行,一旦中斷發生,則會暫停執行后臺的while(1),然后去執行前臺的中斷服務函數,如果事件簡短,直接在中斷中實現,如果事件復雜,則返回主程序的死循環實現,該方案可以提高程序的實時響應能力。
int main(){//硬件的初始化//注冊中斷,設置中斷的觸發條件while(1){//事件1//事件2.....}}//中斷服務函數void XXX_IRQ (void){//執行中斷的事件//執行完成返回main函數}
- 多任務
多任務系統指的是在前后臺系統的基礎上執行外部事件,只不過外部事件是放在任務中執行,不在中斷服務函數中執行,一旦某個外部事件滿足觸發條件,就在中斷服務函數中設置事件標志,然后在跳轉到任務中執行事件,任務分優先級的,優先級高的任務就先執行,所以程序就會被分割為一個個的任務(不能退出),每個任務都有一個獨立的函數來執行的功能。更大程序提高程序的實時性。
void task1(void *arg){while(1){//LED}}void task2(void *arg){while(1){//BEEP}}int main(){//硬件的初始化//注冊中斷,設置中斷的觸發條件//注冊任務,根據任務調度器進行調度}
- RTOS的種類
RTOS是實時操作系統的統稱,不意味著是某一種確定的操作系統,而是指某一類操作系統,比如最常用的uC/OSII、uC/OSIII、FreeRTOS、RTX、RT-Thread、Huawei LiteOS........每種RTOS各有特色,所以大家可以根據實際需要選擇對應的RTOS進行學習。
- uC/OS
uC/OS是Micrium公司推出的RTOS實時操作系統,分為兩個版本: uC/OSII 和 uC/OSIII,該RTOS的特點是開源的、可裁剪的、具有可剝奪型內核,uC/OSII可以支持創建最多255個任務,而uC/OSIII對任務數量沒有限制。
uC/OS的發布時間是較早的,所以中文資料是最多的,并且代碼例程比較豐富,但是想要在商業中進行使用,需要取得正版授權(花錢),所以大家可以把UCOS作為RTOS的入門。關于uC/OS的資料和源碼都可以去官網下載 官網地址:www.micrium.com
- FreeRTOS
FreeRTOS也是RTOS的一種,在2003年發布,是免費的,雖然起步比UCOS晚,但是由于可以在商業中免費使用,所以目前的市場占有率是最高的,并且很多的半導體公司都和FreeRTOS有很緊密的合作關系,這些半導體公司的評估板絕大多數都是采用FreeRTOS進行程序設計。比如半導體公司發布的SDK(開發工具包)一般也采用FreeRTOS,另外,像藍牙、WIFI等帶協議棧的芯片或者模塊也是采用FreeRTOS。
相比于UCOS而言,FreeRTOS的文件數量更少,占用內存空間更少,所以在移植到不同硬件平臺的時候更加輕松,FreeRTOS對于任務數量也是沒有限制的,而是對于任務的優先級也沒有限制。
FreeRTOS支持搶占式、時間片調度等算法,而且FreeRTOS是完全免費的,這也是FreeRTOS的核心競爭力。
FreeRTOS可以用在商業領域,不具有版權問題,如果在產品中使用FreeRTOS時沒有修改原碼,則產品不需要開源,如果使用FreeRTOS的過程修改了原碼,則需要把修改的那部分代碼進行開源,遵循MIT開源協議。
大家可以去FreeRTOS的官網下載源碼以及其他的資料,比如FreeRTOS提供了若干本書籍,比如關于RTOS的API函數的參考手冊以及新手教程。 官網地址:www.freertos.org
- RT-Thread
長期作業:自行觀看RT-Thread的相關視頻和教程,要求大家可以自行完成Rt-thread的移植。
- RTOS的源碼下載
想要真正掌握RTOS,則必須要去閱讀RTOS的源碼,才能理解RTOS是如何對任務進行調度
可以去FreeRTOS的官網下載源碼。
- 點擊選項鏈接跳轉GitHub托管網站,下載FreeRTOS以前的發行源碼包, 比如 V9.0.0
- 點擊GitHub的標簽tags,顯示所有的FreeRTOS的源碼發行版,搜索到V9.0.0版本即可
注意:如果瀏覽器在登錄GitHub網站時等待時間過長,或者無法登錄界面,則可以使用其他的代碼托管網站進行源碼下載,比如Sourceforge代碼托管網站 ,搜索FreeRTOS即可。
- RTOS源碼結構
解壓好的源碼包內部有一個叫做FreeRTOS的文件夾,該文件夾內部包含FreeRTOS的源碼以及許可和通用的頭文件,并且還提供豐富的案例供用戶在不同的硬件平臺使用。
Demo中提供了很多個半導體公司的評估板的代碼例程,用戶可以參考甚至直接使用。而License文件夾中包含了FreeRTOS的許可文件,大家可以在商業軟件中進行參考,在Source文件夾中包含通用的頭文件以及針對不同硬件平臺的移植文件供用戶使用。
五、FreeRTOS的移植
如果想要在項目中利用RTOS對任務進行調度,則需要把RTOS的源碼移植到自己的項目中,移植的步驟如下:
- 去FreeRTOS的官網下載源碼包,源碼包的版本可以是V9.0.0或更新的版本 (比較穩定)
- 把源碼包解壓到本地,分析源碼包中哪些文件需要移植,可以瀏覽源碼包的readme.txt
- 把FreeRTOS源碼包中需要移植的文件拷貝到自己工程中對應的文件夾,操作如下所示:
- 打開自己的工程,把拷貝過來文件添加到KEIL5工程中,編輯文件夾的結構,如下所示
- 配置KEIL5工程的頭文件的路徑,確保編譯器可以找到關于FreeRTOS的頭文件,如下:
- 編譯工程,如果編譯之后報錯,根據錯誤原因解決錯誤,直到編譯通過為止,如下所示
- 提示:__ICCARM__宏定義是和開發工具相關的,該宏定義是IAR軟件需要使用的,而目前采用的開發工具是KEIL,KEIL軟件需要使用其他的宏定義。
再次編譯,發現有函數出現重復定義的情況,port.c和stm32f4xx_it.c中出現,所以可以選擇分別進行分析,可以把stm32f4xx_it.c中的函數名稱刪除即可。
再次編譯,發現有5個函數未定義,命名規則是有規律的,都是HooK結尾,Hook是鉤子函數,其實屬于回調函數的一種,目前由于不知道是否需要使用,可以選擇不去定制。
由于FreeRTOS是高度可定制的,定制的功能是由FreeRTOSConfig.h決定,所以需要配置該頭文件,裁剪掉這幾個功能即可。
再次編譯,發現沒有出現任何錯誤和任何警告,則說明FreeRTOS實時操作系統移植成功!!
五、FreeRTOS的任務管理
- 任務的概念
FreeRTOS是一個支持多任務的實時操作系統,如之前裸機開發時采用的輪詢系統而言,主程序是一個死循環,CPU按照死循環中的流程執行代碼,而在多任務系統中,用戶可以把整個系統分割為多個獨立的且不能返回(死循環)的函數,這些函數就被稱為任務。
應用程序中的任務都是由FreeRTOS的調度器進行調度,同時每個任務具有獨立的棧空間,棧空間其實就是單片機中RAM的一段空間,通常可以提前定義一個全局數組,或者在創建任務的時候對任務的棧空間進行動態的分配,可以參考FreeRTOS的官方資料。
- 任務的狀態
對于FreeRTOS中的任務而言,FreeRTOS的調度器會根據任務的狀態決定運行哪個任務,任務的狀態一共有四種:運行態、就緒態、掛起態、阻塞態。 可以參考FreeRTOS的官網資料。
- 任務優先級
FreeRTOS可以為每一個創建的任務分配一個優先級,當然也可以讓多個任務共用一個優先級,這里就涉及到調度器的調度算法,有搶占式、時間片一共2種算法。
- 任務的創建
剛才提到過任務都是獨立的,并且每個任務都需要占用一部分RAM空間,單片機中的RAM是有限的,所以FreeRTOS就提供了兩種方案為每個任務分配棧空間:靜態分配 + 動態分配,而且FreeRTOS提供了不同的函數接口給用戶去申請任務的空間。兩種分配方案的區別如下:
一般情況下采用動態分配的方案,所以需要調用API函數,名字叫做xTaskCreate(),如下圖
- 啟動調度器
- 任務的刪除
FreeRTOS中的任務是可以刪除的,如果用戶創建的任務只打算運行一次就可以刪掉,調用函數接口 vTaskDelete() ,調用該函數就可以把動態創建或者靜態創建的任務從任務表中刪掉。
- 任務的掛起
在某些情況下,某些任務可能只運行一段時間,然后讓任務暫停運行,過一段時間繼續運行,如果采用反復刪除和反復創建的方案,就會導致任務之前的數據丟失,FreeRTOS提供一個函數可以把任務掛起,該函數為vTaskSuspend() 。
一旦任務被掛起,則不管任務的優先級是否為最高,都不會獲得CPU資源,也就是說處于掛起態的任務永遠不能進入運行態,除非該任務被恢復,如果想要恢復一個任務,則需要調用vTaskResume()。
- 任務的恢復
FreeRTOS提供了一個恢復函數,可以讓處于掛起態的任務恢復,注意只有被掛起的任務才可以被恢復。