目录
学习目标:
- 掌握FreeRTOS静态任务创建与删除
学习笔记:
任务创建流程(摘自正点原子官方资料):
要点一:
FreeRTOSConfig.h中将第39行configSUPPORT_STATIC_ALLOCATION宏定义改为1,以支持静态任务创建。编译后报两个错,原因是静态任务创建需要先创建空闲任务内存分配与定时器任务内存分配。
要点二:空闲任务内存分配
configMINIMAL_STACK_SIZE //定义空闲任务的栈空间大小, 单位: Word, 无默认需定义
vApplicationGetIdleTaskMemory( 任务控制块,
栈地址,
栈大小 )
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;
}
要点三:定时器任务内存分配(可选是否开启)
configUSE_TIMERS /* 1: 使能软件定时器, 默认: 0 */
configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2) /* 定义软件定时器任务的栈空间大小, 无默认configUSE_TIMERS为1时需定义 */
任务调度器函数中关于定时器任务代码如下:
#if ( configUSE_TIMERS == 1 )
{
if( xReturn == pdPASS )
{
xReturn = xTimerCreateTimerTask();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configUSE_TIMERS */
BaseType_t xTimerCreateTimerTask( void )
{
/*省略..........................................................................*/
vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );
xTimerTaskHandle = xTaskCreateStatic( prvTimerTask,
configTIMER_SERVICE_TASK_NAME,
ulTimerTaskStackSize,
NULL,
( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
pxTimerTaskStackBuffer,
pxTimerTaskTCBBuffer );
/*省略..........................................................................*/
}
要点四:静态任务创建与删除
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 | 任务的描述性名称。此参数主要用于方便调试,但也可用于获取任务句柄。 任务名称的最大长度由 FreeRTOSConfig.h 中的 |
ulStackDepth | puxStackBuffer 参数用于将 StackType_t 变量数组传递给 xTaskCreateStatic() 。必须将 ulStackDepth 设置为数组中的索引数。 |
pvParameters | 传递给已创建任务的参数值。 如果将 |
uxPriority | 所创建任务执行的优先级。 包含 MPU支持的系统可选择通过在 断言优先级低于 |
puxStackBuffer | 必须指向至少具有 ulStackDepth 索引的 StackType_t 数组(请参阅上面的 ulStackDepth 参数),该数组用作任务的堆栈,因此必须是永久性的(而不是在函数的堆栈上声明)。 |
pxTaskBuffer | 必须指向 StaticTask_t 类型的变量。该变量用于保存新任务的数据结构体 (TCB) ,因此必须是持久的(而不是在函数的堆栈中声明)。 |
返回:
如果 puxStackBuffer
和 pxTaskBuffer
均不为 NULL,则创建任务,并返回任务的句柄。如果 puxStackBuffer
或 pxTaskBuffer
为 NULL,则不会创建任务,并返回 NULL。
#define START_TASK_STACK_SIZE 128
#define START_TASK_PRIO 1
TaskHandle_t start_task_handler;
StackType_t start_task_stack[START_TASK_STACK_SIZE];
StaticTask_t start_task_tcb;
void start_task( void * pvParameters );
#define TASK1_STACK_SIZE 128
#define TASK1_PRIO 2
TaskHandle_t task1_handler;
StackType_t task1_stack[TASK1_STACK_SIZE];
StaticTask_t task1_tcb;
void task1( void * pvParameters );
#define TASK2_STACK_SIZE 128
#define TASK2_PRIO 3
TaskHandle_t task2_handler;
StackType_t task2_stack[TASK2_STACK_SIZE];
StaticTask_t task2_tcb;
void task2( void * pvParameters );
#define TASK3_STACK_SIZE 128
#define TASK3_PRIO 4
TaskHandle_t task3_handler;
StackType_t task3_stack[TASK3_STACK_SIZE];
StaticTask_t task3_tcb;
void task3( void * pvParameters );
void freertos_demo(void)
{
start_task_handler = xTaskCreateStatic( (TaskFunction_t) start_task,
(char * ) "start_task",
(uint32_t ) START_TASK_STACK_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_handler = xTaskCreateStatic( (TaskFunction_t) task1,
(char * ) "task1",
(uint32_t ) TASK1_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_PRIO,
(StackType_t * ) task1_stack,
(StaticTask_t *) &task1_tcb );
task2_handler = xTaskCreateStatic( (TaskFunction_t) task2,
(char * ) "task2",
(uint32_t ) TASK2_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_PRIO,
(StackType_t * ) task2_stack,
(StaticTask_t *) &task2_tcb );
task3_handler = xTaskCreateStatic( (TaskFunction_t) task3,
(char * ) "task3",
(uint32_t ) TASK3_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK3_PRIO,
(StackType_t * ) task3_stack,
(StaticTask_t *) &task3_tcb );
vTaskDelete(start_task_handler);
taskEXIT_CRITICAL(); /*退出临界区*/
}
问题:
动态任务删除正在执行的任务是在空闲任务中释放内存,但是静态任务需要手动删除,正点原子的讲解中并未提到如何释放start_task任务已占用的内存。
解决方案(未验证):在其他任务中释放start_task任务已占用的内存。