FreeRTOS多任務操作系統簡單理解


聲明:博主是剛開始進行FreeRTOS的學習,對於很多地方都只是自己的理解,或許有很多沒有意識到的錯誤,如果您發現有什么問題,勞煩指出筆者必及時修改,也希望可以給更多看到這篇博文的人傳遞正確的信息。

實時多任務系統理解

FreeRTOS是一個搶占式的實時多任務系統,多任務系統是將一個大問題分成很多個小任務,任務就可以理解為裸機開發中的每一個功能的函數,但是和函數不一樣的是,裸機開發在進入到某個函數中,在結束當前函數前,其他的任何事項都會被擱置,也就是意味着同一時間只能有一個任務運行,但是操作系統卻允許多任務同時運行,類比我們的電腦,如果一次只能運行一個任務,那么移動鼠標的時候音樂就會被停止,打開網頁的時候,鼠標就動不了了,只能等待網頁打開結束才能移動鼠標,因為一次只能進行一個任務,而實際生活中,我們可以一邊聽着音樂一邊瀏覽網頁,順便還能和同學聊聊天,這就歸於操作系統的任務調度器,決定了在某一時刻究竟運行哪個任務。

實際上,一個處理器核心在某一時刻確實是只能運行一個任務的,為什么說操作系統可以同時運行多個任務呢,剛才提到的任務調度器,在各個任務之間快速的切換,這就給我們一種好像同一時刻有很多個任務同時在運行的感覺,為方便理解,就稱作同一時刻運行多個任務,剛才提到的在任務中快速切換,很形象的一點就是,我們買電腦一定會看的一個參數——CPU 的主頻,主頻越快,速度越快,實際上指的就是任務切換的非常快,而主頻慢的CPU正是由於在任務切換中過慢,導致我們感覺電腦卡頓。

另外操作系統的特點,還是由一個例子來引出:我們需求寫一個讓兩個led燈每秒閃爍一次的代碼,接着引入第一個按鍵,按下該按鍵,保留第一個led1燈的狀態,但是不影響led2的閃爍,按下第二個按鍵,將保留led2的狀態,但是不影響led1的閃爍,再次按下按鍵則恢復對應的led狀態,需求每次保留燈的狀態的時候,也必須保留led燈亮滅的時間,比如亮了0.3s,按鍵使它保留,松開按鍵的話,它只能再亮0.7s,然后繼續保持每秒閃爍。

如果裸機開發的話,想要實現這樣的場景,該怎么做?

用中斷可以實現嗎,配置定時器函數,主函數進行led閃爍,中斷判斷按鍵是否按下,按下就暫停計時器計數,松開則恢復計數器,計時器每溢出一次就改變一次led的狀態,如果一個led燈這樣做是可行的,但這里是兩個led燈,那就得設置兩個不同的定時器,分別進行計數和暫停,想想就感覺十分復雜,如果還想加入按下一個按鍵就向串口返回當前兩個led狀態呢,這才只是點亮了個led燈,明明只是這么簡單的任務,結果已經占用了這些中斷資源和等待時間,這些資源對於32來說,確實都有,那么我要繼續將這些安裝到一個遙控車上,遙控車受到控制信號靈敏響應需要中斷,車輛輪子轉速控制需要實時速度用編碼器需要中斷,車輛避障為確保靈敏也需要中斷,再加上不可避免的要使用delay()來延時,筆者曾深刻感到中斷不夠用,而且反應十分緩慢,一度更改代碼框架也難以有很好的提升,一方面是筆者寫代碼寫的很差勁,另一方面也體現出前后台系統的上限,實時性不足,對於簡單的任務(不需要大量的實時性的任務)來說前后台系統很好用,而對於某些需求來說,即使只是點個led燈,都無法正常運作。

那么使用FreeRTOS又如何實現上述問題呢?

FreeRTOS中實時應用作為一個獨立的任務,就像裸機開發中的函數一樣,每個任務執行自己對應的功能,並且每個任務都有自己的運行環境,不依賴於系統中的其他任務或者RTOS調度器,雖然任何時間都只有一個任務在運行,但具體運行哪一個任務是由RTOS調度器決定的,任務不需要了解RTOS調度器的具體行為,每個任務都有自己的堆棧,RTOS調度器的職責就是在每個任務切換的時候,確保其堆棧和寄存器內容不變,隨時可以恢復之前的狀態繼續運行。

