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