一、基本介绍
对于freeRTOS中任务的创建和删除,分为静态创建和动态创建;静态创建时需要将FreeRTOSConfig.h中的configSUPPORT_STATIC_ALLOCATION置1,但是即使使用静态创建,configSUPPORT_DYNAMIC_ALLOCATION也需要为1,否则编译报错。
静态创建和动态创建的函数分别为:xTaskCreate(),xTaskCreateStatic();
删除的函数两者相同都为vTaskDelete();
同时因为静态创建的堆栈大小和任务控制块(TCB)大小是用户自定义的,所以还提供了一个获取的函数:xTaskGetStaticBuffers();
同时在学习中还是一个开启任务调度器的函数:vTaskStartScheduler();
为了在保护某段程序在运行时不被打断,可以在需要保护的代码段加上:taskENTER_CRITICAL(),taskEXIT_CRITICAL()。
二、函数解释
1.xTaskCreate()定义为
BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
const char * const pcName,
const configSTACK_DEPTH_TYPE uxStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask
);
pvTaskCode--指向任务入口函数的指针(即 实现任务的函数名称);
pcName--任务的描述性名称。主要是为了方便 调试,但也可用于 获取任务句柄。任务名称的最大长度由 FreeRTOSConfig.h 中的 configMAX_TASK_NAME_LEN
定义,其定义的为字长度,而非字节长度。
uxStackDepth--分配用于任务堆栈的堆栈大小,单位为字。
pvParameters--指向传入任务函数的参数指针。
urPriority--任务优先级,数值越大优先级越高。
pxCreatedTask--创建的任务句柄,等同于TCB,可以通过它获取任务的信息。
创建成功,返回pdPASS,否则返回errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY.
2.xTaskCreatedStatic()定义为:
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 );
前五个参数与动态创建一样,区别在与后面两个参数。
puxStackBuffer--任务堆栈大小指针,必须大于等于ulStackDepth,且其定义是为一个数组。
pxTaskBuffer--TCB大小的指针,指向存储TCB的内存空间。
如果 puxStackBuffer
和 pxTaskBuffer
均不为 NULL,则创建任务,并返回任务的句柄。如果 puxStackBuffer
或 pxTaskBuffer
为 NULL,则不会创建任务,并返回 NULL。
注意:对于静态任务创建,还需要用户实现两个函数:vApplicationGetIdleMemory()、vApplicationGetTimerMemory()。在freeRTOS中只声明了这两个函数,但没有定义。
2.1 vApplicationGetIdleMemory()定义如下:
/*空闲任务配置*/
StaticTask_t Idle_Task_TCB;
StackType_t Idle_Task_Stack[configMINIMAL_STACK_SIZE];
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize )
{
*ppxIdleTaskTCBBuffer = &Idle_Task_TCB;
*ppxIdleTaskStackBuffer = Idle_Task_Stack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
使用时,需要用户自定义空闲任务TCB和空闲任务堆栈内存;
2.2 vApplicationGetTimerMemory()定义如下:
注意,如果你的FreeRTOSConfig.h中的configUSE_TIMERS宏定义为0,则可以省略,如果唯一,则需要进行如下的定义:
/*软件定时器任务配置*/
StaticTask_t TIMER_Task_TCB;
StackType_t TIMER_Task_Stack[configTIMER_TASK_STACK_DEPTH];
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
StackType_t ** ppxTimerTaskStackBuffer,
uint32_t * pulTimerTaskStackSize )
{
*ppxTimerTaskTCBBuffer = &TIMER_Task_TCB;
*ppxTimerTaskStackBuffer = TIMER_Task_Stack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
3.vTaskDelete()定义为:
void vTaskDelete( TaskHandle_t xTask );
该函数用于删除已经创建的任务,传入参数为任务句柄,如果传入的参数为NULL,则为删除滋生,等待自身任务结束,有空闲任务负责删除。
4.xTaskGetStaticBuffers()定义为:
BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask,
StackType_t ** ppuxStackBuffer,
StaticTask_t ** ppxTaskBuffer );
xTask--被检索的任务句柄。
ppuxStackBuffer--存放任务堆栈的二级指针。
ppxTaskBuffer--存放TCB缓存区的二级指针。
检索成功范围pdTRUE,否则返回pdFALSE。
5.其他
剩余提及的函数无形参,直接调用即可。
三、问题和总结
1.注意各个函数传入参数的类型,避免形参和实参参数类型不一致导致代码编译错误或程序无法正常运行。
2.使用某个freeRTOS的API函数往往都伴随着在FreeRTOSConfig.h开启对应的宏定义。
3.在静态任务创建时,ulStackDepth和puxStackBuffer的区别是什么?