FreeRTOS是一個搶占式的實時多任務系統,搶占就意味着任務之間有優先級,高優先級的任務可以打斷低優先級的任務,就像是裸機開發中的中斷,但又不是中斷,RTOS的運行過程如下圖:

任務狀態:

 每個任務都會處於如下幾個狀態:

運行態:就是正在運行任務的狀態,這個沒什么解釋的。

阻塞態:就像外部中斷一樣,阻塞態的任務在等待着某個信號,上述說到的 vTaskDelay() 函數就像是 delay() 延時函數,而阻塞態就是在等待着延時結束這個信號,所以說某個任務調用了 vTaskDelay() 就會進入阻塞態:這個任務在等待延時結束這個信號!!!千萬不要誤解為只有調用vTaskDelay()函數就進入阻塞態,實際上不只是等待延時結束,處於阻塞態的任務也可以是等待某個傳感器發來的信號,某個串口傳來的信息等。就像我們把串口通信寫進定時器中斷一樣,每進入一次中斷判斷一次,沒有就退出,阻塞態也是一樣,沒有等到信號量,達到了超市時間,任務就會推出阻塞態。

掛起態:任務掛起的意思是什么呢,就是暫時脫離了整個內核調用,它不在運行了,內核也不調用它了,但是進入掛起前的所有狀態都被保存着,等待着退出掛起。

就緒態:先了解上面的三種狀態了,來說明就緒態,阻塞態超時了之后會怎么樣呢,有新的任務將會去執行,而這個等待某個信號的任務已經不處於阻塞態了,但是也並沒有被掛起,而且也沒有運行,這時它就處於就緒態,已經准備好了,但是現在還在執行別的任務,就這這邊等待,可以隨時運行,這就是就緒態。

這下再看這幅圖,是否對這幾種狀態有所了解。

 上圖中箭頭的函數正是接着要使用和學習的函數,先不繼續,回想一開始的點燈任務,如果用FreeRTOS如何實現呢:

分別創建led1和led2閃爍的任務,接着創建按鍵一和按鍵二的任務,當按下按鍵一的時候掛起led1閃爍,再按下按鍵一的時候,取消led1任務的掛起,同理led2和按鍵二也如此,掛起保存了當前運行的所有狀態,所以不需要在意時間保留的問題,那些數值都被保存,而且沒有使用中斷,並且FreeRTOS的任務可以分配0~(configMAX_PRIORITIES-1)的優先級,並且當宏 configUSE_TIME_SLICING 定義為1 的時候還允許多個任務共用一個優先級,FreeRTOS調度器確保處於就緒態或者運行態的高優先級任務獲得處理器使用權,其他處於就緒態的同優先級的任務會使用時間片轉調度器獲取運行時間,那么任務優先級和中斷優先級有什么關系嗎?答案是沒有。

FreeRTOS任務優先級和中斷優先級

中斷優先級和任務優先級這兩個之間沒有任何關系,不管中斷的優先級是多少,中斷的優先級永遠高於任何任務的優先級,即任務在執行的過程中,中斷來了就開始執行中斷服務程序,這樣的話我們同時擁有了任務優先級,和中斷優先級,實時性是不是就上來了。

這里轉載一個任務優先級分配方案(出自STM32用FreeRTOS時任務優先級和中斷優先級說明 - 騎單車去旅行 - 博客園 (cnblogs.com)

IRQ 任務:IRQ 任務是指通過中斷服務程序進行觸發的任務,此類任務應該設置為所有任務里面優先級最高的。

高優先級后台任務:比如按鍵檢測,觸摸檢測,USB 消息處理,串口消息處理等,都可以歸為這一類任務。

低優先級的時間片調度任務:比如 emWin 的界面顯示,LED 數碼管的顯示等不需要實時執行的都可以歸為這一類任務。 實際應用中用戶不必拘泥於將這些任務都設置為優先級 1 的同優先級任務,可以設置多個優先級,只需注意這類任務不需要高實時性。

空閑任務:空閑任務是系統任務。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM