当前位置: 首页 > news >正文

【FreeRTOS】任务(TASK)——任务的创建(源码解读)

在FreeRTOS中,任务可以被理解为一个独立运行的函数,它拥有自己的栈空间和程序计数器,可以与其他任务并发执行。每个任务都拥有唯一的优先级,优先级高的任务会优先获得CPU资源。任务(Task) 是系统调度的基本单元,其本质是一个独立的执行线程。
【FreeRTOS】任务(TASK)——定义、切换、管理

一、任务的创建方式

FreeRTOS 提供两种任务创建方式,分别对应不同的内存管理策略:

动态创建静态创建
内存分配由 FreeRTOS 堆动态分配 TCB 和栈空间用户预先提供 TCB 和栈内存
适用场景任务数量不确定、内存管理灵活资源受限、需严格内存控制
优点简单易用,无需手动管理内存无堆内存碎片,确定性更高
缺点容易产生内存碎片需手动分配内存,灵活性低
配置开关configSUPPORT_DYNAMIC_ALLOCATION=1configSUPPORT_STATIC_ALLOCATION=1

二、任务创建 API 函数解析

2.1 动态创建函数 xTaskCreate()

BaseType_t xTaskCreate(
    TaskFunction_t pvTaskCode,       		// 任务函数指针
    const char * const pcName,       		// 任务名称(字符串,用于调试)
    configSTACK_DEPTH_TYPE usStackDepth, 	// 栈大小(单位:字)
    void *pvParameters,              		// 任务参数(传递给任务函数的 void* 指针)
    UBaseType_t uxPriority,          		// 初始优先级
    TaskHandle_t *pxCreatedTask      		// 任务句柄输出(可设为 NULL)
);
返回值含义
pdPASS任务创建成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY内存不足,创建失败

2.2 静态创建函数 xTaskCreateStatic()

TaskHandle_t xTaskCreateStatic(
    TaskFunction_t pxTaskCode,       		// 任务函数指针
    const char * const pcName,       		// 任务名称
    uint32_t ulStackDepth,           		// 栈大小(单位:字)
    void *pvParameters,           		   	// 任务参数
    UBaseType_t uxPriority,     		   	// 初始优先级
    StackType_t *pxStackBuffer, 		   	// 用户提供的栈内存数组
    StaticTask_t *pxTaskBuffer    		   	// 用户提供的 TCB 内存
);

返回值: 任务句柄(若参数无效返回 NULL)。

三、任务创建函数 源码解析

下载源码可从FreeFtos官网直接下载,我下载的是FreeRTOSv202406.01-LTS版本
FreeRTOS™

2.1 动态创建函数 xTaskCreate()


函数原型

/*-----------------------------------------------------------*/

/* 函数定义:xTaskCreate
 * 返回值:BaseType_t(FreeRTOS标准返回类型,成功或错误码)
 * 参数说明见下方详细注释 */
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,        // 任务函数指针(函数入口)
                        const char * const pcName,        // 任务名称字符串(用于调试)
                        const configSTACK_DEPTH_TYPE uxStackDepth, // 任务堆栈深度(单位:字)
                        void * const pvParameters,        // 传递给任务的参数指针
                        UBaseType_t uxPriority,           // 任务优先级
                        TaskHandle_t * const pxCreatedTask ) // 输出任务句柄
{
    TCB_t * pxNewTCB;       // 定义任务控制块(TCB)指针
    BaseType_t xReturn;     // 函数返回值变量

    /* FreeRTOS调试跟踪宏,记录函数调用信息(需开启configUSE_TRACE_FACILITY) */
    traceENTER_xTaskCreate( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, pxCreatedTask );

    /* 调用私有函数prvCreateTask,完成TCB和堆栈内存分配、初始化工作 */
    pxNewTCB = prvCreateTask( pxTaskCode,          // 传递任务函数
                              pcName,              // 传递任务名称
                              uxStackDepth,        // 传递堆栈深度
                              pvParameters,        // 传递参数指针
                              uxPriority,          // 传递优先级
                              pxCreatedTask );     // 传递任务句柄指针

    /* 检查TCB是否分配成功 */
    if( pxNewTCB != NULL )  // 内存分配成功
    {
        /* 条件编译:多核CPU亲和性设置(仅当configNUMBER_OF_CORES > 1且启用亲和性时生效) */
        #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
        {
            /* 设置任务的CPU核心亲和性掩码(例如0x01表示仅允许在核心0运行) */
            pxNewTCB->uxCoreAffinityMask = configTASK_DEFAULT_CORE_AFFINITY;
        }
        #endif

        /* 将新任务添加到就绪列表(Ready List),准备被调度 */
        prvAddNewTaskToReadyList( pxNewTCB ); 

        xReturn = pdPASS;  // 返回成功标志
    }
    else  // 内存分配失败(TCB或堆栈分配失败)
    {
        xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;  // 返回内存错误码
    }

    /* FreeRTOS调试跟踪宏,记录函数返回信息 */
    traceRETURN_xTaskCreate( xReturn );

    return xReturn;  // 返回函数结果(pdPASS或错误码)
}

