Arduino 如何禁用';中断看门狗&x27;在ESP32中还是增加ISR时间限制?

Arduino 如何禁用';中断看门狗&x27;在ESP32中还是增加ISR时间限制?,arduino,arduino-ide,adafruit,esp32,Arduino,Arduino Ide,Adafruit,Esp32,我正在使用ESP32 DEVKIT和Adafruit VS1053编解码器+MicroSD Breakout-MP3/WAV/MIDI/OGG Play+Record-v4来录制并播放声音。我使用ArduinoIDE进行编码 我现在面临一个问题,模块使用硬件中断进行播放。但当我试着播放音轨时,ESP32一次又一次地重置。调试日志显示: Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1) Core 1 re

我正在使用ESP32 DEVKIT和Adafruit VS1053编解码器+MicroSD Breakout-MP3/WAV/MIDI/OGG Play+Record-v4来录制并播放声音。我使用ArduinoIDE进行编码

我现在面临一个问题,模块使用硬件中断进行播放。但当我试着播放音轨时,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冥想错误:Core 1 panic'ed(CPU 1上的中断wdt超时)
指示其中断wdt

我找到了禁用中断WDT的方法,但没有任何帮助。
~Documents\Arduino\hardware\espressif\esp32\tools\sdk\include\esp32
中的文件
esp\u int\u wdt.h
提供了两个函数,用于为两个或一个CPU启用中断wdt。没有禁用它的功能


如何禁用ESP32中断WDT?

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

与其禁用看门狗计时器,不如确保不要在
循环()中停留太长时间。您应该始终对代码进行结构化,以便在
loop()
中尽可能少地工作,然后让它返回。当它返回支持您的ESP32应用程序的软件时,它将执行重要的内务管理任务,并重置看门狗计时器

例如,你不应该写:

void loop() {
  while(1) {
    do_some_work();
  }
}
相反,你应该写:

void loop() {
  do_some_work();
}
如果您必须在
loop()
中完成比看门狗定时器允许的更多的工作,请确保偶尔从代码中调用
yield()
delay()
;这将允许系统赶上它需要做的事情
yield()
将在完成任何必要的内务工作后立即返回<代码>延迟(毫秒)
将在完成任何需要的工作后返回
毫秒

与其写,不如写

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

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

  do_some_work();
}
或者更好,如果您的循环可以满足多种需求:

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

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

  • 打开菜单配置:
    makemenuconfig
  • 输入
    组件配置
  • 输入ESP32特定的
  • 从中断看门狗中删除星号
  • 根据
    void,esp\u int\u wdt\u init()
    用于初始化中断看门狗。在
    menuconfig
    中启用
    IWDT
    时调用此函数。因此,您可以尝试查找此函数的调用并将其删除;)

    但是: 我建议你不要禁用看门狗。相反,尝试使用FreeRTOS任务在中断时执行大量代码

    我不知道如何在arduino平台上实现,但我可以告诉你我是如何使用esp idf实现的

    首先,创建带有签名的中断处理程序
    void f(void*)

    其次,在中断处理程序中,您必须使用
    xTaskCreate
    xtaskcreatedpinnedtocore
    创建新任务。例如,
    xTaskCreate(MyHandler,“int_handler”,256,NULL,4,NULL)(签出)

    仅此而已,现在您可以在中断时运行大型代码。除此之外,我建议您不要创建太多的任务。系统可能会挂起

    另外,如果您需要每秒处理成吨的interurpt请求,请尝试使用

    或者在menuconfig中关闭它。不过,我同意其他海报,您不应该关闭它,相反,您还可以使用以下功能为其提供信息:

    rtc_wdt_feed();
    
    我通常创建一个优先级最低的FreeRTOS任务,该任务只循环并调用feed方法,延迟小于超时,这样就有足够的时间运行优先级较高的“业务逻辑”。例如:

    在菜单配置或代码中将超时设置为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));
    }
    
    while(true) {
        rtc_wdt_feed();
        vTaskDelay(pdMS_TO_TICKS(100));
    }
    

    这将为FreeRTOS WDT和RTC WDT提供数据,并在系统陷入循环或未在您的时间要求内处理时重置系统。您需要处理超时以及为系统提供计时器的频率。请记住,Wifi、PHY和BT不是确定性的,因此如果您依赖来自“网络”的DAQ,则在计时方面会有很多不可预测性。

    我也遇到了类似的问题。虽然我没有解决方案,但我可以在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));
    }
    
    while(true) {
        rtc_wdt_feed();
        vTaskDelay(pdMS_TO_TICKS(100));
    }
    
    虽然它编译得很好,但以一种非常可靠的方式,它似乎什么也没做

    事实上,我可以触发WDT超时,这是完全可复制的,所以我认为WDT超时根本没有增加,或者WDT被馈送


    我对
    loop()没有任何怀疑(arduino特定任务)可能希望更改、禁用或以任何方式篡改看门狗。另外,
    yield()
    延迟(nnn)似乎什么都不做,不管我把它们放在哪里,不管我放了多少这样的东西。

    恕我直言,你永远不应该告诉某人他们不应该做一些不常用的实践方法,甚至是在特定庄园执行任务的好主意。在庄园里执行一项任务有很多理由,而“产业界”认为这是个坏主意。FWIW:我讲的是近40年的编程经验。
    while(true) {
        rtc_wdt_feed();
        vTaskDelay(pdMS_TO_TICKS(100));
    }