FreeRTOS任務API函式的使用
1. 任務建立和刪除API函式
1.1 xTaskCreate()
函式xTaskCreate()使用動態的方法建立一個任務,建立人物所需的RAM自動從FreeRTOS的堆中分配,巨集configSUPPORT_DYNAMIC_ALLOCATION必須為1
函式原型:
BaseType_t xTaskCreate(
TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
pxTaskCode: 任務函式
pcName: 任務名字,任務名字長度不能超過 configMAX_TASK_NAME_LEN
usStackDepth: 任務堆疊大小,實際申請堆疊是usStackDepth的4倍(因為這裡是uint16,而申請時的型別是uint32).空閒任務的堆疊大小為configMINIMAL_STACK_SIZE
pvParameters: 傳遞給任務函式的引數
uxPriotiry: 任務優先順序,範圍0~configMAX_PRIORITIES-1
pxCreatedTask: 任務控制代碼,任務建立成功以後返回此任務的任務控制代碼,任務控制代碼其實就是這個任務的任務堆疊。此引數就是用來儲存這個任務控制代碼,其他API函式可能會使用到這個任務控制代碼。
返回值:
pdPASS: 任務建立成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任務建立失敗,堆記憶體不足。
1.2 xTaskCreateStatic()
此函式與xTaskCreate()的功能相同,但是建立任務所需的RAM需要使用者來提供,巨集configSUPPORT_STATIC_ALLOCATION必須定義為1
函式原型:
xTaskCreateStatic(
TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer )
pxTaskCode: 任務函式
pcName:任務名字,任務名字長度不能超過 configMAX_TASK_NAME_LEN
usStackDepth: 任務堆疊大小,由於此函式是用靜態方法建立任務,所以任務堆疊由使用者給出,一般是一個數組,此引數就是這個陣列的大小
pvParameters: 傳遞給任務函式的引數
uxPriotiry: 任務優先順序,範圍0~configMAX_PRIORITIES-1
puxStackBuffer: 任務堆疊,一般為陣列,型別為StackType_t
pxTaskBuffer: 任務控制塊
返回值:
NULL: 任務建立失敗,pxTaskBuffer或puxStackBuffer為NULL時會導致錯誤發生
其他值:任務建立成功,返回任務的任務控制代碼
1.3 VTaskDelete()
刪除一個已經建立樂的任務,被刪除的任務不再存在(不會進入執行態)。任務被刪除後不能再使用此任務的控制代碼。
若是用動態方法建立,刪除任務後,此任務之前申請的堆疊和控制塊記憶體會在空閒任務中被釋放掉,因此當呼叫函式vTaskDelete()刪除任務以後必須給空閒任務一定的執行時間
若是靜態方法建立任務,刪除任務後用戶分配給任務的記憶體需要使用者自行釋放掉。
函式原型:
void vTaskDelete( TaskHandle_t xTaskToDelete )
xTaskDelete: 要刪除的任務的任務控制代碼
2. 任務建立和刪除
2.1 任務相關宣告:
//任務優先順序
#define START_TASK_PRIO 1
//任務堆疊大小
#define START_STK_SIZE 256
//任務控制代碼
TaskHandle_t StartTask_Handler;
//任務函式
void start_task(void *pvParameters);
//任務優先順序
#define LED0_TASK_PRIO 2
//任務堆疊大小
#define LED0_STK_SIZE 50
//任務控制代碼
TaskHandle_t LED0Task_Handler;
//任務函式
void led0_task(void *pvParameters);
//任務優先順序
#define LED1_TASK_PRIO 3
//任務堆疊大小
#define LED1_STK_SIZE 50
//任務控制代碼
TaskHandle_t LED1Task_Handler;
//任務函式
void led1_task(void *pvParameters);
聲明瞭每個任務的優先順序,堆疊大小和控制代碼,以及任務函式
2.2 main()
int main(void)
{
HAL_Init(); //初始化HAL庫
Stm32_Clock_Init(360,25,2,8); //設定時鐘,180Mhz
delay_init(180); //初始化延時函式
uart_init(115200); //初始化串列埠
LED_Init(); //初始化LED
xTaskCreate((TaskFunction_t )start_task, //任務函式
(const char* )"start_task", //任務名稱
(uint16_t )START_STK_SIZE, //任務堆疊大小
(void* )NULL, //傳遞給任務函式的引數
(UBaseType_t )START_TASK_PRIO, //任務優先順序
(TaskHandle_t* )&StartTask_Handler); //任務控制代碼
vTaskStartScheduler();//開啟任務排程
}
用來初始化相關硬體,並且呼叫函式xTaskCreate()建立start_task任務,再呼叫函式vTaskStartScheduler()開啟FreeRTOS的任務排程器,FreeRTOS開始執行
2.3 任務函式
//開始任務任務函式
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //進入臨界區
//建立LED0任務
xTaskCreate((TaskFunction_t )led0_task,
(const char* )"led0_task",
(uint16_t )LED0_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED0_TASK_PRIO,
(TaskHandle_t* )&LED0Task_Handler);
//建立LED1任務
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
vTaskDelete(StartTask_Handler); //刪除開始任務
taskEXIT_CRITICAL(); //退出臨界區
}
//LED0任務函式
void led0_task(void *pvParameters)
{
while(1)
{
LED0=~LED0;
vTaskDelay(500);
}
}
//LED1任務函式
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
start_task任務的任務函式中建立了另外兩個任務led0_task和led1_task。這個任務用來建立其他任務,完成之後呼叫vTaskDelete(StartTask_Handler)刪除掉開始任務
led0_task的任務函式每隔500ms讓LED0亮滅反轉,led1_task的任務函式間隔200ms和800ms來回反轉LED1
3. 任務掛起和恢復API函式
暫停某個任務的執行,過一段時間再重新執行。 任務掛起後任務中變數儲存的值不變,而任務刪除和重建後任務中變數儲存的值會丟失。
3.1 vTaskSuspend()
此函式用於將某個任務設定為掛起狀態。
函式原型:
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
xTaskToSuspend: 要掛起任務的任務控制代碼。如果引數為NULL表示掛起任務自己。
3.2 vTaskResume()
將一個任務從掛起態恢復到就緒態
函式原型:
void vTaskResume( TaskHandle_t xTaskToResume )
xTaskToResume: 要恢復任務的任務控制代碼
3.3 xTaskResumeFromISR()
此函式用於在中斷服務函式中恢復一個任務,是vTaskResume()的中斷版本
函式原型:
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
xTaskResumeFromISR:要恢復任務的任務控制代碼
返回值:
pdTRUE: 恢復執行的任務的任務優先順序等於或高於正在執行的任務(被中斷打斷的任務),在退出中斷服務函式以後必須進行一次上下文切換
pdFALSE: 恢復執行的任務的任務優先順序低於正在執行的任務(被中斷打斷的任務),在退出中斷服務函式以後不需要進行一次上下文切換
4. 任務掛起和恢復
4.1 任務相關宣告:
#define START_TASK_PRIO 1
//任務堆疊大小
#define START_STK_SIZE 256
//任務控制代碼
TaskHandle_t StartTask_Handler;
//任務函式
void start_task(void *pvParameters);
//任務優先順序
#define KEY_TASK_PRIO 2
//任務堆疊大小
#define KEY_STK_SIZE 128
//任務控制代碼
TaskHandle_t KEYTask_Handler;
//任務函式
void key_task(void *pvParameters);
//任務優先順序
#define LED0_TASK_PRIO 3
//任務堆疊大小
#define LED0_STK_SIZE 50
//任務控制代碼
TaskHandle_t LED0Task_Handler;
//任務函式
void led0_task(void *pvParameters);
//任務優先順序
#define LED1_TASK_PRIO 4
//任務堆疊大小
#define LED1_STK_SIZE 50
//任務控制代碼
TaskHandle_t LED1Task_Handler;
//任務函式
void led1_task(void *pvParameters);
4.2 main()
int main(void)
{
HAL_Init(); //初始化HAL庫
Stm32_Clock_Init(360,25,2,8); //設定時鐘,180Mhz
delay_init(180); //初始化延時函式
uart_init(115200); //初始化串列埠
LED_Init(); //初始化LED
KEY_Init(); //初始化KEY
xTaskCreate((TaskFunction_t )start_task, //任務函式
(const char* )"start_task", //任務名稱
(uint16_t )START_STK_SIZE, //任務堆疊大小
(void* )NULL, //傳遞給任務函式的引數
(UBaseType_t )START_TASK_PRIO, //任務優先順序
(TaskHandle_t* )&StartTask_Handler); //任務控制代碼
vTaskStartScheduler();//開啟任務排程
}
4.3 任務函式
//開始任務任務函式
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //進入臨界區
//建立KEY任務
xTaskCreate((TaskFunction_t )key_task,
(const char* )"key_task",
(uint16_t )KEY_STK_SIZE,
(void* )NULL,
(UBaseType_t )KEY_TASK_PRIO,
(TaskHandle_t* )&KEYTask_Handler);
//建立LED0任務
xTaskCreate((TaskFunction_t )led0_task,
(const char* )"led0_task",
(uint16_t )LED0_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED0_TASK_PRIO,
(TaskHandle_t* )&LED0Task_Handler);
//建立LED1任務
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
vTaskDelete(StartTask_Handler); //刪除開始任務
taskEXIT_CRITICAL(); //退出臨界區
}
//KEY任務函式
void key_task(void *pvParameters)
{
u8 key;
while(1)
{
key=KEY_Scan(0);
switch(key)
{
case WKUP_PRES:
vTaskSuspend(LED0Task_Handler);//掛起任務led0
printf("掛起LED0!\r\n");
break;
case KEY0_PRES:
vTaskResume(LED0Task_Handler); //恢復任務led0
printf("恢復LED0!\r\n");
break;
case KEY1_PRES:
vTaskSuspend(LED1Task_Handler);//掛起任務led1
printf("掛起LED1!\r\n");
break;
case KEY2_PRES:
vTaskResume(LED1Task_Handler);//恢復任務led1
printf("恢復LED1!\r\n");
break;
}
vTaskDelay(10); //延時10ms
}
}
//LED0任務函式
void led0_task(void *pvParameters)
{
while(1)
{
LED0=~LED0;
vTaskDelay(500);
}
}
//LED1任務函式
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
start_task任務建立了三個任務函式後刪除自己;
key_task任務函式進行按鍵掃描,當WKUP按下 掛起任務led0_task;當KEY0按下,恢復任務led0_task;當KEY1按下,掛起任務led1_task;當KEY2按下,恢復任務led1_task;並且串列埠輸出列印在電腦端顯示
led0_task和led1_task 分別控制LED0和LED1閃爍