tags: [source-summary] type: source source: "尚硅谷嵌入式技术之FreeRTOS实时操作系统 V1.0.3 — 第8章 任务相关API函数" author: "尚硅谷研究院" date: 2026-07-17
用生活理解:任务状态查询就像给公司做一次全面盘点——有多少员工(任务数)、每个员工的职级(优先级)、当前在干嘛(运行/就绪/阻塞)、堆栈压力(水位线)一目了然。运行时统计则像月底看考勤——每个员工干了多少活,一目了然。
FreeRTOS 提供一套丰富的 API 用于查询任务运行时信息,包括:
运行时统计(Run Time Stats) 需要额外的硬件定时器作为时钟源:
配置步骤:
1. 启用 configGENERATE_RUN_TIME_STATS = 1
2. 配置一个硬件定时器(如 TIM6/TIM7)产生高频计时
3. 实现 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() 初始化定时器
4. 实现 portGET_RUN_TIME_COUNTER_VALUE() 返回定时器计数值
统计结果以表格形式输出:
Task Abs Time % Time
--------------------------------
task1 12345 45.2
task2 9876 36.1
IDLE 5120 18.7
P06(状态查询 API):
uxTaskPriorityGet() / vTaskPrioritySet()uxTaskGetNumberOfTasks()uxTaskGetSystemState() / vTaskGetInfo()xTaskGetCurrentTaskHandle() / xTaskGetHandle()uxTaskGetStackHighWaterMark()eTaskGetState()vTaskList()P07(运行时统计):
vTaskGetRunTimeStats() 结果File: 06_任务状态查询/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);
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handle;
void task1(void *pvParameters);
/* task2栈空间更大,因为要调用多个API和打印 */
#define TASK2_STACK 256
#define TASK2_PRIORITY 3
TaskHandle_t task2_handle;
void task2(void *pvParameters);
void freertos_start(void)
{
xTaskCreate((TaskFunction_t)start_task,
(char *)"start_task",
(configSTACK_DEPTH_TYPE)START_TASK_STACK,
(void *)NULL,
(UBaseType_t)START_TASK_PRIORITY,
(TaskHandle_t *)&start_task_handle);
vTaskStartScheduler();
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
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);
vTaskDelete(NULL);
taskEXIT_CRITICAL();
}
void task1(void *pvParameters)
{
while (1)
{
printf("task1正在运行...\r\n");
LED_Toggle(LED1_Pin);
vTaskDelay(500);
}
}
char task_info[500];
/**
* @description: task2——演示所有任务状态查询API的使用
*/
void task2(void *pvParameters)
{
UBaseType_t task_priority = 0;
UBaseType_t task_num = 0;
TaskStatus_t task_status[10] = {0}; // 最多10个任务的状态信息
TaskStatus_t task_state;
TaskHandle_t task_handle = NULL;
UBaseType_t task_stack_remain_min = 0;
eTaskState e_task_state = 0;
/* 1. 获取task1的优先级 */
task_priority = uxTaskPriorityGet(task1_handle);
printf("task1当前优先级=%d\r\n", task_priority);
/* 2. 设置task1的优先级为4 */
vTaskPrioritySet(task1_handle, 4);
task_priority = uxTaskPriorityGet(task1_handle);
printf("task1修改后优先级=%d\r\n", task_priority);
/* 3. 获取系统中任务总数 */
task_num = uxTaskGetNumberOfTasks();
printf("当前系统中任务数量=%d\r\n", task_num);
/* 4. 获取所有任务状态信息 */
uxTaskGetSystemState(task_status, task_num, NULL);
printf("任务名\t\t任务号\t\t状态\t\t当前优先级\t\t基础优先级\r\n");
for (uint8_t i = 0; i < task_num; i++)
{
printf("%s\t\t%d\t\t%d\t\t%d\t\t%d\r\n",
task_status[i].pcTaskName,
task_status[i].xTaskNumber,
task_status[i].eCurrentState,
task_status[i].uxCurrentPriority,
task_status[i].uxBasePriority);
}
/* 5. 获取任务详细信息 */
vTaskGetInfo(
task1_handle, // 要查询的任务句柄
&task_state, // 用于接收任务信息的结构体
pdTRUE, // 是否获取栈状态
eInvalid); // 任务状态(入参被忽略)
printf("任务名称: %s\r\n", task_state.pcTaskName);
printf("任务编号: %d\r\n", task_state.xTaskNumber);
printf("任务状态: %d\r\n", task_state.eCurrentState);
printf("当前优先级: %d\r\n", task_state.uxCurrentPriority);
/* 6. 获取当前正在运行的任务句柄 */
task_handle = xTaskGetCurrentTaskHandle();
printf("当前运行任务句柄=%p, task2句柄=%p\r\n", task_handle, task2_handle);
/* 7. 通过任务名获取句柄 */
task_handle = xTaskGetHandle("task1");
printf("通过名称获取task1句柄=%p, task1原始句柄=%p\r\n", task_handle, task1_handle);
/* 8. 获取栈空间水位线(栈剩余的最小值→反映栈峰值使用量) */
task_stack_remain_min = uxTaskGetStackHighWaterMark(task2_handle);
printf("task2栈剩余空间最小值=%d\r\n", task_stack_remain_min);
/* 9. 获取任务状态(运行/就绪/阻塞/挂起/删除) */
e_task_state = eTaskGetState(task1_handle);
printf("task1当前状态=%d\r\n", e_task_state);
/* 10. 打印可读格式的任务列表 */
vTaskList(task_info);
printf("%s\r\n", task_info);
while (1)
{
vTaskDelay(500);
}
}
File: 07_任务运行时间统计/Core/Src/freertos_demo.c
#include "freertos_demo.h"
#include "FreeRTOS.h"
#include "task.h"
#include "LED.h"
#define START_TASK_STACK 128
#define START_TASK_PRIORITY 1
TaskHandle_t start_task_handle;
void start_task(void *pvParameters);
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handle;
void task1(void *pvParameters);
#define TASK2_STACK 128
#define TASK2_PRIORITY 3
TaskHandle_t task2_handle;
void task2(void *pvParameters);
void freertos_start(void)
{
xTaskCreate((TaskFunction_t)start_task,
(char *)"start_task",
(configSTACK_DEPTH_TYPE)START_TASK_STACK,
(void *)NULL,
(UBaseType_t)START_TASK_PRIORITY,
(TaskHandle_t *)&start_task_handle);
vTaskStartScheduler();
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
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);
vTaskDelete(NULL);
taskEXIT_CRITICAL();
}
void task1(void *pvParameters)
{
while (1)
{
printf("task1正在运行...\r\n");
LED_Toggle(LED1_Pin);
vTaskDelay(500);
}
}
char task_time_info[500];
/**
* @description: task2——每隔500ms打印各任务运行时间统计
*/
void task2(void *pvParameters)
{
while (1)
{
printf("task2正在运行...\r\n");
/* 获取各任务的运行时间统计表(需要硬件定时器支持) */
vTaskGetRunTimeStats(task_time_info);
printf("%s\r\n", task_time_info);
vTaskDelay(500);
}
}
P06 FreeRTOSConfig.h(启用查询功能):
#define configUSE_TRACE_FACILITY 1 // 启用任务跟踪功能
#define configUSE_STATS_FORMATTING_FUNCTIONS 1 // 启用格式化输出函数
#define INCLUDE_xTaskGetHandle 1 // 启用通过名称获取句柄
#define INCLUDE_uxTaskGetStackHighWaterMark 1 // 启用栈水位线查询
P07 FreeRTOSConfig.h(启用运行时统计 + 硬件定时器配置):
#define configGENERATE_RUN_TIME_STATS 1 // 生成运行时统计
#if configGENERATE_RUN_TIME_STATS
extern volatile unsigned long ulHighFrequencyTimerTicks; // 高频定时器计数值
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() ( ulHighFrequencyTimerTicks = 0UL ) // 初始化定时器
#define portGET_RUN_TIME_COUNTER_VALUE() ulHighFrequencyTimerTicks // 读取当前计数值
#endif
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
| Function | Parameters | Return | Description |
|---|---|---|---|
uxTaskPriorityGet |
xTask | UBaseType_t | 获取任务优先级 |
vTaskPrioritySet |
xTask, uxNewPriority | void | 设置任务优先级 |
uxTaskGetNumberOfTasks |
无 | UBaseType_t | 获取系统中任务总数 |
uxTaskGetSystemState |
pxTaskStatusArray, uxArraySize, pulTotalRunTime | UBaseType_t | 获取所有任务的状态 |
vTaskGetInfo |
xTask, pxTaskStatus, xGetFreeStackSpace, eState | void | 获取任务详细信息 |
xTaskGetCurrentTaskHandle |
无 | TaskHandle_t | 获取当前运行任务的句柄 |
xTaskGetHandle |
pcNameToQuery | TaskHandle_t | 通过任务名获取句柄 |
uxTaskGetStackHighWaterMark |
xTask | UBaseType_t | 获取栈剩余空间下限(以 word 计) |
eTaskGetState |
xTask | eTaskState | 获取任务状态(running/ready/blocked/suspended/deleted) |
vTaskList |
pcWriteBuffer | void | 将任务列表格式化输出为可读字符串 |
vTaskGetRunTimeStats |
pcWriteBuffer | void | 获取任务运行时统计信息 |
vTaskList()、uxTaskGetSystemState()、eTaskGetState() 等函数都需要此宏为 1。vTaskList() 需要同时开启 configUSE_TRACE_FACILITY 和 configUSE_STATS_FORMATTING_FUNCTIONS。vTaskGetRunTimeStats() 依赖一个比 SysTick 更高分辨率的硬件定时器。如果不配置该定时器,统计结果无意义。使用 TIM6/TIM7 等基本定时器即可。vTaskList() 和 vTaskGetRunTimeStats() 输出的文本内容随任务数量变化,确保提供的缓冲区足够大(每个任务约 40~60 字节)。