FreeRTOS學習筆記3-任務的幾種狀態及轉換


如果將所有任務都設置在相同的優先級,那么在系統跑起來之后,所有任務將進行輪盤式的調度。如果任務僅僅具有不同的優先級而沒有經過其他處理時。高優先級的任務將一直重復運行,將低優先級的任務“餓死(starved))”。

事件驅動:

為了使我們的任務切實有用,我們需要通過某種方式來進行事件驅動。一個事件驅動任務只會在事件發生后觸發工作(處理),而在事件沒有發生時是不能進入運行態的。調度器總是選擇所有能夠進入運行態的任務中具有最高優先級的任務。一個高優先級但不能夠運行的任務意味着不會被調度器選中,而代之以另一個優先級雖然更低但能夠運行的任務。因此,采用事件驅動任務的意義就在於任務可以被創建在許多不同的優先級上,並且最高優先級任務不會把所有的低優先級任務餓死。

任務有兩種大的運行狀態:運行態和非運行態。非運行態有較多類型,以下一一解釋:

1 阻塞態 blocked:

任務可以進入阻塞態以等待以下兩種不同類型的事件:
1. 定時(時間相關)事件——這類事件可以是延遲到期或是絕對時間到點。比如說某個任務可以進入阻塞態以延遲10ms。
2. 同步事件——源於其它任務或中斷的事件。比如說,某個任務可以進入阻塞態以等待隊列中有數據到來。同步事件囊括了所有板級范圍內的事件類型。

任務可以在進入阻塞態以等待同步事件時指定一個等待超時時間,這樣可以有效地實現阻塞狀態下同時等待兩種類型的事件。

我們可以利用阻塞態進行相應的延時操作提高系統的效率,原來使用for循環或者while循環進行延時,處理器進行的都是很多無用的操作。使用阻塞態進行延時時,處理器可以處理其他任務。從而提高了系統的效率。調用vTaskDelay() API 函數來代替空循環即可。

void vTaskDelay( portTickType xTicksToDelay );

xTicksToDelay 延遲多少個心跳周期。調用該延遲函數的任務將進入阻塞態,經延遲指定的心跳周期數后,再轉移到就緒態。

舉個例子,當某個任務調用vTaskDelay( 100 )時,心跳計數值為10,000,則該任務將保持在阻塞態,直到心跳計數計到10,100。
常數 portTICK_RATE_MS 可以用來將以毫秒為單位的時間值轉換為以心跳周期為單位的時間值。

2 掛起狀態 (suspended))

。讓一個任務進入掛起狀態的唯一辦法就是調用vTaskSuspend() API 函數;而把一個掛起狀態的任務喚醒的唯一途徑就是調用vTaskResume() 或vTaskResumeFromISR() API 函數。大部分應用程序都不需要進入掛起狀態。不在詳細贅述。

3 就緒狀態 (ready)

任務處於非運行狀態,但既沒有阻塞也沒有掛起,則這個任務處於就緒(ready,准備或就緒)狀態。處於就緒態的任務能夠被運行,但是沒有運行。當前狀態的任務已經具有了所有可執行的條件,只等待處理器將他進行調度。

其他延時函數:

vTaskDelayUntil() API 函數的參數就是用來指定任務離開阻塞態進入就緒態那一刻的精確心跳計數值。API 函數vTaskDelayUntil()可以用於實現一個固定執行周期的需求(當你需要讓你的任務以固定頻率周期性執行的時候)。由於調用此函數的任務解除阻塞的時間是絕對時刻,比起相對於調用時刻的相對時間更精確(即比調用vTaskDelay()可以實現更精確的周期性)。

 


免責聲明!

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



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