静态创建任务
源代码 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; }