freeRtos学习笔(2)任务管理
freeRtos學習筆記
freeRtos任務管理
freeRtos任務狀態
freeRtos中任務有四種狀態:就緒態、運行態、杜塞態、掛起態。
圖 16-1(1): 創建任務→就緒態(Ready):任務創建完成后進入就緒態,表明任務已準備就緒,隨時可以運行,只等待調度器進行調度。
圖 16-1(2): 就緒態→運行態(Running):發生任務切換時,就緒列表中最高優先級的任務被執行,從而進入運行態。
圖 16-1(3): 運行態→就緒態:有更高優先級任務創建或者恢復后,會發生任務調度,此刻就緒列表中最高優先級任務變為運行態,那么原先運行的任務由運行態變為就緒態,依然在就緒列表中,等待最高優先級的任務運行完畢繼續運行原來的任務(此處可以看做是 CPU 使用權被更高優先級的任務搶占了)。
圖 16-1(4): 運行態→阻塞態(Blocked):正在運行的任務發生阻塞(延時、讀信號量等待)時,該任務會從就緒列表中刪除,任務狀態由運行態變成阻塞態,然后發生任務切換,運行就緒列表中當前最高優先級任務。
圖 16-1(5): 阻塞態→就緒態:阻塞的任務被恢復后(任務恢復、延時時間超時、讀信號量超時或讀到信號量等),此時被恢復的任務會被加入就緒列表,從而由阻塞態變成就緒態;如果此時被恢復任務的優先級高于正在運行任務的優先級,則會發生任務切換,將該任務將再次轉換任務狀態,由就緒態變成運行態。
圖 16-1(6) (7) (8): 就緒態、阻塞態、運行態→掛起態(Suspended):任務可以通過調用 vTaskSuspend() API 函數都可以將處于任何狀態的任務掛起,被掛起的任務得不到CPU 的使用權,也不會參與調度,除非它從掛起態中解除。
圖 16-1(9): 掛起態→就緒態: 把一個掛起狀態的任務恢復的唯一途徑就是調用 vTaskResume() 或 xTaskResumeFromISR() API 函數,如果此時被恢復任務的優先級高于正在運行任務的優先級,則會發生任務切換,將該任務將再次轉換任務狀態,由就緒態變成運行態。
freeRtos啟動
void vTaskStartScheduler(void);啟動freeRtos的任務調度器,空閑任務和定時器任務是在調用這個函數后才自動創建的。
動態創建任務
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, /* 任務入口函數 */const char * const pcName, /* 任務名 */const configSTACK_DEPTH_TYPE usStackDepth,/* 任務棧大小 單位為字 */void * const pvParameters, /* 任務入口參數 不用的時候配置為0 */UBaseType_t uxPriority, /* 任務任務優先級 空閑任務優先級0 */TaskHandle_t * const pxCreatedTask ) /* 任務控制塊指針 */函數 xTaskCreate 用于實現 FreeRTOS 操作系統的任務創建,并且還可以自定義任務棧的大小。
- 第 1 個參數填創建任務的函數名。
- 第 2 個參數是任務名,這個參數主要是用于調試目的,調試的時候方便看是哪個任務。
- 第 3 個參數是任務棧大小,單位 word,也就是 4 字節。
- 第 4 個參數是創建的任務函數的形參。
- 第 5 個參數是任務優先級,越大優先級越高
- 第 6 個參數是任務句柄,用于區分不同的任務。
- 返回值:當任務創建成功,返回pdPASS,否則返回pdFALL.
刪除任務
void vTaskDelete( TaskHandle_t xTaskToDelete )使用這個函數要注意以下問題:
#define INCLUDE_vTaskDelete 1
掛起任務
void vTaskSuspend(TaskHandle xTaskToSuspend);函數 vTaskSuspend 用于實現 FreeRTOS 操作系統的任務掛起。
第 1 個參數填要掛起任務的句柄
使用這個函數要注意以下問題:
#define INCLUDE_vTaskSuspend 1
此任務被掛起后, FreeRTOS 會切換到任務就緒列表里面下一個要執行的高優先級任務。
恢復掛起任務
void vTaskResume(TaskHandle xTaskToResume); BaseType_t xTaskResumeFromISR(TaskHandle xTaskToResume);函數 vTaskResume 用于實現 FreeRTOS 操作系統的任務掛起
第 1 個參數填要恢復任務的句柄
使用這個函數要注意以下問題:
#define INCLUDE_vTaskSuspend 1
xTaskResumeFromISR(), 以后綴 FromISR 結尾。
修改任務優先級
void vTaskPrioritySet(TaskHandle xTask, UBaseType_t uxNewPriority);函數 vTaskPrioritySet 用于實現 FreeRTOS 任務優先級的修改。
第 1 個參數是任務句柄,用于區分不同的任務。
第 2 個參數是給任務配置的新優先級。
使用這個函數要注意以下問題:
#define INCLUDE_vTaskPrioritySet 1
#define configMAX_PRIORITIES 配置的數值。
獲取任務優先級
UBaseType_t uxTaskPriorityGet(TaskHandle xTask); UBaseType_t uxTaskPriorityGetFromISR(TaskHandle_t xTask);函數 vTaskPriorityGet 用于獲取 FreeRTOS 任務優先級。
第 1 個參數是任務句柄,用于區分不同的任務。
使用這個函數要注意以下問題:
#define INCLUDE_vTaskPriorityGet 1
uxTaskPriorityGetFromISR(), 以后綴 FromISR 結尾。
切換任務
taskYIELD()調用 taskYIELD() 宏可以立刻進行任務調度,切換到就緒的最高優先級任務
獲取當前系統時間
volatile TickType_t xTaskGetTickCount(void); volatile TickType_t xTaskGetTickCountFromISR(void);函數 xTaskGetTickCount 用于獲取系統當前運行的時鐘節拍數。
使用這個函數要注意以下問題:
xTaskGetTickCountFromISR, 這兩個函數切不可混用
任務延時
void vTaskDelay(TickType_t xTickToDelay);函數 vTaskDelay 用于任務的延遲。
參數 xTicksToDelay 用于設置延遲的時鐘節拍個數,范圍 1- 0xFFFFFFFF。 延遲時間的最大值在
portmacro.h 文件里面有定義:
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t )0xffffffffUL
即延遲時間的范圍是: 1- 0xFFFFFFFF
延時后會進行任務調度
任務絕對延時
void vTaskDelayUntil(TickType_t* pxPreviousWakeTime, TickType_t xTimeIncrement);函數 vTaskDelayUntil 用于周期性延遲。
? 第 1 個參數,存儲任務上次處于非阻塞狀態時刻的變量地址。
? 第 2 個參數,周期性延遲時間。
使用這個函數要注意以下問題:
#define INCLUDE_vTaskDelayUntil 1
下面是一個使用vTaskDelay()實現vTaskDelayUntil()的過程。
void vTaskA(void *pvParame) {TickType_t xDelay, xNextTime;/* 200ms執行一次該任務 */const TickType_t xFrequency = 200;/* 獲取 xFrequency 個時鐘節拍后的時間 */xNextTime = xTaskGetTickCount() + xFrequency;while(1){/* 如果用戶函數需要運行50ms */..../* 計算實際需要延時的時間 200 - 50 = 150 */xDelay = xNextTime - xTaskGetTickCount();xNextTime += xFrequency;if(xDelay <= xFrequency){vTaskDelay(xDelay);}} }void vTaskB(void *pvParame) {TickType_t xLastWakeTime;/* 200ms執行一次該任務 */const TickType_t xFrequency = 200;while(1){/* 如果用戶函數需要運行50ms */....vTaskDelayUntil(&xLastWakeTime, xFrequency);}}調度器掛起
void vTaskSuspendAll(void);函數 vTaskSuspendAll 用于實現 FreeRTOS 調度器掛起。
使用這個函數要注意以下問題:
起任務切換的 API, 比如 vTaskDelayUntil、 vTaskDelay、 xQueueSend 等(調用了也不會執行調度)。
調度器恢復
BaseType_t xTaskResumeAll(void);函數 xTaskResumeAll 用于實現 FreeRTOS 調度器恢復
由于調度器操作可以進行嵌套,如果執行了兩次調度器掛起,那么在第一次執行調度器恢復函數時,此函數返回 pdFALSE,調度器并沒有恢復,第二次執行調度器恢復函數才會返回pdTRUE,調度器才會恢復正常。
使用這個函數要注意以下問題:
起任務切換的 API, 比如 vTaskDelayUntil、 vTaskDelay、 xQueueSend 等(調用了也不會執行調度)
本文參考 freertos官方文檔 https://freertos.org/a00110.html
《野火-FreeRTOS 內核實現與應用開發實戰指南》
《安富萊 STM32-V6 開發板 FreeRTOS 教程》
總結
以上是生活随笔為你收集整理的freeRtos学习笔(2)任务管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: freeRtos学习笔(1)内核剪裁
- 下一篇: c语言对齐方式研究笔记