WiFi with timer interrupts sometimes throws a meditation error

kurtisblow
Posts: 8
Joined: Fri Oct 23, 2020 6:41 am

WiFi with timer interrupts sometimes throws a meditation error

Postby kurtisblow » 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:

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);
  }
  
}
HW Timer Init

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);
Callbacks HW Timers:

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

Who is online

Users browsing this forum: No registered users and 28 guests