静态创建任务

源代码 xTaskCreateStatic

静态的方式创建任务,需要用户先申请任务控制模块和任务栈需要的内存(一般使用静态内存),然后把内存地址传递给函数,函数负责其他初始化。

函数按顺序完成:

* 根据用户传递内存,初始化任务 TCB

* 初始化任务堆栈

* 将新建任务加入到就绪链表中

* 如果调度器运行,新任务优先级更高,触发系统切换

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 )
{
TCB_t *pxNewTCB;
TaskHandle_t xReturn;
configASSERT( puxStackBuffer != NULL );
configASSERT( pxTaskBuffer != NULL );

if ((pxTaskBuffer != NULL) && (puxStackBuffer != NULL))
{
// 设置用户传递进来的任务控制块和栈的内存地址到对应指针变量
pxNewTCB = (TCB_t *)pxTaskBuffer;
pxNewTCB->pxStack = (StackType_t *)puxStackBuffer;

#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
{
// 标识这个任务控制块和栈内存时静态的
// 删除任务的时候, 系统不会做内存回收处理
pxNewTCB->ucStaticallyAllocated =
tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
}
#endif
// 初始化任务控制块 下文介绍
prvInitialiseNewTask( pxTaskCode, pcName,
ulStackDepth, pvParameters, uxPriority,
&xReturn, pxNewTCB, NULL );

// 把新任务插入就绪链表 下文介绍
prvAddNewTaskToReadyList( pxNewTCB );
}
else
{
xReturn = NULL;
}
return xReturn;
}


动态创建任务

源代码 xTaskCreate

动态创建任务, 调用函数内部向系统申请创建新任务所需的内存,包括任务控制块和栈。 所以调用这个函数,在内存堆空间不足或者碎片话的情况下,可能创建新任务失败,需要判断函数执行后是否成功返回。 其源码解析如下所示。

BaseType_t xTaskCreate( 
TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
{
TCB_t *pxNewTCB;
BaseType_t xReturn;

// 如果是向下增长的栈, 先申请栈内存再申请任务控制块内存
// 可以避免栈溢出覆盖了自己任务控制块
// 对应向上增长的则相反

// 在旧版本 V8.0.0 中没有这么处理,统一先 TCB 后 Stack
// 项目上碰到平台栈向下增长, 栈溢出错时候覆盖了自己的 TCB
// 导致调试的时候无法获取出错任务信息(比如任务名)
#if( portSTACK_GROWTH > 0 )
{
// 申请任务控制块内存
pxNewTCB = (TCB_t *)pvPortMalloc(sizeof(TCB_t));
if( pxNewTCB != NULL )
{
// 申请栈内存, 返回地址设置任务中的栈指针
pxNewTCB->pxStack = (StackType_t *)pvPortMalloc(
(((size_t)usStackDepth) * sizeof(StackType_t)));

if( pxNewTCB->pxStack == NULL )
{
// 栈内存申请失败, 释放前面申请的任务控制块内存
vPortFree( pxNewTCB );
pxNewTCB = NULL;
}
}
}
#else /*栈向下增长*/
{
StackType_t *pxStack;
pxStack = (StackType_t *)pvPortMalloc(
(((size_t)usStackDepth) * sizeof(StackType_t)));

if( pxStack != NULL )
{
pxNewTCB = (TCB_t *)pvPortMalloc(sizeof(TCB_t));
if( pxNewTCB != NULL )
{
pxNewTCB->pxStack = pxStack;
}
else
{
vPortFree( pxStack );
}
}
else
{
pxNewTCB = NULL;
}
}
#endif


if( pxNewTCB != NULL )
{
// 成功申请所需内存 执行任务初始化操作

#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
{
// 标志任务控制块和栈是动态申请
// 删除任务系统会自动回收内存
pxNewTCB->ucStaticallyAllocated =
tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */

// 初始任务控制块
prvInitialiseNewTask(pxTaskCode, pcName,
(uint32_t)usStackDepth, pvParameters,
uxPriority, pxCreatedTask, pxNewTCB, NULL );

// 将新任务插入到就绪链表
prvAddNewTaskToReadyList( pxNewTCB );
xReturn = pdPASS;
}
else
{
// 创建任务失败,返回错误码
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
return xReturn;
}