ESP32 crashes when I call WiFi.mode(WIFI_MODE_APSTA) from within a Interrupt ISR

1

Summary:

On my ISR routine I call a function that tries to set the WiFi mode to APSTA in a ESP32, and it crashes with the following dump:

Scanning for Modules...
OK1
Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1)
Core 1 register dump:
PC      : 0x4008b7cc  PS      : 0x00060d34  A0      : 0x8008a9a7  A1      : 0x3ffbe530  
A2      : 0x3ffb595c  A3      : 0x3ffb8074  A4      : 0x00000001  A5      : 0x00000001  
A6      : 0x00060d23  A7      : 0x00000000  A8      : 0x3ffb8074  A9      : 0x3ffb8074  
A10     : 0x00000018  A11     : 0x00000018  A12     : 0x00000001  A13     : 0x00000001  
A14     : 0x00060d21  A15     : 0x00000000  SAR     : 0x00000020  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0xffffffff  
Core 1 was running in ISR context:
EPC1    : 0x400e176c  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x4008b7cc

Backtrace: 0x4008b7cc:0x3ffbe530 0x4008a9a4:0x3ffbe550 0x40088c3f:0x3ffbe570 0x400d504d:0x3ffbe5b0 0x400ed002:0x3ffbe5d0 0x400e1adf:0x3ffbe5f0 0x400d1991:0x3ffbe610 0x40081002:0x3ffbe710 0x400811c5:0x3ffbe790 0x4008125d:0x3ffbe7b0 0x40084a2d:0x3ffbe7d0 0x400d223a:0x3ffb1fb0 0x40088e39:0x3ffb1fd0

Core 0 register dump:
PC      : 0x40089e2e  PS      : 0x00060034  A0      : 0x8008b005  A1      : 0x3ffb5500  
A2      : 0x3ffbf300  A3      : 0x0000cdcd  A4      : 0xb33fffff  A5      : 0x00000001  
A6      : 0x00060023  A7      : 0x0000abab  A8      : 0x0000abab  A9      : 0x3ffb5500  
A10     : 0x00000000  A11     : 0x3ffba744  A12     : 0x000002cc  A13     : 0x3ffbbc44  
A14     : 0x3ffba8e9  A15     : 0x00000000  SAR     : 0x00000001  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0x00000000  

Backtrace: 0x40089e2e:0x3ffb5500 0x4008b002:0x3ffb5530 0x40088b9f:0x3ffb5550 0x40088ca9:0x3ffb5590 0x400819ad:0x3ffb55b0 0x400e27c1:0x3ffb55d0 0x400f157d:0x3ffb55f0 0x400e2b3e:0x3ffb5620 0x400e2dc5:0x3ffb5650 0x400ecb31:0x3ffb56a0 0x400e9136:0x3ffb56d0 0x4008f83f:0x3ffb56f0 0x40088e39:0x3ffb5730

Rebooting...
ets Jun  8 2016 00:22:57

Detailed info:

In my project I have 2 buttons that call a different ISR (void IRAM_ATTR ScanForModule1() and void IRAM_ATTR ScanForModule2()) each, and within either ISR I call the same function with a different argument (void IRAM_ATTR ScanForModules(uint8_t moduleNumber)). This new function call for WiFi mode to be set to WiFi.mode(WIFI_MODE_APSTA) and that makes the ESP32 crash.

I added some tracing "OK"s for debugging before and after the Wifi call and it only shows the one before.

Any idea that may help me? Thank you

(non compilable snippet)

// ISR Scan for modules 1 in AP mode
void IRAM_ATTR ScanForModule1()
{
    Serial.println("Enrolling Module 1...");
    module1_addr = NULL;
    ScanForModules(1);
}

// ISR Scan for modules 2 in AP mode
void IRAM_ATTR ScanForModule2()
{

    Serial.println("Enrolling Module 2...");
    module2_addr = NULL;
    ScanForModules(2);
}

// Scan for modules in AP mode
void IRAM_ATTR ScanForModules(uint8_t moduleNumber)
{
    detachInterrupt(ENROLL_BUTTON1_PIN);
    detachInterrupt(ENROLL_BUTTON2_PIN);
    Serial.println("Scanning for Modules...");

    // Switch the ESP to AP and start broadcasting
    //configDeviceAP();
    Serial.println("OK1");
    WiFi.mode(WIFI_MODE_APSTA); //Crashes here <---------------------
    Serial.println("OK2");
crash
wifi
interrupt
esp32
asked on Stack Overflow Feb 5, 2021 by Luis Rodrigues • edited Feb 5, 2021 by Luis Rodrigues

1 Answer

1

The reason for the crash is that your WiFi mode change takes longer to process than an interrupt service routine is allowed to execute (well, technically the watchdog doesn't get reset because the task responsible for it gets blocked by ISR). Which is the expected outcome. Interrupt handlers are not meant for doing any serious work, but rather for registering an event and poking a responsible task to process it.

In this case you should have a task which simply sits and waits for the button press. When a button is pressed, the ISR doesn't do anything but wake up the processing task and say which button was pressed. You can build your own "notification system" with a simple shared bool and busywaiting; or use the FreeRTOS event groups to implement this. I find the Mastering the FreeRTOS Real Time Kernel – a Hands On Tutorial Guide to be an excellent resource for beginners.

answered on Stack Overflow Feb 5, 2021 by Tarmo • edited Feb 6, 2021 by Tarmo

User contributions licensed under CC BY-SA 3.0