原生 FreeRTOS 添加任务

← 返回 添加任务 | ← FreeRTOS | ← 主页


适用于已经完成 FreeRTOS 源码移植,但没有 OSAL 和任务配置表的工程。

需要修改的文件

文件操作
任务模块 .h声明任务函数
任务模块 .c定义任务函数
main.c创建任务并启动调度器

1. 声明任务函数

在任务模块的 .h 文件中声明:

void my_task(void *argument);

2. 定义任务函数

在任务模块的 .c 文件中定义:

#include "FreeRTOS.h"
#include "task.h"
 
void my_task(void *argument)
{
    (void)argument;
 
    /* 任务初始化 */
 
    for (;;)
    {
        /* 任务内容 */
        vTaskDelay(pdMS_TO_TICKS(10U));
    }
}

任务循环中必须加入延时、队列等待或信号量等待,不能一直占用 CPU。

3. 创建任务

在 main.c 中包含任务模块头文件:

#include "FreeRTOS.h"
#include "task.h"
#include "my_task.h"

完成芯片和外设初始化后创建任务:

TaskHandle_t my_task_handle = NULL;
 
BaseType_t result = xTaskCreate(
    my_task,
    "MyTask",
    256U,
    NULL,
    tskIDLE_PRIORITY + 1U,
    &my_task_handle);
 
if (result != pdPASS)
{
    while (1)
    {
    }
}
参数内容
my_task任务函数
"MyTask"任务名称
256U任务栈深度
第一个 NULL传给任务函数的参数
tskIDLE_PRIORITY + 1U任务优先级
&my_task_handle保存任务句柄,不需要句柄时填 NULL

4. 启动调度器

所有初始任务创建完成后调用:

vTaskStartScheduler();
 
while (1)
{
}

vTaskStartScheduler() 只调用一次。调度器启动成功后,不会继续执行后面的普通代码。

5. 静态 vs 动态内存分配

OS 眼里只有一块连续内存,没有 .data / .bss / 栈 / 堆 之分——这些是链接脚本 + 编译器划出来的命名,OS 只认”哪段地址现在归谁用”。

静态分配动态分配
TCB 和栈的位置编译期就定好(占 .bss/.data 数组)运行时才从 Heap 申请
分配时机提前预留创建任务那一刻
创建函数xTaskCreateStatic()xTaskCreate()
前提configSUPPORT_STATIC_ALLOCATION = 1已加 Heap 实现,configSUPPORT_DYNAMIC_ALLOCATION = 1

静态分配:把 TCB 和栈声明成全局数组,位置在链接时就固定了:

static StackType_t  my_task_stack[256];
static StaticTask_t my_task_tcb;
 
TaskHandle_t my_task_handle = xTaskCreateStatic(
    my_task,
    "MyTask",
    256U,
    NULL,
    tskIDLE_PRIORITY + 1U,
    my_task_stack,   /* 栈内存,提前占好 */
    &my_task_tcb);   /* TCB 内存,提前占好 */

纯静态分配时还需提供空闲任务内存:实现 vApplicationGetIdleTaskMemory(),否则调度器起不来。

main.c 顺序

芯片初始化
→ 外设初始化
→ xTaskCreate() / xTaskCreateStatic() 创建任务
→ vTaskStartScheduler() 启动调度器

使用 xTaskCreate() 前,工程必须已经加入一个 Heap 实现,并在 FreeRTOSConfig.h 中允许动态内存分配;使用 xTaskCreateStatic() 则不需要 Heap。