FreeRTOS任务创建和删除
任務(wù)創(chuàng)建和刪除的API函數(shù)
- xTaskCreate():使用動(dòng)態(tài)方法創(chuàng)建一個(gè)任務(wù)
- xTaskCreateStatic():使用靜態(tài)方法創(chuàng)建一個(gè)任務(wù)
- xTaskCreateRestricated():創(chuàng)建一個(gè)使用MPU進(jìn)行限制的任務(wù),相關(guān)內(nèi)存使用動(dòng)態(tài)內(nèi)存分配
- vTaskDelete():刪除一個(gè)任務(wù)
xTaskCreate
使用該函數(shù),configSUPPORT_DYNAMIC_ALLOCATION要設(shè)置為1
#if( 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 ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif- pxTaskCode:函數(shù)名,任務(wù)執(zhí)行的函數(shù),我們可以把一個(gè)任務(wù)當(dāng)做一個(gè)函數(shù),只不過這個(gè)函數(shù)可以循環(huán)執(zhí)行
- pcName:任務(wù)名字,一般用于追蹤和調(diào)試,任務(wù)名字不能超過configMAX_TASK_NAME_LEN,configMAX_TASK_NAME_LEN在FreeRTOSConfig.h文件中
- usStackDepth:任務(wù)堆棧大小,實(shí)際申請(qǐng)到的堆棧是usStackDepth的4倍,其中空閑任務(wù)堆棧大小為configMINIMAL_STACK_SIZE,configMINIMAL_STACK_SIZE在FreeRTOSConfig.h文件中定義
- pvParameters:傳遞給任務(wù)函數(shù)的參數(shù)
- uxPriority:任務(wù)優(yōu)先級(jí),范圍是0-configMAX_PRIORITIES-1
- pxCreatedTask:任務(wù)句柄,任務(wù)創(chuàng)建成功后會(huì)返回此任務(wù)的任務(wù)句柄。
返回值:
pdPASS if the task was successfully created and added to a ready list, otherwise an error code defined in the file projdefs.h
xTaskCreateStatic
使用該函數(shù),configSUPPORT_STATIC_ALLOCATION要等于1
#if( configSUPPORT_STATIC_ALLOCATION == 1 )TaskHandle_t 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 ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /* configSUPPORT_STATIC_ALLOCATION */參數(shù)的具體函數(shù)可以看xTaskCreate,
- ulStackDepth:需要由用戶給出,一般是一個(gè)數(shù)組,此參數(shù)就是這個(gè)數(shù)組的大小
- puxStackBuffer:Must point to a StackType_t array that has at least ulStackDepth indexes - the array will then be used as the task’s stack,removing the need for the stack to be allocated dynamically.
- pxTaskBuffer:任務(wù)控制塊,pxTaskBuffer Must point to a variable of type StaticTask_t, which will then be used to hold the task’s data structures, removing the need for the memory to be allocated dynamically.
返回值:
If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will be created and pdPASS is returned. If either pxStackBuffer or pxTaskBuffer are NULL then the task will not be created and errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.
xTaskCreateRestricted
使用該函數(shù),portUSING_MPU_WRAPPERS=1
#if( portUSING_MPU_WRAPPERS == 1 )BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION; #endif- pxTaskDefinition:是一個(gè)結(jié)構(gòu)體,描述任務(wù)函數(shù)、堆棧大小優(yōu)先級(jí)等,在task.h定義
- pxCreatedTask:任務(wù)句柄
vTaskDelete
void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;- xTaskToDelete:要?jiǎng)h除任務(wù)的任務(wù)句柄
被刪除的任務(wù)不再存在,對(duì)于那些有內(nèi)核自動(dòng)分配給任務(wù)的內(nèi)存,該函數(shù)會(huì)自動(dòng)釋放掉,用戶給任務(wù)分配的內(nèi)存需要用戶自行釋放掉,比如pvPortMalloc()分配了500字節(jié)的內(nèi)存,那么在任務(wù)被刪除之后,用戶需要調(diào)用vPortFree函數(shù)將這些內(nèi)存刪除,否則會(huì)導(dǎo)致內(nèi)存泄露
設(shè)計(jì)
一共有三個(gè)任務(wù):
- start_task:用來創(chuàng)建其他兩個(gè)任務(wù)
- task1_task:次任務(wù)運(yùn)行5次以后,調(diào)用vTaskDelete刪除任務(wù)task2_task,此任務(wù)也會(huì)控制LED0閃爍,并且周期性刷新LCD指定區(qū)域的背景顏色
- task2_task:此任務(wù)普通的應(yīng)用任務(wù),會(huì)控制LED1的閃爍,并且周期性的率先LCD指定區(qū)域的背景顏色
動(dòng)態(tài)創(chuàng)建
main函數(shù)代碼:
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "FreeRTOS.h" #include "task.h" #include "lcd.h" #include "sdram.h"//任務(wù)優(yōu)先級(jí) #define START_TASK_PRIO 1 //任務(wù)堆棧大小 #define START_STK_SIZE 128 //任務(wù)句柄 TaskHandle_t StartTask_Handler; //任務(wù)函數(shù) void start_task(void *pvParameters);//任務(wù)優(yōu)先級(jí) #define TASK1_TASK_PRIO 2 //任務(wù)堆棧大小 #define TASK1_STK_SIZE 128 //任務(wù)句柄 TaskHandle_t Task1Task_Handler; //任務(wù)函數(shù) void task1_task(void *pvParameters);//任務(wù)優(yōu)先級(jí) #define TASK2_TASK_PRIO 3 //任務(wù)堆棧大小 #define TASK2_STK_SIZE 128 //任務(wù)句柄 TaskHandle_t Task2Task_Handler; //任務(wù)函數(shù) void task2_task(void *pvParameters);//LCD刷屏?xí)r使用的顏色 int lcd_discolor[14] = {WHITE ,BLACK,BLUE,BRED,GRED,GBLUE,RED,MAGENTA,GREEN,CYAN,YELLOW,BROWN,BRRED,GRAY};int main(void) {HAL_Init(); //初始化HAL庫(kù) Stm32_Clock_Init(360,25,2,8); //設(shè)置時(shí)鐘,180Mhzdelay_init(180); //初始化延時(shí)函數(shù)LED_Init(); //LED初始化ACR_BYTE0_ADDRESSuart_init(115200);SDRAM_Init();LCD_Init(); POINT_COLOR = RED;LCD_ShowString(30,10,200,16,16,"Apolo STM32F4/F7");LCD_ShowString(30,30,200,16,16,"FreeeRTOS Examples");LCD_ShowString(30,50,200,16,16,"Task create and delete");LCD_ShowString(30,70,200,16,16,"2021/11/20");xTaskCreate(start_task, //任務(wù)函數(shù)"start_task", //任務(wù)名稱START_STK_SIZE, //任務(wù)堆棧大小NULL, //傳遞給任務(wù)函數(shù)的參數(shù)START_TASK_PRIO, //任務(wù)優(yōu)先級(jí)&StartTask_Handler); //任務(wù)句柄 vTaskStartScheduler(); //開啟任務(wù)調(diào)度}//開始任務(wù)任務(wù)函數(shù) void start_task(void *pvParameters) {taskENTER_CRITICAL(); //進(jìn)入臨界區(qū)//創(chuàng)建TASK1任務(wù)xTaskCreate(task1_task, "task1_task", TASK1_STK_SIZE, NULL, TASK1_TASK_PRIO, &Task1Task_Handler); //創(chuàng)建TASK2任務(wù)xTaskCreate(task2_task, "task2_task", TASK2_STK_SIZE,NULL,TASK2_TASK_PRIO,&Task2Task_Handler); vTaskDelete(StartTask_Handler); //刪除開始任務(wù)taskEXIT_CRITICAL(); //退出臨界區(qū) } //task1任務(wù)函數(shù) void task1_task(void *pvParameters) {u8 task1_num=0;POINT_COLOR = BLACK;LCD_DrawRectangle(5,110,115,314); //畫一個(gè)矩形 LCD_DrawLine(5,130,115,130); //畫線POINT_COLOR = BLUE;LCD_ShowString(6,111,110,16,16,"Task1 Run:000");while(1){task1_num++; //任務(wù)執(zhí)1行次數(shù)加1 注意task1_num1加到255的時(shí)候會(huì)清零!!LED0=!LED0;//printf("任務(wù)1已經(jīng)執(zhí)行:%d次\r\n",task1_num);if(task1_num==5) {if(Task2Task_Handler != NULL) //任務(wù)2是否存在? {vTaskDelete(Task2Task_Handler); //任務(wù)1執(zhí)行5次刪除任務(wù)2Task2Task_Handler=NULL; //任務(wù)句柄清零//printf("任務(wù)1刪除了任務(wù)2!\r\n");}}LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充區(qū)域LCD_ShowxNum(86,111,task1_num,3,16,0x80); //顯示任務(wù)執(zhí)行次數(shù)vTaskDelay(1000); //延時(shí)1s,也就是1000個(gè)時(shí)鐘節(jié)拍 } }//task2任務(wù)函數(shù) void task2_task(void *pvParameters) {u8 task2_num=0;POINT_COLOR = BLACK;LCD_DrawRectangle(125,110,234,314); //畫一個(gè)矩形 LCD_DrawLine(125,130,234,130); //畫線POINT_COLOR = BLUE;LCD_ShowString(126,111,110,16,16,"Task2 Run:000");while(1){task2_num++; //任務(wù)2執(zhí)行次數(shù)加1 注意task1_num2加到255的時(shí)候會(huì)清零!!LED1=!LED1;//printf("任務(wù)2已經(jīng)執(zhí)行:%d次\r\n",task2_num);LCD_ShowxNum(206,111,task2_num,3,16,0x80); //顯示任務(wù)執(zhí)行次數(shù)LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充區(qū)域vTaskDelay(1000); //延時(shí)1s,也就是1000個(gè)時(shí)鐘節(jié)拍 } }靜態(tài)創(chuàng)建
使用靜態(tài)創(chuàng)建任務(wù)需要在FreeRTOSConfig.h將宏configSUPPORT_STATIC_ALLOCATION設(shè)置為1,配置完成之后還需要實(shí)現(xiàn)兩個(gè)函數(shù),vApplicationGetIdleTaskMemory和vApplicationGetTimerTaskMemory,通過這兩個(gè)來給空閑任務(wù)和定時(shí)器服務(wù)任務(wù)的任務(wù)堆棧和任務(wù)控制塊分配內(nèi)存,這兩個(gè)函數(shù),我們?cè)趍ain.c里面定義:
//空閑任務(wù)任務(wù)堆棧 static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE]; //空閑任務(wù)控制塊 static StaticTask_t IdleTaskTCB;//定時(shí)器服務(wù)任務(wù)堆棧 static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH]; //定時(shí)器服務(wù)任務(wù)控制塊 static StaticTask_t TimerTaskTCB; //獲取空閑任務(wù)地任務(wù)堆棧和任務(wù)控制塊內(nèi)存,因?yàn)楸纠淌褂玫?/span> //靜態(tài)內(nèi)存,因此空閑任務(wù)的任務(wù)堆棧和任務(wù)控制塊的內(nèi)存就應(yīng)該 //有用戶來提供,FreeRTOS提供了接口函數(shù)vApplicationGetIdleTaskMemory() //實(shí)現(xiàn)此函數(shù)即可。 //ppxIdleTaskTCBBuffer:任務(wù)控制塊內(nèi)存 //ppxIdleTaskStackBuffer:任務(wù)堆棧內(nèi)存 //pulIdleTaskStackSize:任務(wù)堆棧大小 void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {*ppxIdleTaskTCBBuffer=&IdleTaskTCB;*ppxIdleTaskStackBuffer=IdleTaskStack;*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE; } //獲取定時(shí)器服務(wù)任務(wù)的任務(wù)堆棧和任務(wù)控制塊內(nèi)存 //ppxTimerTaskTCBBuffer:任務(wù)控制塊內(nèi)存 //ppxTimerTaskStackBuffer:任務(wù)堆棧內(nèi)存 //pulTimerTaskStackSize:任務(wù)堆棧大小 void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) {*ppxTimerTaskTCBBuffer=&TimerTaskTCB;*ppxTimerTaskStackBuffer=TimerTaskStack;*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH; }main函數(shù)里面內(nèi)容為:
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "FreeRTOS.h" #include "task.h" #include "lcd.h" #include "sdram.h"//空閑任務(wù)任務(wù)堆棧 static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE]; //空閑任務(wù)控制塊 static StaticTask_t IdleTaskTCB;//定時(shí)器服務(wù)任務(wù)堆棧 static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH]; //定時(shí)器服務(wù)任務(wù)控制塊 static StaticTask_t TimerTaskTCB;//任務(wù)優(yōu)先級(jí) #define START_TASK_PRIO 1 //任務(wù)堆棧大小 #define START_STK_SIZE 128 //任務(wù)堆棧 StackType_t StartTaskStack[START_STK_SIZE]; //任務(wù)控制塊 StaticTask_t StartTaskTCB; //任務(wù)句柄 TaskHandle_t StartTask_Handler; //任務(wù)函數(shù) void start_task(void *pvParameters);//任務(wù)優(yōu)先級(jí) #define TASK1_TASK_PRIO 2 //任務(wù)堆棧大小 #define TASK1_STK_SIZE 128 //任務(wù)堆棧 StackType_t Task1TaskStack[TASK1_STK_SIZE]; //任務(wù)控制塊 StaticTask_t Task1TaskTCB; //任務(wù)句柄 TaskHandle_t Task1Task_Handler; //任務(wù)函數(shù) void task1_task(void *pvParameters);//任務(wù)優(yōu)先級(jí) #define TASK2_TASK_PRIO 3 //任務(wù)堆棧大小 #define TASK2_STK_SIZE 128 //任務(wù)堆棧 StackType_t Task2TaskStack[TASK2_STK_SIZE]; //任務(wù)控制塊 StaticTask_t Task2TaskTCB; //任務(wù)句柄 TaskHandle_t Task2Task_Handler; //任務(wù)函數(shù) void task2_task(void *pvParameters);//獲取空閑任務(wù)地任務(wù)堆棧和任務(wù)控制塊內(nèi)存,因?yàn)楸纠淌褂玫?/span> //靜態(tài)內(nèi)存,因此空閑任務(wù)的任務(wù)堆棧和任務(wù)控制塊的內(nèi)存就應(yīng)該 //有用戶來提供,FreeRTOS提供了接口函數(shù)vApplicationGetIdleTaskMemory() //實(shí)現(xiàn)此函數(shù)即可。 //ppxIdleTaskTCBBuffer:任務(wù)控制塊內(nèi)存 //ppxIdleTaskStackBuffer:任務(wù)堆棧內(nèi)存 //pulIdleTaskStackSize:任務(wù)堆棧大小 void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {*ppxIdleTaskTCBBuffer=&IdleTaskTCB;*ppxIdleTaskStackBuffer=IdleTaskStack;*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE; } //獲取定時(shí)器服務(wù)任務(wù)的任務(wù)堆棧和任務(wù)控制塊內(nèi)存 //ppxTimerTaskTCBBuffer:任務(wù)控制塊內(nèi)存 //ppxTimerTaskStackBuffer:任務(wù)堆棧內(nèi)存 //pulTimerTaskStackSize:任務(wù)堆棧大小 void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) {*ppxTimerTaskTCBBuffer=&TimerTaskTCB;*ppxTimerTaskStackBuffer=TimerTaskStack;*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH; }//LCD刷屏?xí)r使用的顏色 int lcd_discolor[14] = {WHITE ,BLACK,BLUE,BRED,GRED,GBLUE,RED,MAGENTA,GREEN,CYAN,YELLOW,BROWN,BRRED,GRAY};int main(void) {HAL_Init(); //初始化HAL庫(kù) Stm32_Clock_Init(360,25,2,8); //設(shè)置時(shí)鐘,180Mhzdelay_init(180); //初始化延時(shí)函數(shù)LED_Init(); //LED初始化ACR_BYTE0_ADDRESSuart_init(115200);SDRAM_Init();LCD_Init(); POINT_COLOR = RED;LCD_ShowString(30,10,200,16,16,"Apolo STM32F4/F7");LCD_ShowString(30,30,200,16,16,"FreeeRTOS Examples");LCD_ShowString(30,50,200,16,16,"Task create and delete");LCD_ShowString(30,70,200,16,16,"2021/11/20");StartTask_Handler= xTaskCreateStatic(start_task,"start_task",START_STK_SIZE,NULL, START_TASK_PRIO,StartTaskStack,&Task1TaskTCB); vTaskStartScheduler(); //開啟任務(wù)調(diào)度}//開始任務(wù)任務(wù)函數(shù) void start_task(void *pvParameters) {taskENTER_CRITICAL(); //進(jìn)入臨界區(qū)//創(chuàng)建TASK1任務(wù)Task1Task_Handler=xTaskCreateStatic((TaskFunction_t )task1_task, (const char* )"task1_task", (uint32_t )TASK1_STK_SIZE, (void* )NULL, (UBaseType_t )TASK1_TASK_PRIO, (StackType_t* )Task1TaskStack, (StaticTask_t* )&Task1TaskTCB); //創(chuàng)建TASK2任務(wù)Task2Task_Handler=xTaskCreateStatic(task2_task, "task2_task", TASK2_STK_SIZE,NULL,TASK2_TASK_PRIO,Task2TaskStack,&Task2TaskTCB); vTaskDelete(StartTask_Handler); //刪除開始任務(wù)taskEXIT_CRITICAL(); //退出臨界區(qū) } //task1任務(wù)函數(shù) void task1_task(void *pvParameters) {u8 task1_num=0;POINT_COLOR = BLACK;LCD_DrawRectangle(5,110,115,314); //畫一個(gè)矩形 LCD_DrawLine(5,130,115,130); //畫線POINT_COLOR = BLUE;LCD_ShowString(6,111,110,16,16,"Task1 Run:000");while(1){task1_num++; //任務(wù)執(zhí)1行次數(shù)加1 注意task1_num1加到255的時(shí)候會(huì)清零!!LED0=!LED0;//printf("任務(wù)1已經(jīng)執(zhí)行:%d次\r\n",task1_num);if(task1_num==5) {if(Task2Task_Handler != NULL) //任務(wù)2是否存在? {vTaskDelete(Task2Task_Handler); //任務(wù)1執(zhí)行5次刪除任務(wù)2Task2Task_Handler=NULL; //任務(wù)句柄清零//printf("任務(wù)1刪除了任務(wù)2!\r\n");}}LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充區(qū)域LCD_ShowxNum(86,111,task1_num,3,16,0x80); //顯示任務(wù)執(zhí)行次數(shù)vTaskDelay(1000); //延時(shí)1s,也就是1000個(gè)時(shí)鐘節(jié)拍 } }//task2任務(wù)函數(shù) void task2_task(void *pvParameters) {u8 task2_num=0;POINT_COLOR = BLACK;LCD_DrawRectangle(125,110,234,314); //畫一個(gè)矩形 LCD_DrawLine(125,130,234,130); //畫線POINT_COLOR = BLUE;LCD_ShowString(126,111,110,16,16,"Task2 Run:000");while(1){task2_num++; //任務(wù)2執(zhí)行次數(shù)加1 注意task1_num2加到255的時(shí)候會(huì)清零!!LED1=!LED1;//printf("任務(wù)2已經(jīng)執(zhí)行:%d次\r\n",task2_num);LCD_ShowxNum(206,111,task2_num,3,16,0x80); //顯示任務(wù)執(zhí)行次數(shù)LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充區(qū)域vTaskDelay(1000); //延時(shí)1s,也就是1000個(gè)時(shí)鐘節(jié)拍 } }編譯即可
總結(jié)
以上是生活随笔為你收集整理的FreeRTOS任务创建和删除的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FreeRTOS任务基础知识
- 下一篇: 推荐几个家用看电影的投影仪,再回答点小问