FreeRTOS任务创建和删除

FreeRTOS 任务创建与删除

1. 任务创建方式

FreeRTOS 提供动态和静态两种任务创建方式。两者都会初始化任务控制块(TCB)和任务栈,并将任务加入就绪列表;主要区别是内存由谁提供。

方式 API TCB 和栈内存来源 特点
动态创建 xTaskCreate() FreeRTOS 堆 使用方便;创建失败时要检查返回值,且堆空间不足会导致失败
静态创建 xTaskCreateStatic() 应用程序提供 内存位置和生命周期由应用程序控制;不依赖运行时堆分配

任务函数通常采用以下形式。任务结束时应自行删除,或持续运行;不能像普通函数一样 return:

复制代码
void vMyTask(void *pvParameters)
{
    for (;;) {
        /* 任务工作 */
    }
}

2. 动态创建任务

API:xTaskCreate()

中文含义:动态创建一个任务。 内核从 FreeRTOS 管理的堆中分配任务控制块和任务栈。

复制代码
BaseType_t xTaskCreate(
    TaskFunction_t pxTaskCode,
    const char * const pcName,
    configSTACK_DEPTH_TYPE usStackDepth,
    void *pvParameters,
    UBaseType_t uxPriority,
    TaskHandle_t *pxCreatedTask
);
参数 含义
pxTaskCode 任务函数入口
pcName 任务名,主要用于调试;长度受 configMAX_TASK_NAME_LEN 限制
usStackDepth 任务栈深度,单位是 StackType_t 的个数(通常为字,不是字节)
pvParameters 传给任务函数的参数;不需要参数时传 NULL
uxPriority 任务优先级,数值越大优先级越高
pxCreatedTask 输出任务句柄;不需要句柄时传 NULL

返回 pdPASS 表示成功;返回其他值表示创建失败。实际项目中应检查结果,并依据目标平台、任务调用深度和中断情况合理设置栈大小。

复制代码
TaskHandle_t xTaskHandle = NULL;
​
if (xTaskCreate(vMyTask,
                "myTask",
                256,
                NULL,
                tskIDLE_PRIORITY + 1,
                &xTaskHandle) != pdPASS) {
    /* 创建失败:检查堆空间及配置 */
}

启用动态创建需要在 FreeRTOSConfig.h 中配置:

复制代码
#define configSUPPORT_DYNAMIC_ALLOCATION 1

3. 静态创建任务

API:xTaskCreateStatic()

中文含义:使用应用程序提供的内存静态创建一个任务。 应用程序提供任务栈数组和静态任务控制块对象,二者在任务运行期间必须保持有效。

复制代码
TaskHandle_t xTaskCreateStatic(
    TaskFunction_t pxTaskCode,
    const char * const pcName,
    configSTACK_DEPTH_TYPE uxStackDepth,
    void *pvParameters,
    UBaseType_t uxPriority,
    StackType_t *puxStackBuffer,
    StaticTask_t *pxTaskBuffer
);

参数含义与 xTaskCreate() 基本相同,另外:

  • puxStackBuffer:应用程序提供的任务栈缓冲区。

  • pxTaskBuffer:应用程序提供的静态 TCB 缓冲区。

成功时返回任务句柄;失败时返回 NULL。示例:

复制代码
static StackType_t xMyTaskStack[256];
static StaticTask_t xMyTaskTCB;
​
TaskHandle_t xTaskHandle = xTaskCreateStatic(
    vMyTask,
    "myTask",
    256,
    NULL,
    tskIDLE_PRIORITY + 1,
    xMyTaskStack,
    &xMyTaskTCB
);
​
configASSERT(xTaskHandle != NULL);

启用静态创建需要配置:

复制代码
#define configSUPPORT_STATIC_ALLOCATION 1

部分移植或配置还要求应用程序提供空闲任务内存;启用软件定时器时,也可能要求提供定时器服务任务内存。接口形式如下,具体是否需要实现以所用 FreeRTOS 版本和 FreeRTOSConfig.h 为准:

复制代码
void vApplicationGetIdleTaskMemory(
    StaticTask_t **ppxIdleTaskTCBBuffer,
    StackType_t **ppxIdleTaskStackBuffer,
    configSTACK_DEPTH_TYPE *pulIdleTaskStackSize
);
​
void vApplicationGetTimerTaskMemory(
    StaticTask_t **ppxTimerTaskTCBBuffer,
    StackType_t **ppxTimerTaskStackBuffer,
    configSTACK_DEPTH_TYPE *pulTimerTaskStackSize
);

4. 删除任务

API:vTaskDelete()

中文含义:删除指定任务。 删除任务后,它不再参与调度。

