WiFi with timer interrupts sometimes throws a meditation error
Posted: Tue Mar 15, 2022 7:04 am
Hi,
I'm using a ESP32 for some IoT with MQTT and it works pretty good so far, but sometimes one of the ESP32 goes into a hardfault (Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed)) and I don't really know what I could do against it. It mostly happen, when I power off or power on the broker (the broker is also the access point). So, according to the meditation error, somehow the ISR is interrupted, right? All the ISRs are in the RAM, so I don't really see what I'm doing wrong. About the Serial.println in the ISR you can ignore, since this was only for debugging purposes and the error comes also without it (Serials runs at 500kbaud).
The Systick timer runs with 2Hz, when I increase this frequency, the chance for the error increases, so it seems to be related to this timer callback.
Edit: I think I found the problem, TIMEDIFF_SYSTICK was 1e3 which is interpreted as a double. When I define it as an integer, there are no more hardfaults
The full error:
Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed)
Core 1 register dump:
PC : 0x400d5b50 PS : 0x00060034 A0 : 0x80081a88 A1 : 0x3ffbfe80
A2 : 0x3ffc17c8 A3 : 0x03938700 A4 : 0x00000400 A5 : 0x3ffbfe80
A6 : 0x3ffbfec8 A7 : 0x00000001 A8 : 0x80081654 A9 : 0x3ffbfe70
A10 : 0x80000000 A11 : 0x4186e97a A12 : 0x80000000 A13 : 0x0000061a
A14 : 0x7ff00000 A15 : 0x00000418 SAR : 0x0000000a EXCCAUSE: 0x00000007
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Core 1 was running in ISR context:
EPC1 : 0x40087ce0 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x400d5b50
ELF file SHA256: 0000000000000000
Backtrace: 0x400d5b50:0x3ffbfe80 0x40081a85:0x3ffbfea0 0x40087ac9:0x3ffbfec0 0x40087cdd:0x3ffba190 0x40085503:0x3ffba1b0 0x4008a45a:0x3ffba1d0
#0 0x400d5b50:0x3ffbfe80 in __fixunsdfdi at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libgcc/config/xtensa/ieee754-df.S:2041
#1 0x40081a85:0x3ffbfea0 in __timerISR at C:\Users\usi\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-timer.c:174
#2 0x40087ac9:0x3ffbfec0 in _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1154
#3 0x40087cdd:0x3ffba190 in spi_flash_op_block_func at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/cache_utils.c:203
#4 0x40085503:0x3ffba1b0 in ipc_task at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/ipc.c:62
#5 0x4008a45a:0x3ffba1d0 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)
Here are the important parts of my code:
WiFi and MQTT connect:
HW Timer Init
Callbacks HW Timers:
I'm using a ESP32 for some IoT with MQTT and it works pretty good so far, but sometimes one of the ESP32 goes into a hardfault (Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed)) and I don't really know what I could do against it. It mostly happen, when I power off or power on the broker (the broker is also the access point). So, according to the meditation error, somehow the ISR is interrupted, right? All the ISRs are in the RAM, so I don't really see what I'm doing wrong. About the Serial.println in the ISR you can ignore, since this was only for debugging purposes and the error comes also without it (Serials runs at 500kbaud).
The Systick timer runs with 2Hz, when I increase this frequency, the chance for the error increases, so it seems to be related to this timer callback.
Edit: I think I found the problem, TIMEDIFF_SYSTICK was 1e3 which is interpreted as a double. When I define it as an integer, there are no more hardfaults
The full error:
Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed)
Core 1 register dump:
PC : 0x400d5b50 PS : 0x00060034 A0 : 0x80081a88 A1 : 0x3ffbfe80
A2 : 0x3ffc17c8 A3 : 0x03938700 A4 : 0x00000400 A5 : 0x3ffbfe80
A6 : 0x3ffbfec8 A7 : 0x00000001 A8 : 0x80081654 A9 : 0x3ffbfe70
A10 : 0x80000000 A11 : 0x4186e97a A12 : 0x80000000 A13 : 0x0000061a
A14 : 0x7ff00000 A15 : 0x00000418 SAR : 0x0000000a EXCCAUSE: 0x00000007
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Core 1 was running in ISR context:
EPC1 : 0x40087ce0 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x400d5b50
ELF file SHA256: 0000000000000000
Backtrace: 0x400d5b50:0x3ffbfe80 0x40081a85:0x3ffbfea0 0x40087ac9:0x3ffbfec0 0x40087cdd:0x3ffba190 0x40085503:0x3ffba1b0 0x4008a45a:0x3ffba1d0
#0 0x400d5b50:0x3ffbfe80 in __fixunsdfdi at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libgcc/config/xtensa/ieee754-df.S:2041
#1 0x40081a85:0x3ffbfea0 in __timerISR at C:\Users\usi\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-timer.c:174
#2 0x40087ac9:0x3ffbfec0 in _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1154
#3 0x40087cdd:0x3ffba190 in spi_flash_op_block_func at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/cache_utils.c:203
#4 0x40085503:0x3ffba1b0 in ipc_task at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/ipc.c:62
#5 0x4008a45a:0x3ffba1d0 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)
Here are the important parts of my code:
WiFi and MQTT connect:
Code: Select all
void solx1_stm_wifi()
{
//WiFi:
if(client.loop())
{
auto_timer_started = false;
}
else
{
if(WiFi.status() != WL_CONNECTED)
{
if(!auto_timer_started)
{
solx1_auto_timer_start();
}
//Connect to router
solx1_wifi_connect();
//Connect to MQTT Broker
if(WiFi.status() == WL_CONNECTED)
{
solx1_mqtt_connect();
}
}
else if(WiFi.status() == WL_CONNECTED)
{
if(!auto_timer_started)
{
solx1_auto_timer_start();
}
if(!client.connected())
{
Serial.print("Wifi on, but MQTT not connected, try reconnect...");
solx1_mqtt_connect();
}
}
else
{
if(!auto_timer_started)
{
solx1_auto_timer_start();
}
}
}
}
void solx1_wifi_connect()
{
if(!solx1_wifi_initial_connected)
{
solx1_wifi_initial_connected = true;
solx1_wifi_connecting_started = true;
solx1_wifi_connecting_started_timer = 0;
String hostname = HOSTNAME;
WiFi.macAddress(mac_addr);
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
WiFi.setHostname(hostname.c_str());
WiFi.mode(WIFI_STA);
WiFi.disconnect();
WiFi.begin(solx1_ssid, solx1_pw);
Serial.print("MAC Adress: ");
Serial.println(WiFi.macAddress());
Serial.print("WiFi initial connecting...");
}
else if(!solx1_wifi_connecting_started && (solx1_auto_cmd.stm == SOLX1_STM_SOLAR_NONE))
{
solx1_wifi_connecting_started = true;
solx1_wifi_connecting_started_timer = 0;
Serial.print("***");
WiFi.disconnect();
WiFi.reconnect();
Serial.print("WiFi reconnecting...");
}
if(WiFi.status() != WL_CONNECTED)
{
solx1_wifi_connecting_started_timer += 1;
// Serial.print(".");
if(solx1_wifi_connecting_started_timer > WIFI_SEARCH_TIMEOUT_RETRY) //retry
{
solx1_wifi_connecting_started = false;
solx1_wifi_connecting_started_timer = 0;
return;
}
}
else
{
solx1_wifi_connecting_started = false;
solx1_wifi_connecting_started_timer = 0;
Serial.println();
Serial.print("Connected to WiFi with IP: ");
Serial.println(WiFi.localIP());
}
}
void solx1_mqtt_connect()
{
client.setServer(mqtt_broker, mqtt_port);
client.setCallback(solx1_mqtt_cb);
client.setBufferSize(1024);
#ifdef BROKER_SHUTDOWN_TEST
delay(5000);
#endif
while (!client.connected()) {
String client_id = "esp32-client-";
client_id += String(WiFi.macAddress());
Serial.printf("The client %s connects to the broker\n", client_id.c_str());
Serial.println();
if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
Serial.println("Public emqx mqtt broker connected");
} else {
Serial.print("failed with state ");
Serial.println(client.state());
Serial.println("*****");
return;
}
}
if(client.connected())
{
client.setKeepAlive(10); //10s keep alive
client.subscribe(topic_s,1);
solx1_publish_cos(IDENT_REGISTER,0xff);
}
}
Code: Select all
//Safety Timer
solx1_safety_timer = timerBegin(TIMER_AUTO, 80, true);
timerAttachInterrupt(solx1_safety_timer, &solx1_safety_timer_cb, true);
timerAlarmWrite(solx1_safety_timer, ((uint64_t)solx1_nvm_data.maximum_exposure_time_s)*1e6, false); //in us
// timerAlarmEnable(solx1_safety_timer);
//Timer SOL
solx1_timer_solar = timerBegin(TIMER_SOL, 80, true);
timerAttachInterrupt(solx1_timer_solar, &solx1_timer_solar_cb, true);
timerAlarmWrite(solx1_timer_sol, TIMEOUT_SOL, false); //in us
// timerAlarmEnable(solx1_timer_sol);
//Timer systick
solx1_timer_systick_puls = timerBegin(TIMER_RELAY_PULS_1, 80, true);
timerAttachInterrupt(solx1_timer_systick_puls, &solx1_timer_systick_puls_cb, true);
timerAlarmWrite(solx1_timer_systick_puls, TIMEDIFF_SYSTICK, true); //in us
timerAlarmEnable(solx1_timer_systick_puls);
Code: Select all
void IRAM_ATTR solx1_safety_timer_cb()
{
#ifdef DEBUG_ON
Serial.println("Shutdown triggered");
#endif
solx1_solar_cmd.stm = SOLX1_STM_SOLAR_T7;
//Deactivate the relay 2 and 3
solx1_data_t.rel.relay = solx1_nvm_data.relay_init;
solx1_apply_relay();
}
void IRAM_ATTR solx1_timer_solar_cb()
{
#ifdef DEBUG_ON
Serial.println("timer state_change_done");
#endif
solx1_solar_cmd.state_change_done = true;
}
void IRAM_ATTR solx1_timer_systick_puls_cb()
{
if(solx1_relay_puls.puls_1_active)
{
if(solx1_relay_puls.relay_puls_1_timeout > solx1_relay_puls.cntr_puls_1)
{
solx1_relay_puls.cntr_puls_1 += TIMEDIFF_SYSTICK;
}
else
{
solx1_relay_puls.puls_1_active = false;
solx1_data_t.rel.relay &= ~(solx1_relay_puls.relay_puls_1_bitmap);
#ifdef DEBUG_ON
Serial.print("timer relay puls 4 done: ");
Serial.println(solx1_data_t.rel.relay,BIN);
#endif
}
}
if(solx1_relay_puls.puls_2_active)
{
if(solx1_relay_puls.relay_puls_2_timeout > solx1_relay_puls.cntr_puls_2)
{
solx1_relay_puls.cntr_puls_2 += TIMEDIFF_SYSTICK;
}
else
{
solx1_relay_puls.puls_2_active = false;
solx1_data_t.rel.relay &= ~(solx1_relay_puls.relay_puls_2_bitmap);
#ifdef DEBUG_ON
Serial.print("timer relay puls 5 done: ");
Serial.println(solx1_data_t.rel.relay,BIN);
#endif
}
}
if(solx1_relay_puls.puls_3_active)
{
if(solx1_relay_puls.relay_puls_3_timeout > solx1_relay_puls.cntr_puls_3)
{
solx1_relay_puls.cntr_puls_3 += TIMEDIFF_SYSTICK;
}
else
{
solx1_relay_puls.puls_3_active = false;
solx1_data_t.rel.relay &= ~(solx1_relay_puls.relay_puls_3_bitmap);
#ifdef DEBUG_ON
Serial.print("timer relay puls 6 done: ");
Serial.println(solx1_data_t.rel.relay,BIN);
#endif
}
}
if(solx1_relay_puls.puls_4_active)
{
if(solx1_relay_puls.relay_puls_4_timeout > solx1_relay_puls.cntr_puls_4)
{
solx1_relay_puls.cntr_puls_4 += TIMEDIFF_SYSTICK;
}
else
{
solx1_relay_puls.puls_1_active = false;
solx1_data_t.rel.relay &= ~(solx1_relay_puls.relay_puls_4_bitmap);
#ifdef DEBUG_ON
Serial.print("timer relay puls 7 done: ");
Serial.println(solx1_data_t.rel.relay,BIN);
#endif
}
}
if(solx1_auto_timer.systick_timer_active)
{
// Serial.println(solx1_auto_timer.auto_timer_cntr);
if(solx1_auto_timer.systick_timer_timeout > solx1_auto_timer.systick_timer_cntr)
{
solx1_auto_timer.systick_timer_cntr += TIMEDIFF_SYSTICK;
}
else
{
#ifdef DEBUG_ON
Serial.println("Timer auto triggered!");
#endif
solx1_auto_timer_stop();
if(solx1_nvm_data.flag_automode && solx1_solar_cmd.stm == SOLX1_STM_SOLAR_NONE)
{
solx1_auto_mode_enabled = true;
}
}
}
if(solx1_disconnect_timer.systick_timer_active)
{
// Serial.println(solx1_disconnect_timer.auto_timer_cntr);
if(solx1_disconnect_timer.systick_timer_timeout > solx1_disconnect_timer.systick_timer_cntr)
{
solx1_disconnect_timer.systick_timer_cntr += TIMEDIFF_SYSTICK;
}
else
{
solx1_disconnect_triggered = true;
#ifdef DEBUG_ON
Serial.println("Timer disconnect triggered!");
#endif
solx1_disconnect_timer.systick_timer_active = false;
solx1_disconnect_timer_start(); //restart the timer
}
}
#ifdef DEBUG_ON
if(solx1_debug_timer.systick_timer_timeout > solx1_debug_timer.systick_timer_cntr)
{
solx1_debug_timer.systick_timer_cntr += TIMEDIFF_SYSTICK;
}
else
{
time_cntr += 5;
Serial.print("Time: ");
Serial.print(time_cntr);
Serial.print("; Modes n:");
Serial.print(solx1_solar_cmd.stm);
Serial.print(", a:");
Serial.print(solx1_auto_cmd.stm);
Serial.print(", s:");
Serial.print(solx1_stm_t);
Serial.print("; SC: ");
Serial.println(solx1_solar_cmd.state_change_done);
solx1_debug_timer.systick_timer_cntr = 0;
}
#endif
}
void IRAM_ATTR solx1_timer_flash_protect_cb()
{
#ifdef DEBUG_ON
Serial.println("Timer flash protect done!");
#endif
solx1_flash_write_enabled = true;
}