我正在使用 ESP32 DEVKIT link和 Adafruit VS1053编解码器+ MicroSD Breakout-MP3 / WAV / MIDI / OGG播放+录音-v4 {{3 }}录制然后播放声音。我正在使用Arduino IDE进行编码。
我现在面临一个问题,该模块出于播放目的使用硬件中断。但是当我尝试播放音轨时,ESP32会一次又一次地重置。调试日志显示:
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)
Core 1 register dump:
PC : 0x400d1280 PS : 0x00060834 A0 : 0x800d128f A1 : 0x3ffc0bb0
A2 : 0x3ffc241c A3 : 0x3ffb1f20 A4 : 0x800d1779 A5 : 0x3ffb1f00
A6 : 0x3ffc241c A7 : 0x3f400f9c A8 : 0x800d1280 A9 : 0x3ffc0b90
A10 : 0x0000002b A11 : 0x3f401067 A12 : 0x800d1691 A13 : 0x3ffb1ed0
A14 : 0x3ffc241c A15 : 0x00000000 SAR : 0x0000001f EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Core 1 was running in ISR context:
EPC1 : 0x400d4123 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x400d1280
Backtrace: 0x400d1280:0x3ffc0bb0 0x400d128c:0x3ffc0bd0 0x40080e21:0x3ffc0bf0 0x400817d5:0x3ffc0c10 0x400d3ae5:0x00000000
Core 0 register dump:
PC : 0x400ee86e PS : 0x00060934 A0 : 0x8008656c A1 : 0x3ffc7910
A2 : 0x00000008 A3 : 0x00000000 A4 : 0x00000001 A5 : 0x3ffc7f4c
A6 : 0x00000000 A7 : 0x00000001 A8 : 0x3ffc3404 A9 : 0x3ffc33e8
A10 : 0x00000000 A11 : 0x00000001 A12 : 0x00000000 A13 : 0x00000001
A14 : 0x00060b20 A15 : 0x00000000 SAR : 0x00000000 EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Backtrace: 0x400ee86e:0x3ffc7910 0x40086569:0x3ffc7930
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:952
load:0x40078000,len:6084
load:0x40080000,len:7936
entry 0x40080310
Adafruit VS1053 Simple Test
VS1053 found
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)
行表示其中断为wdt。
我搜索了禁用中断WDT的方法,但没有帮助。 esp_int_wdt.h
中的文件~Documents\Arduino\hardware\espressif\esp32\tools\sdk\include\esp32
提供了两个功能,用于为两个或一个CPU启用中断WDT。没有禁用它的功能。
如何禁用ESP32中断WDT?
答案 0 :(得分:4)
看门狗定时器在系统稳定性中起着重要作用。
不要禁用看门狗定时器,而要确保不要在loop()
停留太长时间。您应该始终对代码进行结构设计,以使您在loop()
中所做的工作最少,然后让它返回。当它返回支持您ESP32应用程序的软件时,它将执行重要的内务处理任务,并重置看门狗计时器。
例如,您永远不要写:
void loop() {
while(1) {
do_some_work();
}
}
相反,您应该写:
void loop() {
do_some_work();
}
如果您绝对必须在loop()
中完成比监视程序计时器所允许的更多工作,请确保偶尔从代码中调用yield()
或delay()
;这将使系统赶上它需要做的事情。 yield()
将在完成所有必要的客房整理工作后立即返回;完成所有必要的工作后,delay(milliseconds)
将返回milliseconds
。
所以不要写
void loop() {
unsigned long start_time = millis();
while(millis() - start_time < 10*1000) { }
do_some_work();
}
这将导致看门狗定时器关闭,而您想写
void loop() {
delay(10*1000);
do_some_work();
start_time = millis();
}
甚至更好,如果您的循环可能满足了多种需求:
void loop() {
static unsigned long start_time1 = millis();
static unsigned long start_time2 = millis();
if(millis() - start_time >= 10*1000) {
do_some_work1();
start_time1 = millis();
}
if(millis() - start_time >= 20*1000) {
do_some_work2();
start_time2 = millis();
}
}
答案 1 :(得分:1)
我不知道如何使用arduino禁用监视程序,但是我可以告诉您如何使用esp-idf
及其make menuconfig
make menuconfig
component config
ESP32-specific
interrupt watchdog
删除星星 P.S。根据{{3}},void esp_int_wdt_init()
用于初始化中断看门狗。在IWDT
中启用menuconfig
时将调用此函数。因此,您可以尝试找到此函数的调用并将其删除;)
但是: 我建议您不要禁用看门狗。取而代之的是,尝试使用FreeRTOS任务在中断时执行大量代码。
我不确定如何在arduino平台上完全做到这一点,但我可以告诉我如何使用esp-idf
首先,创建带有签名void f(void*)
的中断处理程序
void MyHandler(void* pData){
/* Your code here */
vTaskDelete(NULL); // delete current taks, must have
}
第二,您必须在中断处理程序中使用xTaskCreate
或xTaskCreatePinnedToCore
创建新任务。例如,xTaskCreate(MyHandler, "int_handler", 256, NULL, 4, NULL);
(签出esp-idf docs)
仅此而已,现在您可以在中断上运行大代码了。除此之外,我建议您不要创建太多任务。系统可能会挂起。
P.S。如果您需要每秒处理大量中断请求,请尝试使用api reference
答案 2 :(得分:0)
#include "soc/rtc_wdt.h"
rtc_wdt_protect_off();
rtc_wdt_disable();
或在menuconfig中将其关闭。我也同意其他海报,但是您不应将其关闭,而应使用以下功能:
rtc_wdt_feed();
我通常创建一个最低优先级的FreeRTOS任务,该任务仅循环并以小于超时的延迟调用feed方法,从而为足够高的优先级“业务逻辑”运行留出足够的时间。示例:
在menuconfig或代码中将超时设置为250毫秒:
rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us);
rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM);
tc_wdt_set_time(RTC_WDT_STAGE0, 250);
然后在您的任务中执行此操作:
while(true) {
rtc_wdt_feed();
vTaskDelay(pdMS_TO_TICKS(100));
}
这将同时馈送FreeRTOS WDT和RTC WDT并在系统陷入循环中或在您的时间要求内未处理时重置系统。您需要处理超时问题以及需要多长时间喂一次定时器才能使它正确地适用于您的系统。请注意,Wifi,PHY和BT并不确定,因此,如果您选择定时,则将有很多不确定性取决于“网络”中的DAQ。
答案 3 :(得分:0)
我遇到了类似的问题。尽管我没有解决方案,但是我可以在Arduino + ESP32中进行确认,但以上答案似乎都无法解决这个问题。 特别是:
rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us);
rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM);
tc_wdt_set_time(RTC_WDT_STAGE0, 250);`
然后在您的任务中执行此操作:
while(true) {
rtc_wdt_feed();
vTaskDelay(pdMS_TO_TICKS(100));
}
尽管可以很好地编译,但它似乎以一种非常可靠的方式根本没有任何作用。
实际上,我可以触发WDT超时,并且完全可以重现,所以我认为WDT超时根本不会增加,也不会给WDT供食。
我怀疑loop();
(特定于arduino的任务)中的任何内容都不能希望更改,禁用或以任何方式篡改看门狗。另外,yield();
和delay(nnn);
似乎什么也没做,无论我放置在哪里,无论我放置在其中多少个。