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)
相关推荐
天吾cc9 小时前
FreeRTOS中断管理
freertos
天吾cc9 小时前
FreeRTOS任务挂起和恢复
freertos
中文英文-我选中文4 天前
8.2 学习探索
freertos
qq_401700419 天前
FreeRTOS 堆内存管理源码剖析:释放一块内存,空闲块数量反而变少了?
单片机·freertos
List<String> error_P11 天前
使用FreeRTOS搭建工程项目(一)
freertos
@嵌入式扫地僧19 天前
RTOS 面试实战:任务状态切换原理
freertos·rtos·时间片轮转·任务状态切换·抢占式调度
WWJA王文举1 个月前
Bootloader、App 和升级分区之间是什么关系?
stm32·freertos·嵌入式开发·在线升级
怀民民民1 个月前
嵌入式软件学习路线与项目实践记录:STM32、FreeRTOS、Linux 与 OpenMV
stm32·freertos·嵌入式软件·嵌入式linux·openmv
长江后浪博客1 个月前
ESP32-SOLO-1 在 ESP-IDF v5.5 下启动不断重启问题分析与解决
单片机·嵌入式硬件·嵌入式·esp32·freertos·esp-idf