FreeRTOS 任务信息查询函数使用指南
本文整理 FreeRTOS 官方提供的任务状态、栈、运行耗时查询系列 API用于工程调试、CPU 负载评估、任务栈溢出风险排查辅助开发者合理分配系统资源避免 CPU 占用过高、栈溢出、资源浪费等问题。1.任务函数序号函数功能1void vTaskListchar* buffer以“表格”形式获取所有任务的信息2UBaseType_t uxTaskGetNumberOfTasks(void);获取系统中任务的数量3UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,const UBaseType_t uxArraySize,configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime );获取所有任务状态信息4void vTaskGetInfo( TaskHandle_t xTask,TaskStatus_t * pxTaskStatus, BaseType_t xGetFreeStackSpace,eTaskState eState );获取指定单个的任务信息5UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );获取任务的任务栈历史剩余最小值6void vTaskGetRunTimeStats( char *pcWriteBuffer );获取任务的运行时间补充说明栈水位单位为word字32 位 MCU 1 字 4 字节计算实际剩余字节 水位值 × 42.功能演示1.vTaskList代码示例 static char taskListBuffer[512]; // 获取任务列表信息 vTaskList(taskListBuffer); USART_2_printf(Task List:\n%s\n, taskListBuffer);运行结果2.vTaskGetRunTimeStats代码示例 UBaseType_t taskCount uxTaskGetNumberOfTasks(); USART_2_printf(Task Count: %d\n, taskCount);运行结果3.uxTaskGetSystemState代码示例 TaskStatus_t *taskStatusArray NULL; UBaseType_t taskCount uxTaskGetNumberOfTasks(); UBaseType_t arraySize 0; uint32_t totalRunTime 0; // 分配内存存储任务状态 taskStatusArray (TaskStatus_t *)pvPortMalloc(taskCount * sizeof(TaskStatus_t)); if (taskStatusArray NULL) { USART_2_printf(Failed to allocate memory for task status\n); return CAT_RETURN_STATE_ERROR; } // 获取任务系统状态 arraySize uxTaskGetSystemState(taskStatusArray, taskCount, totalRunTime); // 打印任务状态信息 USART_2_printf(Task State Info:\n); USART_2_printf(Task Name\t\tState\tPriority\tStack Watermark\n); USART_2_printf(--------------------------------------------------------------\n); for (UBaseType_t i 0; i arraySize; i) { char stateChar; switch (taskStatusArray[i].eCurrentState) { case eRunning: stateChar R; break; case eReady: stateChar R; break; case eBlocked: stateChar B; break; case eSuspended: stateChar S; break; case eDeleted: stateChar D; break; default: stateChar U; break; } USART_2_printf(%-16s\t%c\t%u\t\t%u\n, taskStatusArray[i].pcTaskName, stateChar, taskStatusArray[i].uxCurrentPriority, taskStatusArray[i].usStackHighWaterMark); } USART_2_printf(--------------------------------------------------------------\n); USART_2_printf(Total Run Time: %lu\n, totalRunTime); // 释放内存 vPortFree(taskStatusArray);运行结果4.vTaskGetInfo代码示例 TaskHandle_t targetTaskHandle NULL; TaskStatus_t *taskStatusArray NULL; TaskStatus_t taskStatus; UBaseType_t taskCount uxTaskGetNumberOfTasks(); UBaseType_t arraySize 0; uint32_t totalRunTime 0; taskStatusArray (TaskStatus_t *)pvPortMalloc(taskCount * sizeof(TaskStatus_t)); if (taskStatusArray NULL) { USART_2_printf(Failed to allocate memory\n); return CAT_RETURN_STATE_ERROR; } arraySize uxTaskGetSystemState(taskStatusArray, taskCount, totalRunTime); // 查找匹配的任务 for (UBaseType_t i 0; i arraySize; i) { targetTaskHandle taskStatusArray[i].xHandle; vTaskGetInfo(targetTaskHandle, taskStatus, pdTRUE, eInvalid); // 打印任务详细信息 USART_2_printf(Task Info: %s\n, taskStatus.pcTaskName); USART_2_printf( State: ); switch (taskStatus.eCurrentState) { case eRunning: USART_2_printf(Running\n); break; case eReady: USART_2_printf(Ready\n); break; case eBlocked: USART_2_printf(Blocked\n); break; case eSuspended: USART_2_printf(Suspended\n); break; case eDeleted: USART_2_printf(Deleted\n); break; default: USART_2_printf(Unknown\n); break; } USART_2_printf( Priority: %u\n, taskStatus.uxCurrentPriority); USART_2_printf( Base Priority: %u\n, taskStatus.uxBasePriority); USART_2_printf( Stack High Watermark: %u words\n, taskStatus.usStackHighWaterMark); } vPortFree(taskStatusArray); vTaskDelay(pdMS_TO_TICKS(1000));运行结果5.uxTaskGetStackHighWaterMark代码示例 TaskHandle_t targetTaskHandle NULL; TaskStatus_t *taskStatusArray NULL; TaskStatus_t taskStatus; UBaseType_t taskCount uxTaskGetNumberOfTasks(); UBaseType_t arraySize 0; uint32_t totalRunTime 0; UBaseType_t watermark 0; taskStatusArray (TaskStatus_t *)pvPortMalloc(taskCount * sizeof(TaskStatus_t)); if (taskStatusArray NULL) { USART_2_printf(Failed to allocate memory\n); return CAT_RETURN_STATE_ERROR; } arraySize uxTaskGetSystemState(taskStatusArray, taskCount, totalRunTime); // 查找匹配的任务 for (UBaseType_t i 0; i arraySize; i) { targetTaskHandle taskStatusArray[i].xHandle; watermark uxTaskGetStackHighWaterMark(targetTaskHandle); // 打印结果 USART_2_printf(--------------------------------------------------------------\n); USART_2_printf(Task: %s\n, taskStatusArray[i].pcTaskName); USART_2_printf(Stack High Watermark: %u words\n, watermark); } vPortFree(taskStatusArray); vTaskDelay(pdMS_TO_TICKS(1000)); }运行结果6.vTaskGetRunTimeStats代码示例 static char runTimeStatsBuffer[512]; // 获取任务运行时间统计信息 vTaskGetRunTimeStats(runTimeStatsBuffer); // 打印任务运行时间统计 USART_2_printf(Task Run Time Stats:\n); USART_2_printf(%s\n, runTimeStatsBuffer);FreeRTOS 是使用一个外部的变量进行统计时间的理论上提供一个低于系统时钟节拍的即可若使用的时基与系统时钟频率相同会导致运行时间较短的任务统计的CPU利用率精度不足1%,建议使用较高频率的定时器作为时基并打开FreeRTOSConfig.h中的configGENERATE_RUN_TIME_STATS开关STM32部分芯片提供DWT功能可直接作为计数器/* 运行时间和任务状态统计相关定义 */ #define configGENERATE_RUN_TIME_STATS 1 /* 1: 使能任务运行时间统计功能, 默认: 0 */ #if configGENERATE_RUN_TIME_STATS /* 使用DWT硬件周期计数器作为时基80MHz下精度为12.5ns */ #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* DWT已在main函数初始化 */ #define portGET_RUN_TIME_COUNTER_VALUE() (*(volatile uint32_t*)0xE0001004) /* DWT-CYCCNT寄存器地址 */ #endif运行结果