简体   繁体   English

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

[英]How to disable 'interrupt watchdog' in ESP32 OR increase ISR time limit?

I am using ESP32 DEVKIT link and Adafruit VS1053 Codec + MicroSD Breakout - MP3/WAV/MIDI/OGG Play + Record - v4 link to record and then play the sound.我正在使用ESP32 DEVKIT 链接Adafruit VS1053 Codec + MicroSD Breakout - MP3/WAV/MIDI/OGG Play + Record - v4链接来录制然后播放声音。 I am using Arduino IDE for coding.我正在使用 Arduino IDE 进行编码。

I am facing an issue right now that the module uses hardware interrupt for playing purposes.我现在面临一个问题,该模块使用硬件中断进行播放。 But ESP32 is resetting again and again when I try to play a sound track.但是当我尝试播放音轨时,ESP32 会一次又一次地重置。 The debug log says:调试日志说:

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

The line Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1) indicates that its interrupt wdt.Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)表示它的中断 wdt。

I searched ways to disable interrupt WDT but no help.我搜索了禁用中断 WDT 的方法,但没有帮助。 The file esp_int_wdt.h in ~Documents\\Arduino\\hardware\\espressif\\esp32\\tools\\sdk\\include\\esp32 provides two functions for enabling interrupt WDT for both or one CPU.文件esp_int_wdt.h~Documents\\Arduino\\hardware\\espressif\\esp32\\tools\\sdk\\include\\esp32用于使中断WDT两个或一个CPU提供两个功能。 There is no function to disable it.没有禁用它的功能。

How to disable ESP32 interrupt WDT?如何禁用 ESP32 中断 WDT?

#include "soc/rtc_wdt.h"

rtc_wdt_protect_off();
rtc_wdt_disable();

Or turn it off in menuconfig.或者在 menuconfig 中关闭它。 I agree with other posters though, you should not turn it off, instead, you can also feed it with the following function:我同意其他海报,但你不应该关闭它,相反,你也可以使用以下功能提供它:

rtc_wdt_feed();

I usually create a lowest priority FreeRTOS task that just loops and calls the feed method with a delay less then the timeout, giving enough time for higher priority "business logic" to run.我通常会创建一个优先级最低的 FreeRTOS 任务,该任务只是循环并以小于超时的延迟调用 feed 方法,从而为更高优先级的“业务逻辑”提供足够的时间来运行。 Example:例子:

Set timeout to 250 ms in menuconfig or in code:在 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);

Then do this in your task:然后在您的任务中执行此操作:

while(true) {
    rtc_wdt_feed();
    vTaskDelay(pdMS_TO_TICKS(100));
}

This will feed both the FreeRTOS WDT and the RTC WDT and reset your system if it gets stuck in a loop or doesn't processes within your time requirements.这将同时提供 FreeRTOS WDT 和 RTC WDT,并在系统陷入循环或未在您的时间要求内处理时重置您的系统。 You'll need to play with the timeout and how often you feed the timer to get it right for your system.Keep in mind the Wifi, PHY, and BT are not deterministic so you'll have a lot of unpredictability in timing if you are dependent on DAQ from from "the net".您需要调整超时时间以及为计时器提供的频率以使其适合您的系统。请记住,Wifi、PHY 和 BT 不是确定性的,因此如果您在时间上有很多不可预测性依赖于来自“网络”的 DAQ。

The watchdog timer plays an important role in system stability.看门狗定时器对系统稳定性起着重要作用。

Rather than disabling the watchdog timer, try to make sure that you don't stay in loop() for too long.与其禁用看门狗定时器,不如尝试确保您不会在loop()停留太久。 You should always structure your code so that you do the least work you can in loop() and let it return.您应该始终构建您的代码,以便您在loop()做最少的工作并让它返回。 When it returns the software that supports your ESP32 application gets to do important housekeeping tasks, and reset the watchdog timer.当它返回时,支持您的 ESP32 应用程序的软件可以执行重要的内务管理任务,并重置看门狗定时器。

For instance, you should never write:例如,你永远不应该写:

void loop() {
  while(1) {
    do_some_work();
  }
}

and instead you should write:而你应该写:

void loop() {
  do_some_work();
}

