tags: [source-summary] type: source source: "尚硅谷嵌入式技术之FreeRTOS实时操作系统 V1.0.3 — 第4章 任务创建和删除" author: "尚硅谷研究院" date: 2026-07-17
用生活理解:公司招人(创建任务)需要分配工位(栈)和建立档案(TCB);人员可以按编制内(静态)或外聘(动态)两种方式入职;裁员(删除任务)时需清理工位和档案。
FreeRTOS 中,一个任务(Task)包含三要素:
FreeRTOS 创建任务时:
动态创建(xTaskCreate)由内核自动分配栈和 TCB 内存:
静态创建(xTaskCreateStatic)由用户预先分配栈和 TCB 内存:
删除任务时使用 vTaskDelete(),任务被删除后不会再次运行,任务占用的资源会被释放。
| Function | Params | Description |
|---|---|---|
xTaskCreate |
pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask |
动态创建一个新任务 |
pvTaskCode |
任务函数指针 | |
pcName |
任务名称(用于调试) | |
usStackDepth |
栈深度(单位 word,STM32 中 1 word = 4 字节) | |
pvParameters |
传递给任务函数的参数 | |
uxPriority |
任务优先级(0~configMAX_PRIORITIES-1) | |
pxCreatedTask |
返回任务句柄 | |
| 返回 | pdPASS |
创建成功 |
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY |
创建失败(内存不足) |
| Function | Params | Description |
|---|---|---|
xTaskCreateStatic |
pvTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer |
静态创建一个新任务 |
puxStackBuffer |
用户预先分配的栈空间 | |
pxTaskBuffer |
用户预先分配的 TCB 空间 | |
| 返回 | 非 NULL | 任务句柄 |
| NULL | 创建失败(用户未提供内存) |
| Function | Params | Description |
|---|---|---|
vTaskDelete |
xTask |
删除指定任务 |
xTask |
待删除任务句柄;传 NULL 表示删除自身 | |
| 注意 | 传 NULL 时会在函数末尾触发一次任务切换 |
当 configSUPPORT_STATIC_ALLOCATION = 1 时,必须提供以下两个钩子函数:
| Function | Description |
|---|---|
vApplicationGetIdleTaskMemory |
提供空闲任务的 TCB 和栈缓冲区 |
vApplicationGetTimerTaskMemory |
提供定时器任务的 TCB 和栈缓冲区 |
File: 01_任务创建与删除_CubeMX/Core/Src/freertos_demo.c
#include "freertos_demo.h"
#include "FreeRTOS.h"
#include "task.h"
#include "LED.h"
#include "Key.h"
/* 起始任务配置 */
#define START_TASK_STACK 128
#define START_TASK_PRIORITY 1
TaskHandle_t start_task_handle;
void start_task(void *pvParameters);
/* 任务1配置 */
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handle;
void task1(void *pvParameters);
/* 任务2配置 */
#define TASK2_STACK 128
#define TASK2_PRIORITY 3
TaskHandle_t task2_handle;
void task2(void *pvParameters);
/* 任务3配置 */
#define TASK3_STACK 128
#define TASK3_PRIORITY 4
TaskHandle_t task3_handle;
void task3(void *pvParameters);
/**
* @description: 启动FreeRTOS
*/
void freertos_start(void)
{
/* 1. 创建起始任务(所有任务在起始任务中统一创建) */
xTaskCreate((TaskFunction_t)start_task, // 任务函数指针
(char *)"start_task", // 任务名称(用于调试标识)
(configSTACK_DEPTH_TYPE)START_TASK_STACK, // 栈空间大小 128 word × 4 = 512 字节
(void *)NULL, // 传递给任务的参数
(UBaseType_t)START_TASK_PRIORITY, // 任务优先级
(TaskHandle_t *)&start_task_handle); // 返回任务句柄
/* 2. 启动调度器:将CPU控制权交给FreeRTOS */
vTaskStartScheduler();
}
/**
* @description: 起始任务函数,负责创建其他任务后自我删除
*/
void start_task(void *pvParameters)
{
/* 进入临界区:防止创建任务过程中被中断干扰 */
taskENTER_CRITICAL();
/* 创建3个实际工作任务 */
xTaskCreate((TaskFunction_t)task1,
(char *)"task1",
(configSTACK_DEPTH_TYPE)TASK1_STACK,
(void *)NULL,
(UBaseType_t)TASK1_PRIORITY,
(TaskHandle_t *)&task1_handle);
xTaskCreate((TaskFunction_t)task2,
(char *)"task2",
(configSTACK_DEPTH_TYPE)TASK2_STACK,
(void *)NULL,
(UBaseType_t)TASK2_PRIORITY,
(TaskHandle_t *)&task2_handle);
xTaskCreate((TaskFunction_t)task3,
(char *)"task3",
(configSTACK_DEPTH_TYPE)TASK3_STACK,
(void *)NULL,
(UBaseType_t)TASK3_PRIORITY,
(TaskHandle_t *)&task3_handle);
/* 删除起始任务自身:传NULL代表删除当前运行的任务 */
vTaskDelete(NULL);
/* 退出临界区 */
taskEXIT_CRITICAL();
}
/**
* @description: 任务1——翻转LED1,周期500ms
*/
void task1(void *pvParameters)
{
while (1)
{
printf("task1正在运行...\r\n");
LED_Toggle(LED1_Pin); // 翻转LED1
vTaskDelay(500); // 阻塞延时500ms,让出CPU
}
}
/**
* @description: 任务2——翻转LED2,周期500ms
*/
void task2(void *pvParameters)
{
while (1)
{
printf("task2正在运行...\r\n");
LED_Toggle(LED2_Pin); // 翻转LED2
vTaskDelay(500); // 阻塞延时500ms,让出CPU
}
}
/**
* @description: 任务3——检测按键,按下KEY1则删除task1
*/
void task3(void *pvParameters)
{
uint8_t key = 0;
while (1)
{
printf("task3正在运行...\r\n");
key = Key_Detect();
if (key == KEY1_PRESS)
{
/* 确保task1句柄有效 */
if (task1_handle != NULL)
{
/* KEY1按下则删除task1 */
printf("正在删除Task1....\r\n");
vTaskDelete(task1_handle); // 删除指定任务
task1_handle = NULL; // 句柄置空防止误用
}
}
vTaskDelay(500);
// HAL_Delay(500); // 注意:HAL_Delay是忙等待,会占用CPU
}
}
File: 02_任务创建与删除_静态创建/Core/Src/freertos_demo.c
#include "freertos_demo.h"
#include "FreeRTOS.h"
#include "task.h"
#include "LED.h"
#include "Key.h"
/* 任务栈和TCB变量全部由用户预先定义 */
#define START_TASK_STACK 128
StackType_t start_task_stack[START_TASK_STACK]; // 用户分配的栈空间
StaticTask_t start_task_tcb; // 用户分配的TCB空间
TaskHandle_t start_task_handle;
#define TASK1_STACK 128
StackType_t task1_stack[TASK1_STACK];
StaticTask_t task1_tcb;
TaskHandle_t task1_handle;
#define TASK2_STACK 128
StackType_t task2_stack[TASK2_STACK];
StaticTask_t task2_tcb;
TaskHandle_t task2_handle;
#define TASK3_STACK 128
StackType_t task3_stack[TASK3_STACK];
StaticTask_t task3_tcb;
TaskHandle_t task3_handle;
/* ============= 系统任务内存分配(静态分配时必须提供)=============== */
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];
StaticTask_t idle_task_tcb;
StackType_t timer_task_stack[configTIMER_TASK_STACK_DEPTH];
StaticTask_t timer_task_tcb;
/* 提供空闲任务的栈和TCB */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer = &idle_task_tcb;
*ppxIdleTaskStackBuffer = idle_task_stack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/* 提供定时器任务的栈和TCB */
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize)
{
*ppxTimerTaskTCBBuffer = &timer_task_tcb;
*ppxTimerTaskStackBuffer = timer_task_stack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
void freertos_start(void)
{
/* 静态创建起始任务:需要用户提供栈和TCB缓冲区 */
start_task_handle = xTaskCreateStatic(
(TaskFunction_t)start_task,
(char *)"start_task",
(uint32_t)START_TASK_STACK,
(void *)NULL,
(UBaseType_t)START_TASK_PRIORITY,
(StackType_t *)start_task_stack, // 用户预分配的栈
(StaticTask_t *)&start_task_tcb // 用户预分配的TCB
);
vTaskStartScheduler();
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
/* 静态创建3个工作任务 */
task1_handle = xTaskCreateStatic(
(TaskFunction_t)task1, (char *)"task1",
(configSTACK_DEPTH_TYPE)TASK1_STACK, (void *)NULL,
(UBaseType_t)TASK1_PRIORITY,
(StackType_t *)task1_stack, (StaticTask_t *)&task1_tcb
);
task2_handle = xTaskCreateStatic(
(TaskFunction_t)task2, (char *)"task2",
(configSTACK_DEPTH_TYPE)TASK2_STACK, (void *)NULL,
(UBaseType_t)TASK2_PRIORITY,
(StackType_t *)task2_stack, (StaticTask_t *)&task2_tcb
);
task3_handle = xTaskCreateStatic(
(TaskFunction_t)task3, (char *)"task3",
(configSTACK_DEPTH_TYPE)TASK3_STACK, (void *)NULL,
(UBaseType_t)TASK3_PRIORITY,
(StackType_t *)task3_stack, (StaticTask_t *)&task3_tcb
);
vTaskDelete(NULL);
taskEXIT_CRITICAL();
}
/* task1/task2/task3 与动态创建版本相同 */
P01 FreeRTOSConfig.h(默认配置,无需特殊设置):
// 默认配置已启用 vTaskDelete
#define INCLUDE_vTaskDelete 1
P02 FreeRTOSConfig.h(静态分配额外配置):
#define configSUPPORT_STATIC_ALLOCATION 1 // 启用静态分配
#define configUSE_TIMERS 1 // 启用软件定时器(产生定时器任务)
#define configTIMER_TASK_PRIORITY 4 // 定时器任务优先级
#define configTIMER_QUEUE_LENGTH 5 // 定时器命令队列长度
#define configTIMER_TASK_STACK_DEPTH 256 // 定时器任务栈大小
| Function | Parameters | Return | Description |
|---|---|---|---|
xTaskCreate |
pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask | BaseType_t | 动态创建任务 |
xTaskCreateStatic |
pvTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer | TaskHandle_t | 静态创建任务 |
vTaskDelete |
xTaskToDelete | void | 删除任务(NULL=自身) |
vTaskStartScheduler |
无 | void | 启动调度器 |
vApplicationGetIdleTaskMemory |
ppxIdleTaskTCBBuffer, ppxIdleTaskStackBuffer, pulIdleTaskStackSize | void | 提供空闲任务内存(静态分配时) |
vApplicationGetTimerTaskMemory |
ppxTimerTaskTCBBuffer, ppxTimerTaskStackBuffer, pulTimerTaskStackSize | void | 提供定时器任务内存(静态分配时) |
configCHECK_FOR_STACK_OVERFLOW 为 1 或 2,并实现 vApplicationStackOverflowHook()。NULL。xTaskCreate 返回 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY。增大 configTOTAL_HEAP_SIZE 或改用静态创建。configSUPPORT_STATIC_ALLOCATION = 1 后,必须实现 vApplicationGetIdleTaskMemory,若启用定时器还必须实现 vApplicationGetTimerTaskMemory。taskYIELD()。taskENTER_CRITICAL() / taskEXIT_CRITICAL() 之间不应调用 vTaskDelay() 等可能导致阻塞的 API。