任务创建API函数
任务创建和删除的API函数,而任务创建有动态创建任务和静态创建任务
(1)动态创建任务:任务的任务控制块以及任务的栈空间所需的内存,均由 FreeRTOS 从 FreeRTOS 管理的堆中分配 。
(2)静态创建任务:任务的任务控制块以及任务的栈空间所需的内存,需用户分配提供
动态任务创建函数:
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
)
参数:
pxTaskCode /* 指向任务函数的指针 */
pcName /* 任务名字,最大长度configMAX_TASK_NAME_LEN */
usStackDepth, /* 任务堆栈大小,注意字为单位 */
pvParameters, /* 传递给任务函数的参数 */
uxPriority /*任务优先级,范围:0 ~ configMAX_PRIORITIES - 1 */
pxCreatedTask /* 任务句柄,就是任务的任务控制块 */
返回值:
成功:pdPASS
失败:errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
实现动态创建任务流程:
(1)将宏configSUPPORT_DYNAMIC_ALLOCATION 配置为 1
(2)定义函数入口参数
(3)编写任务函数
使用示例:
/*任务创建任务相关定义*/
#define START_TASK_PRIO 1 /*任务优先级*/
#define START_STK_SZIE 128 /*任务堆栈大小*/
TaskHandle_t START_Handle_t; /*任务句柄*/
void Start_Task(void *p); /*任务函数*/
/*LED闪烁任务相关定义*/
#define LED_TASK_PRIO 3 /*任务优先级*/
#define LED_STK_SZIE 128 /*任务堆栈大小*/
TaskHandle_t LED_Handle_t; /*任务句柄*/
void LED_Task(void *p); /*任务函数*/
/**
* @brief FreeRTOS例程入口函数
* @param 无
* @retval 无
*/void FreeRTOS_Dome(void)
{
/*创建任务创建函数*/
xTaskCreate(Start_Task,"Start_Task",START_STK_SZIE,NULL,START_TASK_PRO,&START_Handle_t);
/*启动任务调度*/
vTaskStartScheduler();
}
/*任务创建函数*/
void Start_Task(void *p)
{
taskENTER_CRITICAL(); /*进入临界区*/
/*创建LED闪烁任务函数*/
xTaskCreate(LED_Task,"LED_Task",LED_STK_SZIE,NULL,LED_TASK_PRIO,&LED_Handle_t);
vTaskDelete(START_Handle_t); /*删除任务创建函数*/
taskEXIT_CRITICAL(); /*退出临界区*/
}
/*LED闪烁任务函数*/
void LED_Task(void *p)
{
while(1)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
vTaskDelay(500);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
vTaskDelay(500);
}
}
任务控制块结构体成员介绍
typedef struct tskTaskControlBlock
{
/* 任务栈栈顶,必须为TCB的第一个成员 */
volatile StackType_t * pxTopOfStack;
/* 任务状态列表项 */
ListItem_t xStateListItem;
/* 任务事件列表项 */
ListItem_t xEventListItem;
/* 任务优先级,数值越大,优先级越大 */
UBaseType_t uxPriority;
/* 任务栈起始地址 */
StackType_t * pxStack;
/* 任务名字 */
char pcTaskName[ configMAX_TASK_NAME_LEN ];
…
省略很多条件编译的成员
} tskTCB;
任务栈栈顶,在任务切换时的任务上下文保存、任务恢复息息相关
注意:每个任务都有属于自己的任务控制块,类似身份证
静态创建任务函数:
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 );
参数:
pxTaskCode, /* 指向任务函数的指针 */
pcName, /* 任务函数名 */
ulStackDepth, /* 任务堆栈大小注意字为单位 */
pvParameters, /* 传递的任务函数参数 */
uxPriority, /* 任务优先级 */
puxStackBuffer, /* 任务堆栈,一般为数组,由用户分配
pxTaskBuffer /* 任务控制块指针,由用户分配 */
返回值:
成功:任务句柄
失败:NULL
静态创建任务使用流程:
(1)需将宏configSUPPORT_STATIC_ALLOCATION 配置为 1
(2)定义空闲任务&定时器任务的任务堆栈及TCB
(3)实现两个接口函数:
1.vApplicationGetIdleTaskMemory();
2.vApplicationGetTimerTaskMemory();
(4)定义函数入口参数
(5)编写任务函数
此函数创建的任务会立刻进入就绪态,由任务调度器调度运行
使用示例:
/*任务优先级、任务句柄、任务堆栈大小、任务控制块指针*/
#define START_TASK_PRIO 1
#define START_SIZE 128
TaskHandle_t start_task_handle;
StackType_t start_task_stack[START_SIZE];
StaticTask_t start_task_tcb;
/*任务优先级、任务句柄、任务堆栈大小、任务控制块指针*/
#define TASK1_PRIO 2
#define TASK1_SIZE 50
TaskHandle_t task1_handle;
StackType_t task1_stack[TASK1_SIZE];
StaticTask_t task1_tcb;
/*空闲任务内存配置*/
StaticTask_t idle_task_tcb;
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];
/*软件定时器内存配置*/
StaticTask_t timer_task_tcb;
StackType_t timer_task_stack[configTIMER_TASK_STACK_DEPTH];
/* 空闲任务内存分配 */
void vApplicationGetIdleTaskMemory(
StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize )
{
* ppxIdleTaskTCBBuffer = &idle_task_tcb;
* ppxIdleTaskStackBuffer = idle_task_stack;
* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/* 软件定时器内存分配 */
void vApplicationGetTimerTaskMemory(
StaticTask_t ** ppxTimerTaskTCBBuffer,
StackType_t ** ppxTimerTaskStackBuffer,
uint32_t * pulTimerTaskStackSize )
{
* ppxTimerTaskTCBBuffer = &timer_task_tcb;
* ppxTimerTaskStackBuffer = timer_task_stack;
* pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
/**
* @brief FreeRTOS例程入口函数
* @param 无
* @retval 无
*/void freertos_dome(void)
{
start_task_handle = xTaskCreateStatic(
(TaskFunction_t ) start_task,
(char * ) "start_task",
(uint32_t ) START_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(StackType_t * ) start_task_stack,
(StaticTask_t * ) &start_task_tcb );
vTaskStartScheduler(); //开启任务调度
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
task1_handle = xTaskCreateStatic(
(TaskFunction_t ) task1,
(char * ) "task1",
(uint32_t ) TASK1_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_PRIO,
(StackType_t * ) task1_stack,
(StaticTask_t * ) &task1_tcb );
vTaskDelete(start_task_handle);
taskEXIT_CRITICAL(); //退出临界区
}
//实现LED0每500ms反转一次
void task1(void *pvParameters)
{
while(1)
{
printf("-----task1正在运行-----\n");
LED0 = 0;
vTaskDelay(200);
LED0 = 1;
vTaskDelay(200);
}
}
· 任务删除函数
void vTaskDelete(TaskHandle_t xTaskToDelete);
参数:xTaskToDelete /*待删除任务的任务句柄*/
返回值:无
用于删除已被创建的任务
被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除
注意
1、当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)
2、空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存, 则需要由用户在任务被删除前提前释放,否则将导致内存泄露。
·删除任务流程
(1)使用删除任务函数,需将宏INCLUDE_vTaskDelete 配置为 1
(2)入口参数输入需要删除的任务句柄(NULL代表删除本身)