Description
Basic Infos
- This issue complies with the issue POLICY doc.
- I have read the documentation at readthedocs and the issue is not addressed there.
- I have tested that the issue is present in the current master branch (aka latest git).
- I have searched the issue tracker for a similar issue.
- If there is a stack dump, I have decoded it.
- I have filled out all fields below.
Platform
- Hardware: ESP-12
- Core Version: [5a47cab]
- Development Env: Arduino IDE
- Operating System: Ubuntu
Settings in IDE
- Module: Adafruit HUZZAH
- Flash Mode: qio
- Flash Size: 4MB
- lwip Variant: v2 Lower Memory
- Reset Method: nodemcu
- Flash Frequency: 40Mhz
- CPU Frequency: 80Mhz
- Upload Using: SERIAL
- Upload Speed: 115200 (serial upload only)
Problem Description
I have found, that there are some actions that an ISR can take, that can unexpectedly result in a "Hardware WDT". Calls made from an ISR to panic(), abort(), assert(), or the __unhandled_exception() will result in: no message, no stack trace, just:
ets Jan 8 2013,rst cause:4, boot mode:(3,6)
wdt reset
Obviously, it would be best to avoid these in our ISRs. However, it might not be obvious we are doing these calls from an ISR. Take the case of running a build with just "Debug: Serial" selected in the IDE.
This will enable the UMM_POISON
, build flag. If an ISR steps on the poison, then later does a free()
, a message is printed (with non-IRAM based printf()
function) then an attempt is made within umm_malloc.cpp
to call panic()
. When I tested this the umm poison message printed; however, the panic()
details never appeared. Alter a long period, the "Hardware WDT" event appeared.
What I think I am seeing is, calls from an ISR that reach a panic(), abort(), assert(), or the __unhandled_exception() will eventually arrive at raise_exception()
in module core_postmortem.cpp
. Then onto the inline assembly for "syscall". After a long period of silence, I see the "Hardware WDT" event. My test method at that time was less than ideal because I was using a printf function that was not in IRAM. However, it did print all the way up to the "syscall", before the WDT appeared and nothing at __wrap_system_restart_local().
It is interesting to find that there are causes for the "Hardware WDT", that are not caused by being stuck in a loop.
In Arduino Core 2.5.0 and up, a failed "new" operator without (std::nothrow)
in an ISR will call abort()
resulting in WDT. I am concerned that there might be a lot more cases out there.
This one is unconfirmed however looks like a good one to verify:
Arduino/cores/esp8266/core_esp8266_main.cpp
Lines 104 to 115 in 7c67015
Arduino/cores/esp8266/cont_util.cpp
Lines 65 to 68 in 7c67015
It looks like a call from an ISR, that reaches yield(), would call panic() and the message would never be seen.
I could say more but I'll wait and see what you say, just in case I made a wrong turn in my assessment of this issue.
MCVE Sketch
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <interrupts.h>
#include <assert.h>
#define CC4US_DELAY(us) ((us) * clockCyclesPerMicrosecond())
void ICACHE_RAM_ATTR timer0_handler(void) {
timer0_detachInterrupt();
// From an ISR context these calls will fail with a hardware WDT
// No event related information or stack trace is printed.
panic();
// abort();
// assert(1==0);
}
void setup(void) {
Serial.begin(115200);
delay(20);
WiFi.mode(WIFI_OFF);
Serial.printf("\n\nUp and running.\n");
{
AutoInterruptLock(15);
timer0_isr_init();
timer0_attachInterrupt(&timer0_handler);
timer0_write(ESP.getCycleCount() + CC4US_DELAY(150));
}
}
void loop() {
}
Debug Messages
Up and running.
ets Jan 8 2013,rst cause:4, boot mode:(3,6)
wdt reset
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v5a47cab7
~ld