FreeRTOS筆記(九)任務相關的過渡
文章目錄
上一文連結:FreeRTOS筆記(八)任務切換
01 - 任務相關的過渡
1.1 - get和set函式
瞭解到任務、列表和排程器後,關於任務的核心內容應該比較清晰,FreeRTOS還有很多工的輔助函式,比如一些必要的get
和set
函式,用於獲取和設定任務的狀態和資訊,比如常見的如下
函式 | 功能 |
---|---|
xTaskGetCurrentTaskHandle() | 獲取執行態任務的控制代碼 |
uxTaskGetNumberOfTasks() | 獲取當前所有任務的數量 |
vTaskGetRunTimeStats() | 獲取任務的執行時間 |
eTaskGetState() | 獲取任務狀態 |
vTaskPrioritySet() | 設定任務優先順序 |
vTaskSetTimeOutState() | 設定任務溢位時間 |
這些輔助函式在工作進度調整的時候需要用到,比如vTaskGetRunTimeStats()
用於獲取任務佔用CPU的時間,在工作進度開始之前可以先測試每個任務的CPU佔用率,再去調整任務的優先順序。關於這些函式應該要根據實際去使用。
1.2 - delay延遲函式
為了驗證自己瞭解的任務基本內容,現在我們可以分析一下常用的延遲函式,FreeRTOS提供了兩種延遲方式,vTaskDelay()
相對延遲和vTaskDelayUntil()
絕對延遲,不同點是時間計算的起點不同,相同點是都會進入阻塞狀態,相對延遲是每次都從呼叫處的時刻為起點,而絕對延遲是根據上一次的結束點為起點,絕對延遲用於週期性任務的設定。
跟蹤vTaskDelay()
函式,可以得到常見延遲的呼叫層次如下
vTaskDelay()
prvAddCurrentTaskToDelayedList()
xTimeToWake = xConstTickCount + xTicksToWait; #以當前值為起點計算喚醒時間xTimeToWake
listSET_LIST_ITEM_VALUE() #把xTimeToWake插入任務列表項的列表值
vListInsert() #任務插入延遲列表
可以嘗試下面的追朔
這樣,喚醒任務的時間就加入任務的列表項中了,同時任務也加入延遲列表
pxDelayedTaskList
,那麼是誰喚醒的,要喚醒任務,必須把任務從延遲列表中移到就緒列表,於是追朔延遲列表的呼叫者,可以其中一個呼叫者是listGET_OWNER_OF_HEAD_ENTRY()
,繼續追朔,呼叫者是xTaskIncrementTick()
,繼續追朔,呼叫者是xPortSysTickHandler()
,到此追朔完成,上一文已經提及,xPortSysTickHandler()
是SysTick
中斷的服務函式,週期性地進行工作。
下面是喚醒的呼叫層次,喚醒的核心程式碼在xTaskIncrementTick()
中
xPortSysTickHandler() #中斷服務函式
xTaskIncrementTick() #更新xTickCount計數
pxTCB = listGET_OWNER_OF_HEAD_ENTRY() #獲取延遲列表項
xItemValue = listGET_LIST_ITEM_VALUE() #獲取喚醒時間
if( xConstTickCount < xItemValue ) #如果到達喚醒時間
uxListRemove() #把任務從延遲列表移除
prvAddTaskToReadyList( pxTCB ); #任務插入就緒列表
以上簡單總結為:呼叫vTaskDelay()
後,計算喚醒時間並加入任務屬性中,然後任務加入延遲列表,每個SysTick
中斷週期內就會檢查延遲列表中的任務是否到達喚醒時間,如果是,就從延遲列表中移到就緒列表,喚醒完成。
可以用同樣的方式追朔vTaskDelayUntil()
絕對延遲,它只是計算喚醒時間的方式不同,以上一次喚醒的時間為起點,如果是第一次呼叫,那麼起點就是任務函式的執行時刻,區別可以用下圖表達
絕對延遲vTaskDelayUntil()
除了延遲函式,還可以去分析掛起函式xTaskSuspend()
等等,任務函式相關API就過渡到這裡。
02 - 總結
- 任務有非常多的get和set函式,可以在任務執行期間獲取和設定任務的狀態和屬性
- 延遲函式分為相對和絕對,相對延遲一般用於短暫的等待,絕對延遲一般用於週期性工作
- 任務還有很多輔助API函式