以下轉載自安富萊電子: http://forum.armfly.com/forum.php
vTaskDelete() API 函數
任務可以使用 API 函數 vTaskDelete()刪除自己或其它任務。
任務被刪除后就不復存在,也不會再進入運行態。
空閑任務的責任是要將分配給已刪除任務的內存釋放掉。因此有一點很重要,那就
是使用 vTaskDelete() API 函數的任務千萬不能把空閑任務的執行時間餓死。
需要說明一點,只有內核為任務分配的內存空間才會在任務被刪除后自動回收。任
務自己占用的內存或資源需要由應用程序自己顯式地釋放。
在使用這個API函數之前,需要配置INCLUDE_vTaskDelete == 1。
剛開始,看歷程有點不解,給一個任務句柄初始化為NULL,為什么刪除任務(非自身任務)的時候,傳入的還是句柄,句柄不是初始化為NULL了嗎?思前想后覺得應該是xTaskCreate創建函數會更改任務句柄的值,果然,xTaskCreate函數接受的任務句柄是個二級指針,就算我們給任務句柄初始化為NULL,xTaskCreate函數執行之后,任務句柄會被更改為一個非NULL指針。所以就有了下面的代碼:
//初始化任務句柄
static TaskHandle_t xHandleTaskLED1 = NULL;
static TaskHandle_t xHandleTaskBeep = NULL;
//創建任務
static void AppTaskCreate(void) { xTaskCreate(vTaskLed1, /* 任務函數名 */ "Task Led1", /* 任務名,字符串形式,方便調試 */ 512, /* 棧大小,單位為字,即4個字節 */ (void *)&task_led3, /* 任務形參 */ 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)即可。
改變任務優先級
vTaskPrioritySet() API 函數
API 函數 vTaskPriofitySet()可以用於在調度器啟動后改變任何任務的優先級。
函數 vTaskPrioritySet 用於實現 FreeRTOS 任務優先級的修改。
第 1 個參數是任務句柄,用於區分不同的任務。
第 2 個參數是給任務配置的新優先級。
使用這個函數要注意以下問題:
1. 使用此函數需要在 FreeRTOSConfig.h 配置文件中配置如下宏定義為 1
#define INCLUDE_vTaskPrioritySet 1
2. 如果第一個參數里面填的是 NULL,即數值 0 的話,那么配置的就是當前正在執行的任務。
3. 如果被修改的任務的優先級,修改后高於正在執行的任務,將執行任務切換,切換到修改好的高優先級任務。
4. 第二個參數數值不可大於等於 FreeRTOSConfig.h 文件中的宏定義:
#define configMAX_PRIORITIES 配置的數值。
使用這個函數要注意以下問題:
1. 使用此函數需要在 FreeRTOSConfig.h 配置文件中配置如下宏定義為 1
#define INCLUDE_vTaskPriorityGet 1
2. 如果第一個參數里面填的是 NULL,即數值 0 的話,那么獲取的優先級就是當前正在執行的任務。
改變任務優先級
調度器總是在所有就緒態任務中選擇具有最高優先級的任務,並使其進入運行態。
本例即是通過調用 vTaskPrioritySet() API 函數來改變兩個任務的相對優先級,以達到
對調度器這一行為的演示。
在不同的優先級上創建兩個任務。這兩個任務都沒有調用任何會令其進入阻塞態的
API 函數,所以這兩個任務要么處於就緒態,要么處於運行態——這種情形下,調度器
選擇具有最高優先級的任務來執行。
所以,我們創建任務一LED亮,優先級1,任務二,蜂鳴器響,優先級2。這樣在不阻塞的情況下,只會執行任務2,蜂鳴器響,但是,我們在任務二中,修改任務一的優先級,使它高於任務二。步驟如下:
void vTaskLed1(void *pvParameters) { /* 任務都是一個無限,不能返回 */ int *piParameters; piParameters=(int *)pvParameters; while(1) { if(*piParameters==1) { LED1( ON ); /* 阻塞延時,單位ms */ vTaskDelay( 500 ); LED1( OFF ); vTaskDelay( 500 ); } else if(*piParameters==2) { LED2( ON ); /* 阻塞延時,單位ms */ vTaskDelay( 500 ); LED2( OFF ); vTaskDelay( 500 ); } else if(*piParameters==3) { LED3( ON ); } } } /********************************************************************************* * @ 函數名 : vTaskBeep * @ 功能說明: Beep 任務 * @ 參數 : pvParameters,當任務創建的時候傳進來,可以沒有 * @ 返回值 : 無 ********************************************************************************/ void vTaskBeep(void *pvParameters) { /* 任務都是一個無限循環,不能返回 */ while(1) { BEEP_ON; } }
上面代碼,任務2,beep優先級為2,任務1,led優先級為1,沒有阻塞操作,調度器只執行優先級高的任務2,但是,我們更改任務2代碼如下:
void vTaskBeep(void *pvParameters) { /* 任務都是一個無限循環,不能返回 */ while(1) { BEEP_ON; vTaskPrioritySet(xHandleTaskLED1,3); } }
把任務一優先級設成3,這樣任務2運行到vTaskPrioritySet ()函數后(就算vTaskPrioritySet 函數后面還有程序都不會再執行),調度器會重新選擇優先級更高的執行。
再試試我們用vTaskPrioritySet 的NULL參數修改自身優先級為1,這樣任務1,2優先級都是1,這樣都可以運行。
void vTaskBeep(void *pvParameters) { /* 任務都是一個無限循環,不能返回 */ while(1) { BEEP_ON; vTaskPrioritySet(NULL,1); } }