任務(wù)概述
任務(wù)是 FreeRTOS 中最基本的調(diào)度單元,它是一段可執(zhí)行的代碼,可以獨(dú)立運(yùn)行。FreeRTOS 中的任務(wù)是基于優(yōu)先級(jí)的搶占式調(diào)度,優(yōu)先級(jí)高的任務(wù)可以搶占優(yōu)先級(jí)低的任務(wù)的 CPU 資源。任務(wù)的創(chuàng)建、刪除、掛起、恢復(fù)、設(shè)置優(yōu)先級(jí)等操作都是通過調(diào)用 API 函數(shù)來(lái)實(shí)現(xiàn)的。
任務(wù)的創(chuàng)建
任務(wù)的創(chuàng)建是通過調(diào)用 xTaskCreate
函數(shù)來(lái)實(shí)現(xiàn)的,函數(shù)原型如下:
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask );
參數(shù)說(shuō)明:
- pxTaskCode:任務(wù)函數(shù)的入口地址。
- pcName:任務(wù)的名字,用于調(diào)試。
- usStackDepth:任務(wù)棧的大小,單位為字。
- pvParameters:傳遞給任務(wù)函數(shù)的參數(shù)。
- uxPriority:任務(wù)的優(yōu)先級(jí)。
- pxCreatedTask:任務(wù)創(chuàng)建成功后,返回任務(wù)句柄。
任務(wù)的刪除
任務(wù)的刪除是通過調(diào)用 vTaskDelete
函數(shù)來(lái)實(shí)現(xiàn)的,函數(shù)原型如下:
void vTaskDelete( TaskHandle_t xTask );
參數(shù)說(shuō)明:
- xTask:任務(wù)句柄。
任務(wù)的掛起和恢復(fù)
任務(wù)的掛起和恢復(fù)是通過調(diào)用 vTaskSuspend
和 xTaskResume
函數(shù)來(lái)實(shí)現(xiàn)的,函數(shù)原型如下:
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
BaseType_t xTaskResume( TaskHandle_t xTaskToResume );
參數(shù)說(shuō)明:
- xTaskToSuspend:掛起任務(wù)句柄。
- xTaskToResume:恢復(fù)任務(wù)句柄。
任務(wù)的優(yōu)先級(jí)
任務(wù)的優(yōu)先級(jí)是通過調(diào)用 vTaskPrioritySet
和 xTaskPriorityGet
函數(shù)來(lái)實(shí)現(xiàn)的,函數(shù)原型如下:
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
UBaseType_t xTaskPriorityGet( TaskHandle_t xTask, BaseType_t * pxPreviousPriority );
參數(shù)說(shuō)明:
- xTask:任務(wù)句柄。
- uxNewPriority:新的優(yōu)先級(jí)。
- pxPreviousPriority:保存原來(lái)的優(yōu)先級(jí)。
注意: 在 FreeRTOS 中,優(yōu)先級(jí)數(shù)值越大,優(yōu)先級(jí)越高,任務(wù)的優(yōu)先級(jí)不能超過 configMAX_PRIORITIES
宏定義的值。
任務(wù)的延時(shí)
任務(wù)的延時(shí)是通過調(diào)用 vTaskDelay
函數(shù)來(lái)實(shí)現(xiàn)的,函數(shù)原型如下:
void vTaskDelay( const TickType_t xTicksToDelay );
參數(shù)說(shuō)明:
- xTicksToDelay:延時(shí)時(shí)間,單位為時(shí)鐘節(jié)拍。
任務(wù)的阻塞
任務(wù)的阻塞是通過調(diào)用 vTaskDelayUntil
函數(shù)來(lái)實(shí)現(xiàn)的,函數(shù)原型如下:
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement );
參數(shù)說(shuō)明:
- pxPreviousWakeTime:保存上一次喚醒的時(shí)間。
- xTimeIncrement:下一次喚醒的時(shí)間增量。
任務(wù)的阻塞和喚醒
任務(wù)的阻塞和喚醒是通過調(diào)用 xTaskNotifyWait
和 xTaskNotify
函數(shù)來(lái)實(shí)現(xiàn)的,函數(shù)原型如下:
UBaseType_t xTaskNotifyWait( UBaseType_t uxBitsToClearOnEntry, UBaseType_t uxBitsToClearOnExit, uint32_t * pulNotificationValue, TickType_t xTicksToWait );
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, UBaseType_t uxTaskPriority, uint32_t ulValue, eNotifyAction eAction );
參數(shù)說(shuō)明:
- uxBitsToClearOnEntry:在任務(wù)進(jìn)入阻塞前,需要清除的任務(wù)通知位。
- uxBitsToClearOnExit:在任務(wù)退出阻塞前,需要清除的任務(wù)通知位。
- pulNotificationValue:保存任務(wù)通知值。
- xTicksToWait:阻塞時(shí)間。
- xTaskToNotify:需要通知的任務(wù)句柄。
- uxTaskPriority:需要通知的任務(wù)優(yōu)先級(jí)。
- ulValue:需要通知的任務(wù)通知值。
Playground
創(chuàng)建任務(wù)
創(chuàng)建 2 個(gè)優(yōu)先級(jí)都是1
的任務(wù).
#include < freertos/FreeRTOS.h >
#include < freertos/task.h >
#include < stdio.h >
// 任務(wù)1的函數(shù)
void task1(void *pvParameter) {
while (1) {
printf("這是任務(wù)1n");
vTaskDelay(1000 / portTICK_PERIOD_MS); // 1秒的延遲
}
}
// 任務(wù)2的函數(shù)
void task2(void *pvParameter) {
while (1) {
printf("這是任務(wù)2n");
vTaskDelay(2000 / portTICK_PERIOD_MS); // 2秒的延遲
}
}
void app_main() {
// 創(chuàng)建任務(wù)1
xTaskCreate(task1, "task1", 2048, NULL, 1, NULL);
// 創(chuàng)建任務(wù)2
xTaskCreate(task2, "task2", 2048, NULL, 1, NULL);
}
運(yùn)行一下,輸出:
這是任務(wù)1
這是任務(wù)1
這是任務(wù)2
這是任務(wù)1
這是任務(wù)1
這是任務(wù)2
這是任務(wù)1
這是任務(wù)1
這是任務(wù)2
這是任務(wù)1
這是任務(wù)1
這是任務(wù)2
...
我們稍加修改,將任務(wù) 1 中的任務(wù)延時(shí)去掉,看看任務(wù) 1 會(huì)不獨(dú)占 CPU 資源:
#include < freertos/FreeRTOS.h >
#include < freertos/task.h >
#include < stdio.h >
// 任務(wù)1的函數(shù)
void task1(void *pvParameter) {
while (1) {
}
}
// 任務(wù)2的函數(shù)
void task2(void *pvParameter) {
while (1) {
printf("這是任務(wù)2n");
vTaskDelay(2000 / portTICK_PERIOD_MS); // 2秒的延遲
}
}
void app_main() {
// 創(chuàng)建任務(wù)1
xTaskCreate(task1, "task1", 2048, NULL, 2, NULL);
// 創(chuàng)建任務(wù)2
xTaskCreate(task2, "task2", 2048, NULL, 1, NULL);
}
運(yùn)行一下,輸出:
這是任務(wù)2
這是任務(wù)2
E (5509) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (5509) task_wdt: - IDLE (CPU 0)
E (5509) task_wdt: Tasks currently running:
E (5509) task_wdt: CPU 0: task1
E (5509) task_wdt: Print CPU 0 (current core) registers
Core 0 register dump:
MEPC : 0x42007356 RA : 0x40385920 SP : 0x3fc90a50 GP : 0x3fc8b000
0x42007356: task1 at C:/Users/Peter/Desktop/udp_server/main/udp_server.c:7 (discriminator 1)
0x40385920: vPortTaskWrapper at C:/Users/Peter/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:205
TP : 0x3fc88554 T0 : 0x00000000 T1 : 0x00000000 T2 : 0x00000000
S0/FP : 0x00000000 S1 : 0x00000000 A0 : 0x00000000 A1 : 0x00000000
A2 : 0x00000000 A3 : 0x00000000 A4 : 0x00000000 A5 : 0x42007356
0x42007356: task1 at C:/Users/Peter/Desktop/udp_server/main/udp_server.c:7 (discriminator 1)
A6 : 0x00000000 A7 : 0x00000000 S2 : 0x00000000 S3 : 0x00000000
S4 : 0x00000000 S5 : 0x00000000 S6 : 0x00000000 S7 : 0x00000000
S8 : 0x00000000 S9 : 0x00000000 S10 : 0x00000000 S11 : 0x00000000
T3 : 0x00000000 T4 : 0x00000000 T5 : 0x00000000 T6 : 0x00000000
MSTATUS : 0x00000000 MTVEC : 0x00000000 MCAUSE : 0x00000000 MTVAL : 0x00000000
MHARTID : 0x00000000
這是任務(wù)2
這是任務(wù)2
...
可以看到,相同優(yōu)先級(jí)的任務(wù) 2 依然可以正常運(yùn)行,而任務(wù) 1 則觸發(fā)了看門狗。兩個(gè)任務(wù)按照時(shí)間片輪轉(zhuǎn)的方式共享 CPU 資源。可以想見,如果任務(wù) 1 的優(yōu)先級(jí)比任務(wù) 2 高,那么任務(wù) 1 就會(huì)獨(dú)占 CPU 資源,任務(wù) 2 就無(wú)法運(yùn)行了。
-
cpu
+關(guān)注
關(guān)注
68文章
10902瀏覽量
213014 -
API
+關(guān)注
關(guān)注
2文章
1510瀏覽量
62395 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4346瀏覽量
62971 -
代碼
+關(guān)注
關(guān)注
30文章
4825瀏覽量
69049 -
FreeRTOS
+關(guān)注
關(guān)注
12文章
484瀏覽量
62395
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論