【任务管理与调度机制--- 任务创建流程深入分析】
本文详细解析了FreeRTOS任务创建函数xTaskCreate()的实现机制。该函数通过pvTaskCode、pcName、usStackDepth等参数创建新任务,核心流程包括:1)堆栈深度计算(以StackType_t为单位);2)优先级设置(0到configMAX_PRIORITIES-1);3)通过prvInitialiseNewTask()初始化任务控制块;4)使用pxPortInit
概要
xTaskCreate() 是 FreeRTOS 中用于创建任务的核心函数。让我详细解析其源码实现
函数原型
BaseType_t xTaskCreate(
TaskFunction_t pvTaskCode, // 任务函数指针
const char * const pcName, // 任务名称字符串
const configSTACK_DEPTH_TYPE usStackDepth, // 堆栈深度(字数,不是字节)
void * const pvParameters, // 传递给任务函数的参数
UBaseType_t uxPriority, // 任务优先级
TaskHandle_t * const pvCreatedTask // 返回的任务句柄
);
关键步骤
- 堆栈深度计算:以 StackType_t 为单位,不是字节数
- 优先级范围:0(最低)到 configMAX_PRIORITIES-1(最高)
- 任务名称:用于调试,不影响功能
- 内存分配:使用 FreeRTOS 的内存管理函数
- 调度器状态:调度器运行前后创建任务的行为不同
关键子函数解析
- prvInitialiseNewTask() - 初始化新任务
static void prvInitialiseNewTask(
TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask,
TCB_t *pxNewTCB,
const MemoryRegion_t * const xRegions )
{
StackType_t *pxTopOfStack;
UBaseType_t x;
/* 配置任务名称 */
#if ( configMAX_TASK_NAME_LEN > 1 )
strncpy( pxNewTCB->pcTaskName, pcName, configMAX_TASK_NAME_LEN );
#endif
/* 初始化任务状态列表项 */
vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
/* 设置列表项的所有者为TCB */
listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
/* 设置事件列表项的值(优先级取反,确保高优先级排在前面) */
listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ),
( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority );
/* 设置任务优先级 */
pxNewTCB->uxPriority = uxPriority;
pxNewTCB->uxBasePriority = uxPriority;
/* 初始化堆栈 */
pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) &
( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
/* 存储堆栈限制地址用于堆栈溢出检测 */
pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ulStackDepth;
/* 模拟中断上下文,初始化堆栈帧 */
#if ( portUSING_MPU_WRAPPERS == 1 )
/* 带MPU保护的任务初始化 */
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack,
pxTaskCode,
pvParameters,
xRunPrivileged );
#else
/* 普通任务初始化 */
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack,
pxTaskCode,
pvParameters );
#endif
}
- pxPortInitialiseStack() - 架构相关的堆栈初始化
这个函数是移植层实现的,以 ARM Cortex-M 为例
/* Cortex-M 堆栈初始化示例 */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack,
TaskFunction_t pxCode,
void *pvParameters )
{
/* 模拟异常返回时的堆栈帧 */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2, R1 */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5, R4 */
return pxTopOfStack;
}
- prvAddNewTaskToReadyList() - 将任务添加到就绪列表
后面专门针对该函数进行详细介绍
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
{
/* 进入临界区 */
taskENTER_CRITICAL();
{
/* 任务计数器递增 */
uxCurrentNumberOfTasks++;
if( pxCurrentTCB == NULL )
{
/* 这是创建的第一个任务 */
pxCurrentTCB = pxNewTCB;
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
{
/* 初始化任务列表 */
prvInitialiseTaskLists();
}
}
else
{
/* 如果新任务优先级高于当前任务,则触发上下文切换 */
if( xSchedulerRunning == pdFALSE )
{
if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
{
pxCurrentTCB = pxNewTCB;
}
}
}
/* 将任务添加到就绪列表 */
uxTaskNumber++;
#if ( configUSE_TRACE_FACILITY == 1 )
pxNewTCB->uxTCBNumber = uxTaskNumber;
#endif
/* 将任务添加到就绪列表对应优先级的末尾 */
prvAddTaskToReadyList( pxNewTCB );
#if ( configUSE_TIMERS == 1 )
if( xSchedulerRunning != pdFALSE )
{
/* 如果调度器已运行,可能需要调整定时器任务优先级 */
}
#endif
}
taskEXIT_CRITICAL();
/* 如果调度器已运行,可能需要任务切换 */
if( xSchedulerRunning != pdFALSE )
{
if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
{
taskYIELD_IF_USING_PREEMPTION();
}
}
}
-
内存布局
创建任务后的内存结构:
TCB (任务控制块)
±----------------+
| 任务状态信息 |
| 优先级 |
| 堆栈指针 |
| 事件列表项 |
| 状态列表项 |
| … |
±----------------+任务堆栈
±----------------+
| 高地址 |
| 模拟堆栈帧 |
| R4-R11寄存器 |
| R0-R3, R12 |
| LR (R14) |
| PC (任务入口) |
| xPSR |
| … |
| 低地址 |
±----------------+
返回值说明
pdPASS (1): 任务创建成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY (-1): 内存分配失败
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐

所有评论(0)