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

7
我正在使用ESP32 DEVKITlinkAdafruit VS1053 Codec + MicroSD Breakout - MP3/WAV/MIDI/OGG Play + Record - v4link来录制并播放声音。我在使用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的方法,但没有帮助。在“~Documents\Arduino\hardware\espressif\esp32\tools\sdk\include\esp32”文件夹中的“esp_int_wdt.h”文件提供了两个函数,用于启用双CPU或单CPU的中断WDT。没有禁用它的功能。如何禁用ESP32中断WDT?
5个回答

6
#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);
rtc_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

我不知道如何使用Arduino禁用看门狗,但我可以告诉您如何使用esp-idf及其make menuconfig禁用它:

  1. 打开menuconfig:make menuconfig
  2. 进入component config
  3. 进入ESP32-specific
  4. interrupt watchdog中删除星号

P.S. 根据esp-idf文档void esp_int_wdt_init()用于初始化中断看门狗。当在menuconfig中启用时,将调用此函数。因此,您可以尝试查找此函数的调用并将其删除;)

但是:我建议您不要禁用看门狗。取而代之的是,请尝试使用FreeRTOS任务在中断上执行大量代码。

我不确定如何在Arduino平台上确切地执行此操作,但我可以告诉您如何在esp-idf中执行此操作:

首先,使用签名void f(void*)创建中断处理程序。

void MyHandler(void* pData){
    /* Your code here */
    vTaskDelete(NULL); // delete current taks, must have
}

其次,在中断处理程序中,您必须使用xTaskCreatexTaskCreatePinnedToCore创建新任务。例如:xTaskCreate(MyHandler,“int_handler”,256,NULL,4,NULL);(查看api reference
就这些,现在您可以在中断上运行大代码。除此之外,我建议您不要创建太多的任务。系统可能会挂起。
附言:如果您需要处理每秒钟大量的中断请求,请尝试使用FreeRTOS队列

1
看门狗定时器在系统稳定性方面起着重要作用。
与其禁用看门狗定时器,不如确保您不会在loop()中停留太久。您应该始终构建代码,以便在loop()中尽可能少地工作并让其返回。当它返回时,支持ESP32应用程序的软件可以执行重要的后勤任务,并重置看门狗定时器。
例如,您永远不应编写以下内容:
void loop() {
  while(1) {
    do_some_work();
  }
}

而你应该写成:

而你应该写成:

void loop() {
  do_some_work();
}

如果你必须在loop()中执行比看门狗计时器允许的更多工作,确保你的代码偶尔调用yield()delay(); 这将允许系统赶上它需要做的事情。yield()将在完成任何必要的后勤工作后立即返回; delay(milliseconds)将在完成任何必要的工作后milliseconds毫秒后返回。请注意保留html标签。
所以与其写
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();
  }
}

12
恕我直言,您不应该告诉别人绝对不要使用一种非常规或者某种特定方式执行任务,因为有很多理由可以解释为什么这种方法并不是坏主意。即使这种方法不被业内认可。顺便说一下:我有将近40年的编程经验。 - Capt
是的,虽然有用,但这并没有真正回答问题。 例如,我正在在核心0 GPIO中断期间模拟SPI协议(与esp不兼容)。我将中断保持尽可能长的时间,以防止核心0自身的中断干扰事情。在这种奇怪的情况下,关闭WD或短暂延长它将是最有效的解决方案。 - Sicklebrick
@Sicklebrick 如果你正在这样做,显然你比 OP 更了解,并且能够做出更明智的决策。 - romkey
公正,但这仍然是谷歌上的最佳“答案”,并没有完全回答问题。 - Sicklebrick
一个只是建议做其他事情的“答案”并不算是真正的答案。这里不是一个咨询论坛。如果你无法回答问题,最好不要发表任何帖子。 - NateS

0

我使用HELTEC ESP32 LORA。

选择的开发板是Arduino HELTEC WIFI LORA 32 (V2)。

我的固件运行良好,但一年后使用相同的固件时,esp32开始在中断中重置。

终端中的消息:

Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)。

我进行了以下检查:

  1. 看门狗,它没有起作用

  2. 减少中断内部的程序,它也没有起作用。

最终的解决方案是:

将ESp32通过表达式系统库从2.0.6降级到2.0.3。


0
这段代码禁用了中断看门狗定时器,并且在使用Arduino库时有效。
#include "soc/timer_group_struct.h"
#include "soc/timer_group_reg.h"
...
TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE; // Unlock timer config.
TIMERG1.wdt_feed = 1; // Reset feed count.
TIMERG1.wdt_config0.en = 0; // Disable timer.
TIMERG1.wdt_wprotect = 0; // Lock timer config.

TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed = 1;
TIMERG0.wdt_config0.en = 0;
TIMERG0.wdt_wprotect = 0;

你可能只需要关闭 TIMERG1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接