复制代码
void vTaskDelete(TaskHandle_t xTaskToDelete);
  • 传入其他任务的句柄:删除该任务。

  • 传入 NULL:删除当前正在运行的任务。

  • 如果要删除动态创建的任务,任务控制块和栈的回收由空闲任务完成,因此空闲任务必须获得运行机会。

  • 如果删除自身,vTaskDelete(NULL) 之后不应再访问该任务的局部状态或继续执行任务逻辑。

  • 任务自行申请的其他资源不由 vTaskDelete() 自动释放,应在删除前自行清理。

  • 静态任务使用的 TCB 和栈由应用程序持有,不会由内核释放;确保缓冲区在任务删除前一直有效。

示例:

复制代码
vTaskDelete(xTaskHandle);  /* 删除句柄对应的任务 */

删除当前任务:

复制代码
vTaskDelete(NULL);

启用该 API 需要配置:

复制代码
#define INCLUDE_vTaskDelete 1

5. 任务创建和删除的工作过程

创建任务时,内核准备 TCB 和栈、初始化任务上下文,并把任务加入对应优先级的就绪列表。若调度器已运行且新任务优先级更高,内核可能立即触发任务切换。

删除任务时,内核根据任务句柄找到任务并将其从调度相关列表中移除。删除其他任务时可直接清理其内核对象;删除自身时,内存清理会延后到空闲任务执行。

6. 使用要点

  1. 动态创建时检查返回值,并关注 FreeRTOS 堆空间;静态创建时保证 TCB 和栈缓冲区的生命周期覆盖任务整个生命周期。

  2. xTaskCreate() 和 xTaskCreateStatic() 的栈深度参数按 StackType_t 个数计,不要直接当作字节数。

  3. 任务优先级数值越大,优先级越高;实际可用范围由 configMAX_PRIORITIES 决定。

  4. 删除动态任务后,空闲任务负责回收内核分配的内存;用户自行分配的资源需要单独释放。

  5. 通常优先使用动态创建以简化代码;若需要确定内存占用、控制内存位置或避免运行时堆分配,可选择静态创建。

7. 本章函数汇总

函数 中文含义 主要用法
xTaskCreate() 动态创建任务 xTaskCreate(task_fn, "name", stack_depth, param, priority, &handle);返回 pdPASS 表示成功
xTaskCreateStatic() 静态创建任务 xTaskCreateStatic(task_fn, "name", stack_depth, param, priority, stack_buffer, &tcb_buffer);返回任务句柄,失败返回 NULL
vTaskDelete() 删除任务 vTaskDelete(handle) 删除指定任务;vTaskDelete(NULL) 删除当前任务
vApplicationGetIdleTaskMemory() 提供空闲任务的静态内存 按接口参数返回空闲任务的 TCB 缓冲区、栈缓冲区和栈深度;仅在相应配置要求时实现
vApplicationGetTimerTaskMemory() 提供定时器服务任务的静态内存 按接口参数返回定时器任务的 TCB 缓冲区、栈缓冲区和栈深度;启用软件定时器且配置要求时实现
vMyTask()(示例任务函数) 任务执行入口 定义为 void task_fn(void *pvParameters),由创建函数传入;持续运行或在结束前调用 vTaskDelete(NULL)
相关推荐
La Pulga1 天前
【FreeRTOS源码学习笔记】空闲任务与阻塞延时
笔记·mcu·学习·嵌入式·freertos·实时操作系统
La Pulga2 天前
【FreeRTOS源码学习笔记】任务切换
单片机·mcu·学习·嵌入式·freertos·实时操作系统
La Pulga4 天前
【FreeRTOS源码学习笔记】链表的实现
数据结构·笔记·stm32·mcu·链表·嵌入式·freertos
La Pulga5 天前
【FreeRTOS源码学习笔记】任务创建
笔记·stm32·mcu·学习·嵌入式·freertos·实时操作系统
天吾cc9 天前
FreeRTOS 事件标志组
freertos
编码追梦人11 天前
基于 ESP32-S3 的便携式多参数环境监护仪设计:从硬件选型到 FreeRTOS 多任务落地
数据库·单片机·嵌入式硬件·mongodb·esp32·freertos·低功耗设计
天吾cc14 天前
FreeRTOS 队列集
freertos
硅基手札14 天前
操作系统设计思想系列 06 · FreeRTOS 深度 — 极简可移植范本
架构·操作系统·freertos·实时操作系统·嵌入式开发·设计思想
天吾cc19 天前
FreeRTOS 列表和列表项
freertos
qq_4017004120 天前
RTOS址与值 void*任务传参的坑 走void*万能转的天坑
freertos