/*-----------------------------------------------------------*/

函数执行流程

  1. 调试跟踪入口
    调用 traceENTER_xTaskCreate,用于调试或跟踪任务创建过程(通常由宏定义实现,可能记录任务创建事件)。

  2. 创建任务控制块(TCB)和栈空间
    调用 prvCreateTask 函数完成核心工作:

    • 内存分配:为任务的 TCB(Task Control Block)栈空间 分配内存。
    • 初始化TCB:设置任务函数指针、栈指针、参数、优先级、状态等关键字段。
    • 返回TCB指针:成功时返回 pxNewTCB,失败返回 NULL
  3. 多核亲和性设置(条件编译)
    如果系统配置为多核(configNUMBER_OF_CORES > 1)且启用核心亲和性(configUSE_CORE_AFFINITY == 1):

    • 设置任务的默认核心亲和性掩码 pxNewTCB->uxCoreAffinityMask(例如 0x01 表示绑定到核心0)。
  4. 将任务加入就绪列表
    调用 prvAddNewTaskToReadyList(pxNewTCB)

    • 根据优先级将任务插入 就绪列表(Ready List)
    • 如果新任务优先级高于当前运行任务,可能触发上下文切换(需调度器已启动)。
  5. 返回值处理

    • 成功(pxNewTCB != NULL):返回 pdPASS
    • 失败(内存不足):返回 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
  6. 调试跟踪出口
    调用 traceRETURN_xTaskCreate,记录函数返回结果。


关键代码分析

1. prvCreateTask 内部逻辑
  • 内存分配:从堆中分配 TCB + 栈空间,若内存不足返回 NULL
  • 栈初始化:使用 pxPortInitialiseStack 初始化栈帧,模拟任务首次运行的上下文。
  • 任务链表:将新任务的TCB加入任务链表,维护任务状态。
2. 多核亲和性
  • 掩码机制:通过位掩码指定允许运行的核心(例如 0b011 允许核心0和1)。
  • 调度策略:调度器根据亲和性掩码选择合适核心运行任务(需配合调度算法)。
3. 就绪列表管理
  • 优先级排序:任务按优先级排列在就绪列表中,同优先级任务可能采用轮转调度。
  • 调度触发:若新任务优先级高于当前任务,可能触发 portYIELD() 请求上下文切换。

错误处理

  • 内存不足prvCreateTask 返回 NULL,函数返回 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
  • 栈溢出风险:需合理设置 uxStackDepth,可通过 uxTaskGetStackHighWaterMark 监控栈使用。

使用示例

void vTaskFunction(void *pvParameters) {
    // 任务逻辑
}

TaskHandle_t xHandle;
xTaskCreate(
    vTaskFunction,   // 任务函数
    "Task1",         // 任务名
    128,             // 栈深度(字)
    NULL,            // 参数
    1,               // 优先级
    &xHandle         // 任务句柄
);

总结

xTaskCreate 是 FreeRTOS 任务创建的核心函数,负责:

  1. 分配资源(TCB、栈)
  2. 初始化任务上下文
  3. 设置多核亲和性(可选)
  4. 将任务加入调度队列
  5. 返回创建状态

其设计体现了轻量级实时操作系统的特点,通过条件编译支持多核扩展,同时保持单核系统的高效性。

相关文章:

  • Qt中绘制不规则控件
  • ​Linux 中 nmap 命令详解:从基础到实战的全面指南
  • dfs记忆化搜索刷题 + 总结
  • 如何判断列表a中元素是否在列表b中
  • [leetcode]2685. 统计完全连通分量的数量
  • C++ 结构体、结构体指针与结构体指针数组详解
  • RabbitMQ 的三种集群模式
  • ETL数据集成:企业数字化转型的核心驱动力与实施策略
  • C++ Primer Plus 编程练习题 第五章 循环和关系表达式
  • 22-ArkTs 常见错误
  • DataPlatter:利用最少成本数据提升机器人操控的泛化能力
  • K8S学习之基础六十四:helm常用命令
  • 戴尔电脑安装Ubuntu双系统
  • 设计模式中的“万能转换器”——适配器模式
  • 【AI News | 20250331】每日AI进展
  • 鸿蒙编译构建-多目标产物
  • Scala循环守卫
  • vi编辑器常见命令
  • stm32第十一天外部中断按键控制灯
  • 自定义类型:结构体
  • 除了wordpress还有什么可以建站/搜索引擎优化seo
  • 福州市网站/网站seo文章该怎么写
  • 有关游戏的网站建设规划书/济南竞价托管
  • 渭南市住房和城乡建设局网站/沧州seo推广
  • 国外做调查问卷的网站/重庆关键词排名推广
  • 中国免费建站网/深圳网站建设维护