FreeRTOS 接口: vTaskGetRunTimeStats() - 可解决 task watchdog 和调优 task 优先级
vTaskGetRunTimeStats() 介绍使用 ESP32/ESP8266 进行开发时,读者可通过 vTaskGetRunTimeStats() 来协助分析操作系统当前 taskCPU 占用状态,以帮助优化 task 优先级,帮助定位 task watchdog 问题,帮助理解和学习操作系统原理相关知识。读者若想深入了解 vTaskGetRunTimeStats(), 可参考 v...
vTaskGetRunTimeStats() 介绍
使用 ESP32
/ESP8266
进行开发时,读者可通过 vTaskGetRunTimeStats()
来协助分析操作系统当前 task CPU 占用状态,以帮助优化 task 优先级,帮助定位 task watchdog
问题,帮助理解和学习操作系统原理相关知识。
读者若想深入了解
vTaskGetRunTimeStats()
, 可参考 vTaskGetRunTimeStats() 英文原版介绍 相关文档。
vTaskGetRunTimeStats() 使用
注意:
使用 vTaskGetRunTimeStats()
前需使能:
make menuconfig
->Component config
->FreeRTOS
->Enable FreeRTOS trace facility
make menuconfig
->Component config
->FreeRTOS
->Enable FreeRTOS trace facility
->Enable FreeRTOS stats formatting functions
make menuconfig
->Component config
->FreeRTOS
->Enable FreeRTOS to collect run time stats
通过上面配置,等同于使能
FreeRTOSConfig.h
中如下三个宏:
configGENERATE_RUN_TIME_STATS
,configUSE_STATS_FORMATTING_FUNCTIONS
和configSUPPORT_DYNAMIC_ALLOCATION
参考代码
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
void esp_print_tasks(void)
{
char *pbuffer = (char *)calloc(1, 2048);
printf("--------------- heap:%u ---------------------\r\n", esp_get_free_heap_size());
vTaskGetRunTimeStats(pbuffer);
printf("%s", pbuffer);
printf("----------------------------------------------\r\n");
free(pbuffer);
}
void test_task(void *param)
{
while(1) {
esp_print_tasks();
vTaskDelay(3000 / portTICK_RATE_MS);
}
}
打印一次 task CPU 占用情况可调用:
esp_print_tasks();
循环打印 task CPU 占用情况可调用:
xTaskCreate(test_task, "test_task", 2048, NULL, 5, NULL);
vTaskGetRunTimeStats() 结果
读者可以去
task.c
中查看vTaskGetRunTimeStats()
相关实现逻辑,或更有助于读者理解。
例如: 基于 ESP8266, release/v3.3, commit:4c38ff31
, 在 app_main()
中调用 vTaskGetRunTimeStats()
结果如下:
-
第一列: task name
即xTaskCreate
创建该 task 时第二个参数。
如果名称过长,会根据configMAX_TASK_NAME_LEN
截断。 -
第二列: task 占用 CPU 时间值
默认单位是微秒(us
), 即从上电开始,该 task 得到调度执行的时间。
该值通过硬件计数, 参考#define WDEV_COUNT_REG (0x3ff20c00)
。由于采用四字节微秒计数,该值理论上会在约 1.19 小时后溢出。
-
第三列: task 占用 CPU 百分比
即第二列时间值除以上电总时间。
笔记一: task watchdog 定位和解决
通过参考代码,添加 task 占用 CPU
时间代码,分析结果,例如:
分析:
由于 test_task
CPU
占用率较高,导致 IDLE
task
无法得到运行,
从而无法喂狗,当超过配置的 watchdog
超时时间,即触发 task watchdog
。
解决办法:
-
查看占用率较高的 task 代码逻辑,是否有 delay 代码,如果没有,建议加上
vTaskDelay()
来让该 task 休息片刻 -
如果该 task 某个过程,期望时间很短(用户体验考虑),例如 TLS 握手中非对称加解密过程。
那么读者可在该过程中:
A: 考虑添加esp_task_wdt_reset()
手动喂狗。B: 考虑提高 CPU 默认频率来加速此过程。
参考代码:#include "platform/ssl_port.h" ssl_speed_up_enter(); // speed up to 160MHz // user code to speed up ssl_speed_up_exit(); // back to 80MHz, it is necessary for system stability
笔记二:调优 task 优先级
通常建议客户创建的 task 优先级在 1-9 之间。
参考通过上文的 task
的 CPU
占用率,适当修改 task 优先级以符合预期。
例如一:
MQTT task
优先级可以适当高于 OTA task
优先级。
这是由于
OTA task
通常有长时间的擦写flash
过程,如果OTA task
优先级过高,将可能导致MQTT task
长时间得不到运行,触发MQTT PING
超时,或者触发和服务器链接中断。如果优先级设置合理,则 MQTT 链接不会断开,同时可以完成OTA
过程。
例如二:
需长时间占用 CPU 的 task 优先级可以适当降低。
如果长时间占用 CPU, 可能导致系统内部
ppT task
处理WiFi
包不及时,造成bcn timeout
而断开 WiFi 链接等情况。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)