概要

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 // 返回的任务句柄
);

关键步骤

  1. 堆栈深度计算:以 StackType_t 为单位,不是字节数
  2. 优先级范围:0(最低)到 configMAX_PRIORITIES-1(最高)
  3. 任务名称:用于调试,不影响功能
  4. 内存分配:使用 FreeRTOS 的内存管理函数
  5. 调度器状态:调度器运行前后创建任务的行为不同

关键子函数解析

  1. 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
}
  1. 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;
}
  1. 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();
        }
    }
}
  1. 内存布局
    创建任务后的内存结构:
    TCB (任务控制块)
    ±----------------+
    | 任务状态信息 |
    | 优先级 |
    | 堆栈指针 |
    | 事件列表项 |
    | 状态列表项 |
    | … |
    ±----------------+

    任务堆栈
    ±----------------+
    | 高地址 |
    | 模拟堆栈帧 |
    | R4-R11寄存器 |
    | R0-R3, R12 |
    | LR (R14) |
    | PC (任务入口) |
    | xPSR |
    | … |
    | 低地址 |
    ±----------------+

返回值说明

pdPASS (1): 任务创建成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY (-1): 内存分配失败

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