If you absolutely have to do more work in loop() than the watchdog timer allows for, make sure you call yield() or delay() occasionally from your code;如果你绝对需要在loop()比看门狗定时器允许的更多的工作,确保你偶尔从你的代码中调用yield()delay() this will allow the system to catch up on things it needs to do.这将使系统能够赶上它需要做的事情。 yield() will return immediately after doing any needed housekeeping work; yield()将在完成任何需要的内务工作后立即返回; delay(milliseconds) will return milliseconds later after doing any needed work. delay(milliseconds)将在完成任何需要的工作后返回milliseconds

So rather than write所以而不是写

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

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

  do_some_work();
}

which would cause the watchdog timer to go off, you'd want to write这会导致看门狗定时器关闭,你想写

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

  do_some_work();
  start_time = millis();
}

or even better, if your loop may be servicing multiple needs:甚至更好,如果您的循环可能满足多种需求:

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();
  }
}

I don't know how to disable watchdog using arduino, but I can tell you how to disable it using esp-idf and its make menuconfig我不知道如何使用 arduino 禁用看门狗,但我可以告诉您如何使用esp-idf及其make menuconfig禁用它

  1. Open menuconfig: make menuconfig打开 menuconfig: make menuconfig
  2. Enter component config输入component config
  3. Enter ESP32-specific进入ESP32-specific
  4. Remove star from interrupt watchdoginterrupt watchdog删除星号

PS According to esp-idf docs void esp_int_wdt_init() is used to init interrupt watchdog. PS 根据esp-idf docs void esp_int_wdt_init()用于初始化中断看门狗。 This function is called when IWDT enabled in menuconfig .menuconfig启用IWDT时调用此函数。 So you can try to find call of this function and remove it ;)所以你可以尝试找到这个函数的调用并删除它;)

BUT: I advise you to not disable watchdog.但是:我建议您不要禁用看门狗。 Instead of this, try to use FreeRTOS tasks to execute large amount of code on interrupt.相反,尝试使用 FreeRTOS 任务在中断时执行大量代码。

Im not sure how to do it exactly in arduino platform, but I can tell how I did it using esp-idf我不知道如何在 arduino 平台上完全做到这一点,但我可以告诉我我是如何使用 esp-idf 做到的

First, create interrupt handler with signature void f(void*)首先,创建签名为void f(void*)中断处理程序

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

Second, in interrupt handler you have to create new task, using xTaskCreate or xTaskCreatePinnedToCore .其次,在中断处理程序中,您必须使用xTaskCreatexTaskCreatePinnedToCore创建新任务。 For example, xTaskCreate(MyHandler, "int_handler", 256, NULL, 4, NULL);例如, xTaskCreate(MyHandler, "int_handler", 256, NULL, 4, NULL); (Check out api reference ) (查看api 参考

That's all, now you can run big code on your interrupt.就是这样,现在您可以在中断上运行大代码。 In addition to this, I advise you to not create too many tasks.除此之外,我建议您不要创建太多任务。 System may hang.系统可能挂起。

PS If you need to handle tonns of interurpt requests per second, try to use FreeRTOS queues PS 如果您需要每秒处理大量的中断请求,请尝试使用FreeRTOS 队列

I am using ESP32 DEVKIT link and Adafruit VS1053 Codec + MicroSD Breakout - MP3/WAV/MIDI/OGG Play + Record - v4 link to record and then play the sound.我正在使用ESP32 DEVKIT 链接Adafruit VS1053编解码器+ MicroSD Breakout-MP3 / WAV / MIDI / OGG播放+录制-v4链接来录制然后播放声音。 I am using Arduino IDE for coding.我正在使用Arduino IDE进行编码。

I am facing an issue right now that the module uses hardware interrupt for playing purposes.我现在面临一个问题,该模块出于播放目的使用硬件中断。 But ESP32 is resetting again and again when I try to play a sound track.但是当我尝试播放音轨时,ESP32会一次又一次地重置。 The debug log says:调试日志中显示:

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

The line Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1) indicates that its interrupt wdt.Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)表明它的中断wdt。

I searched ways to disable interrupt WDT but no help.我搜索了禁用中断WDT的方法,但没有帮助。 The file esp_int_wdt.h in ~Documents\\Arduino\\hardware\\espressif\\esp32\\tools\\sdk\\include\\esp32 provides two functions for enabling interrupt WDT for both or one CPU. esp_int_wdt.h ~Documents\\Arduino\\hardware\\espressif\\esp32\\tools\\sdk\\include\\esp32提供了两个功能,用于为两个或一个CPU启用中断WDT。 There is no function to disable it.没有禁用它的功能。

How to disable ESP32 interrupt WDT?如何禁用ESP32中断WDT?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM