如何禁用 ESP32 中的“中断看门狗”或增加 ISR 时间限制?

use*_*210 7 arduino arduino-ide adafruit esp32

我使用ESP32 DEVKIT 链接Adafruit VS1053 Codec + MicroSD Breakout - MP3/WAV/MIDI/OGG Play + Record - v4 链接来录制然后播放声音。我正在使用 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
Run Code Online (Sandbox Code Playgroud)

该行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?

小智 6

#include "soc/rtc_wdt.h"

rtc_wdt_protect_off();
rtc_wdt_disable();
Run Code Online (Sandbox Code Playgroud)

或者在menuconfig中将其关闭。我同意其他海报,但你不应该关闭它,相反,你也可以使用以下功能来提供它:

rtc_wdt_feed();
Run Code Online (Sandbox Code Playgroud)

我通常创建一个最低优先级的 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);
rtc_wdt_set_time(RTC_WDT_STAGE0, 250);
Run Code Online (Sandbox Code Playgroud)

然后在您的任务中执行此操作:

while(true) {
    rtc_wdt_feed();
    vTaskDelay(pdMS_TO_TICKS(100));
}
Run Code Online (Sandbox Code Playgroud)

这将为 FreeRTOS WDT 和 RTC WDT 提供数据,并在系统陷入循环或未在您的时间要求内处理时重置您的系统。您需要调整超时以及为计时器提供数据的频率,以使其适合您的系统。请记住,Wifi、PHY 和 BT 不是确定性的,因此如果您依赖于来自“网络”的 DAQ。


rom*_*key 1

看门狗定时器对于系统稳定性起着重要作用。

不要禁用看门狗定时器,而是尽量确保您不会在室内停留loop()太久。您应该始终构建您的代码,以便您可以做最少的工作loop()并让它返回。当它返回时,支持 ESP32 应用程序的软件将执行重要的内务任务,并重置看门狗定时器。

例如,你不应该写:

void loop() {
  while(1) {
    do_some_work();
  }
}
Run Code Online (Sandbox Code Playgroud)

相反,你应该写:

void loop() {
  do_some_work();
}
Run Code Online (Sandbox Code Playgroud)

如果您绝对需要做loop()比看门狗计时器允许的更多的工作,请确保您调用yield()delay()偶尔从您的代码中调用;这将使系统能够赶上它需要做的事情。yield()完成任何必要的家务工作后将立即返回;完成任何需要的工作后将delay(milliseconds)返回。milliseconds

所以而不是写

void loop() {
  unsigned long start_time = millis();

  while(millis() - start_time < 10*1000) { }

  do_some_work();
}
Run Code Online (Sandbox Code Playgroud)

这会导致看门狗定时器关闭,你需要写

void loop() {
  delay(10*1000);

  do_some_work();
  start_time = millis();
}
Run Code Online (Sandbox Code Playgroud)

甚至更好,如果您的循环可能满足多种需求:

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,你永远不应该告诉别人他们永远不应该做一些不常见的做法,甚至是在特定庄园执行任务的好主意。有很多理由在庄园里执行一项被“行业”认为是坏主意的任务。FWIW:我有近 40 年的编程经验。 (12认同)