1、触发任务看门狗超时
1.1、基本信息(图中红字部分)
E (35626) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (35626) task_wdt: - IDLE0 (CPU 0)
E (35626) task_wdt: Tasks currently running:
E (35626) task_wdt: CPU 0: main
E (35626) task_wdt: CPU 1: IDLE1
E (35626) task_wdt: Print CPU 0 (current core) backtrace
这一段是说明情况,提到的信息包括:看门狗触发了超时事件,CPU0的IDLE进程没有及时喂狗,系统中的任务有哪些,当前正在运行的任务是什么。
1.2、Backtrace调用栈回溯信息
Backtrace: 0x400D83BB:0x3FFB0F80 0x400D8780:0x3FFB0FA0 0x40082D75:0x3FFB0FD0 0x4000C04D:0x3FFB8210 0x400D60E1:0x3FFB8230 0x400D6129:0x3FFB8250 0x400D5FF8:0x3FFB8270 0x400E45A0:0x3FFB82B0 0x40085E35:0x3FFB82E0
--- 0x400d83bb: task_wdt_timeout_handling at C:/Users/LY/esp/v5.3.1/esp-idf/components/esp_system/task_wdt/task_wdt.c:434
0x400d8780: task_wdt_isr at C:/Users/LY/esp/v5.3.1/esp-idf/components/esp_system/task_wdt/task_wdt.c:507
0x40082d75: _xt_lowint1 at C:/Users/LY/esp/v5.3.1/esp-idf/components/xtensa/xtensa_vectors.S:1240
0x4000c04d: _xtos_return_from_exc in ROM
0x400d60e1: EPD_READBUSY at E:/epaper/code/epaper/components/epaper_driver/epaper.c:66
0x400d6129: EPD_Update at E:/epaper/code/epaper/components/epaper_driver/epaper.c:87
0x400d5ff8: app_main at E:/epaper/code/epaper/main/hello_world_main.c:70
0x400e45a0: main_task at C:/Users/LY/esp/v5.3.1/esp-idf/components/freertos/app_startup.c:208
0x40085e35: vPortTaskWrapper at C:/Users/LY/esp/v5.3.1/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134
这部分是详细的调用栈回溯信息,它展示了从看门狗超时处理函数开始,到具体的应用程序代码的调用路径。
重点关注应用程序代码部分:
EPD_READBUSY
函数(位于E:/epaper/code/epaper/components/epaper_driver/epaper.c
文件的第66行)。EPD_Update
函数(位于E:/epaper/code/epaper/components/epaper_driver/epaper.c
文件的第87行)。app_main
函数(位于E:/epaper/code/epaper/main/hello_world_main.c
文件的第70行)。
在这里就可以看到出问题的函数,函数名称、源文件中的具体行数位置。
例如,我的代码中EPD_READBUSY
函数在等待电子纸显示模块的忙信号,而这个等待过程阻塞了。
2、几种解决方式
2.1、vTaskDelay
任务延时 让出 CPU 资源(最常见、简单)
使用vTaskDelay
函数主动让进程延时一段时间,给其他进程执行的机会。
vTaskDelay(10 / portTICK_PERIOD_MS);
2.2、关闭看门狗(不建议)、增加看门狗超时时间
关闭看门狗可以解决看门狗超时的问题,但是可能会让某一进程长时间占用CPU,如果代码有问题,也不能复位,整个系统失去响应,损失了程序的健壮性。
默认的任务看门狗超时时间是5秒,已经不短啦。但是如果真的有需要,倒是可以调。
这两个配置都可以直接在menuconfig中修改,如下图:
2.3、喂狗(一种不成功的尝试及原因分析)
一开始是这么个想法:看门狗超时是因为没喂狗,那就自己在相关代码中喂狗。
首先,需要为当前的进程注册任务看门狗esp_task_wdt_add
,比如app_main进程。
#include "esp_task_wdt.h"
void app_main(void)
{
esp_task_wdt_add(NULL);
......
}
如果不注册,会报错
task_wdt: esp_task_wdt_reset(705): task not found.
其次,要在进程调用会阻塞的某个函数中进行喂狗。
void func()
{
esp_task_wdt_reset();
......
}
最后,因为进程已经注册了任务看门狗,所以该进程本身也必须在指定时间内(默认是5s)进行喂狗,否则还是会出现任务看门狗超时。
但是,这样还是不行的,这么说吧,任务看门狗是各家的狗,不是同一条狗。
就算你在app_main进程注册了看门狗,并按时喂狗,此时喂的是app_main家里的狗,也不能解决IDLE线程家的狗没喂的问题。
2.4、其他方式
阻塞是因为某些条件没有达到,可以利用信号量等其他的方式挂起进程,在达到条件后自动继续执行。