vTaskPrioritySet() API 函數可以用於在調度器啟動后改變任何任務的優先級。
函數原型:
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );
uxTaskPriorityGet() API 函數用於查詢一個任務的優先級。
函數原型:unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );
調度器總是在所有就緒態任務中選擇具有最高優先級的任務,並使其進入運行態。
修改任務優先級的任務實現:
任務在查詢和修改自己的優先級時,並沒有使用一個有效的句柄——使用 NULL代替。只有在某個任務需要引用其它任務的時候才會用到任務句柄。好比任務 1 想要改變任務 2 的優先級,為了讓任務 1 能夠使用到任務 2 的句柄,在任務 2 被創建時其句柄就被獲得並保存下來。如下面注釋所示:
執行流程圖如下:
刪除任務
vTaskDelete() API 函數
任務可以使用 API 函數 vTaskDelete()刪除自己或其它任務。
任務被刪除后就不復存在,也不會再進入運行態。
空閑任務的責任是要將分配給已刪除任務的內存釋放掉。因此有一點很重要,那就是使用 vTaskDelete() API 函數的任務千萬不能把空閑任務的執行時間餓死。
需要說明一點,只有內核為任務分配的內存空間才會在任務被刪除后自動回收。任務自己占用的內存或資源需要由應用程序自己顯式地釋放。
函數原型: void vTaskDelete( xTaskHandle pxTaskToDelete );
[eg] : 任務 1 在 main()中創建在優先級 1 上。任務 1 運行時,以優先級 2 創建任務 2。現在任務 2 具有最高優先級,所以會立即得到執行。
任務 2 什么也沒有做,只是刪除自己。可以通過傳遞 NULL 值以 vTaskDelete()來刪除自己,但是為了純粹的演示,傳遞的是任務自己的句柄。
當任務 2 被自己刪除之后,任務 1 成為最高優先級的任務,所以繼續執行,調用vTaskDelay()阻塞一小段時間。
當任務 1 進入阻塞狀態后,空閑任務得到執行的機會。空閑任務會釋放內核為已刪除的任務 2 分配的內存。
任務 1 離開阻塞態后,再一次成為就緒態中具有最高優先級的任務,因此會搶占空閑任務。又再一次創建任務 2,如此往復。
函數執行流程:
static TaskHandle_t xHandleTaskLED1 = NULL;
static TaskHandle_t xHandleTaskBeep = NULL;
static void AppTaskCreate(void) { xTaskCreate(vTaskLed1, /* 任務函數名 */ "Task Led1", /* 任務名,字符串形式,方便調試 */ 512, /* 棧大小,單位為字,即4個字節 */ NULL, /* 任務形參 */ 1, /* 優先級,數值越大,優先級越高 */ &xHandleTaskLED1); /* 任務句柄 */ xTaskCreate(vTaskBeep,"Task Beep",512,NULL,2,&xHandleTaskBeep); }
//在任務beep中刪除led任務
void vTaskBeep(void *pvParameters) { /* 任務都是一個無限循環,不能返回 */ while(1) { BEEP_ON; /* 阻塞延時,單位ms */ vTaskDelay( 20 ); BEEP_OFF; vTaskDelay( 500 ); if(xHandleTaskLED1 != NULL) vTaskDelete(xHandleTaskLED1); } }
led的任務句柄,雖然初始化為NULL,但是任務創建函數執行之后,任務句柄(是個一級指針)會被二級指針改變,所以當它不是NULL的時候,證明led任務被創建,就可以在beep中將其刪除,如果要刪除beep任務自身,vTaskDelete(NULL)即可。