Skip to content

(SOLVED) Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed) ESP32 VSC Platformio #3634

@petervflocke

Description

@petervflocke

Hardware:

Board: ESP32 Dev Module node32
IDE name: Platform.io on Visual Studio Code
Computer OS: Ubuntu?

Description:

Decoding Guru Meditation does not provide a place of the issue.

Exception Cause: Not found

0x400d1d90: loop() at /home/peter/Documents/PlatformIO/Projects/monitorv1/src/main.cpp:150 (discriminator 10)
0x40084774: _xt_coproc_exc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1091
0x40086a21: spi_flash_restore_cache at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/cache_utils.c:283
0x400d1d90: loop() at /home/peter/Documents/PlatformIO/Projects/monitorv1/src/main.cpp:150 (discriminator 10)
0x400d1d90: loop() at /home/peter/Documents/PlatformIO/Projects/monitorv1/src/main.cpp:150 (discriminator 10)
0x40084771: _xt_coproc_exc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1090
0x40086a1e: spi_flash_phys2cache at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/flash_mmap.c:466
0x40082b8b: esp_reset_reason_get_hint at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/reset_reason.c:117
0x40088b7d: vQueueDelete at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1796 (discriminator 1)

The system reads sensor data over simple 433Mhz ASK routine ( RFReceiver or RadioHead ) and updates a web page on ESPAsyncWebServer. There is also a routine to read the time from NTP server.

If I don't initialize 433Mhz radio objects, failure of the WiFi does not influence the system. If WiFi will be available again the system recovers the WiFI connection and works as design.
With an active radio object and failure of the WiFi after few seconds system reboots with guru meditation:

Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed)
Core 1 register dump:
PC : 0x400d1d90 PS : 0x00060034 A0 : 0x40084774 A1 : 0x3ffbe7b0
A2 : 0x00000004 A3 : 0x3ffc192c A4 : 0x00000000 A5 : 0x00000010
A6 : 0x00000000 A7 : 0x1300005c A8 : 0x80080f80 A9 : 0x00000001
A10 : 0x00000000 A11 : 0x00000000 A12 : 0x3ffc1c7c A13 : 0x00000000
A14 : 0x3ffc1c78 A15 : 0xffffffff SAR : 0x00000018 EXCCAUSE: 0x00000007
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Core 1 was running in ISR context:
EPC1 : 0x40086a21 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x400d1d90

Backtrace: 0x400d1d90:0x3ffbe7b0 0x40084771:0x3ffbe7d0 0x40086a1e:0x3ffba1f0 0x40082b8b:0x3ffba210 0x40088b7d:0x3ffba230

The reboots happen also even if the transmitter is switched off and actually there is no reason to call any radio method.

I read here1 and here2 that a part of the code within interrupt routine must always be in the ESP32's IRAM - is that correct?

I tried to add IRAM_ATTR to few function handling radio parts without any success.

Question1:

Can i somehow disable (taking into consideration a slowdown of the performance) the caching? Is there something similar in Arduino / Platformio config to disable SPI_MASTER_ISR_IN_IRAM in ESP32 config settings?

Question2:

Or how can I identify a function, which requires to stay in IRAM (if it is the solution of my problem)?

Sketch:

#include <Arduino.h>
#include "main.h"
#include "index.h"
#include "credentials.h"
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
#include <Timezone.h>
#include "WiFi.h"
#include <ESPmDNS.h>
#include "ESPAsyncWebServer.h"
#include <PinChangeInterruptHandler.h>
#include <RFReceiver.h>

void updateJson();
void blink();
void printData(Tdata&);
void printDateTime(Timezone, time_t, const char *);

// Central European Time (Frankfurt, Paris)
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 0);     /// get UTC
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};     // Central European Summer Time
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};       // Central European Standard Time
Timezone CE(CEST, CET);
TimeChangeRule *tcr; 

time_t syncNTP();
getExternalTime NtpTime = &syncNTP;

AsyncWebServer server(80);
AsyncEventSource events("/events");

Tdata sensorsData[sensorNumber];
char jsonData[370];

RFReceiver receiver(4);

void setup()
{
  for (int i=0; i<sensorNumber; i++) {
    sensorsData[0].timeStamp = 0;
    sensorsData[0].temperature = 0.0;
    sensorsData[0].humidity = 0.0;
    sensorsData[0].pressure = 0.0;
    sensorsData[0].battery = 0.0;
}
 
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  delay(1000);
   
  WiFi.begin(ssid, password);
  Serial.setDebugOutput(true);
  PRINTS("Connecting to WiFi ");
  while (WiFi.status() != WL_CONNECTED) {
    PRINTS(".");
    blink();
   }
  PRINTS(" connected\n");
  PRINTS(WiFi.localIP());
  
  if (!MDNS.begin(localDomain)) {
      PRINTS("Error setting up MDNS responder! Program Stoped\n");
      while(1) {
          blink();
      }
  }
  PRINTS("mDNS responder started\n");

  timeClient.begin();
  if (!timeClient.update()) {
    PRINTS("1st NTP Update Failed. Program Stoped\n");
      while(1) {
          blink();
      }    
  };

  setSyncInterval(_setSyncInterval);
  setSyncProvider(NtpTime);


  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", index_html);
  });

  server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request) {
      request->send(404);
    });
  
  events.onConnect([](AsyncEventSourceClient *client){
    syncNTP();
    updateJson();
    client->send(jsonData,"data",millis());
  });
  
  server.addHandler(&events);
  server.begin();
  MDNS.addService("http", "tcp", 80);

  receiver.begin();
  PRINT("Max Buf: ", MAX_PACKAGE_SIZE);

}
time_t last_utc=0;

void loop()
{
   uint8_t buf[MAX_PACKAGE_SIZE];
   uint8_t buflen = sizeof(buf);
   uint8_t sensorID;
   byte senderId = 0;
   byte packageId = 0;
  
//PP2
    if (receiver.ready())
    { // (driver.recv(buf, &buflen)) // Non-blocking
      buflen = receiver.recvPackage(buf, &senderId, &packageId);
      // Message with a good checksum received, dump it.
	    #if  DEBUG_ON
         //driver.printBuffer("Got:", buf, buflen);
         PRINT("Buf Len:", buflen); PRINTLN;
         PRINT("Size of TData:", sizeof(Tdata)); PRINTLN;
      #endif
      if (buflen==dataSize) {
        //data = *(Tdata *) buf;
        sensorID=(*reinterpret_cast<Tdata *> (buf)).sensorID;
        memcpy(&sensorsData[sensorID],&buf, sizeof(Tdata));
        PRINT("Sensor ID: ", sensorID); PRINTLN;
        sensorsData[sensorID].timeStamp = now();
        updateJson();
        events.send(jsonData,"data",millis());
        printData(sensorsData[sensorID]);
      }
    }
    if (now()-last_utc >= 1) {
     last_utc = now();
     updateJson();
     events.send(jsonData,"data",millis());
     //printDateTime(CE, last_utc,(timeStatus()==timeSet)? " OK":(timeStatus()==timeNeedsSync)? " Need Sync":" Not Set");

    }
}

void updateJson() {
  time_t  t = CE.toLocal(now(), &tcr);
  time_t t0 = CE.toLocal(sensorsData[0].timeStamp, &tcr);
  time_t t1 = CE.toLocal(sensorsData[1].timeStamp, &tcr);
  time_t t2 = CE.toLocal(sensorsData[2].timeStamp, &tcr);
  sprintf(jsonData,jsonStruc, 
      (timeStatus()==timeSet)? "white":(timeStatus()==timeNeedsSync)? "red":"yellow",
      hour(t), minute(t), second(t), day(t), month(t), year(t),
      hour(t0), minute(t0), second(t0), day(t0), month(t0), year(t0)%100U, 
      sensorsData[0].temperature,
      sensorsData[0].humidity,
      sensorsData[0].pressure,
      sensorsData[0].battery,
      hour(t1), minute(t1), second(t1), day(t1), month(t1), year(t1)%100U,  
      sensorsData[1].temperature,
      sensorsData[1].humidity,
      sensorsData[1].pressure,
      sensorsData[1].battery,
      hour(t2), minute(t2), second(t2), day(t2), month(t2), year(t2)%100U,  
      sensorsData[2].temperature,
      sensorsData[2].humidity,
      (float)sensorsData[0].counter);
}

time_t syncNTP() {
  bool NTPSyncOK=true;
  PRINTS("\nNTP Syncing ... ");
  // WiFi.printDiag(Serial);  
  if (WiFi.isConnected()) {
    NTPSyncOK = timeClient.forceUpdate();
  } else {
      PRINTS("\nRecovering WiFi connection\n");
      //WiFi.mode(WIFI_STA);
      WiFi.begin();
      if (WiFi.isConnected()) {
        NTPSyncOK = timeClient.forceUpdate();
        //WiFi.mode(WIFI_OFF);
      } else {
        PRINTS("\nWIFI failed ...\n");
        NTPSyncOK = false;
      }
  }
  if (NTPSyncOK) {
    PRINTS("NTP Sync OK\n");
    return timeClient.getEpochTime();
  }
  else { 
    PRINTS("NTP Sync Failed\n");
    return 0;
  }
}

void blink() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
}

// --------------------------------
void printData(Tdata& data)
{ 
    PRINT ("Sensor      = ", data.sensorID);    PRINTLN;
    PRINT ("Temperature = ", data.temperature); PRINTS(" *C\n");
    PRINT ("Pressure    = ", data.pressure);    PRINTS(" hPa\n");
    PRINT ("Humidity    = ", data.humidity);    PRINTS(" %\n");
    PRINT ("Battery     = ", data.battery);     PRINTS(" V\n");
    PRINTS("Time        = "); printDateTime(CE, data.timeStamp,(timeStatus()==timeSet)? " OK":(timeStatus()==timeNeedsSync)? " Need Sync":" Not Set");
    PRINT ("Counter     = ", data.counter);     PRINTLN;
}

void printDateTime(Timezone tz, time_t utc, const char *descr)
{
    char buf[40];
    char m[4];    // temporary storage for month string (DateStrings.cpp uses shared buffer)
    TimeChangeRule *tcr;        // pointer to the time change rule, use to get the TZ abbrev

    time_t t = tz.toLocal(utc, &tcr);
    strcpy(m, monthShortStr(month(t)));
    sprintf(buf, "%.2d:%.2d:%.2d %s %.2d %s %d %s",
        hour(t), minute(t), second(t), dayShortStr(weekday(t)), day(t), m, year(t), tcr -> abbrev);
    PRINTS(buf); PRINTS(descr); PRINTLN;
}

Sketch main.h:

#include <Arduino.h>
#define  DEBUG_ON 1

#define localDomain "pogoda"
#define _setSyncInterval 15


typedef struct 
{
  float temperature;
  float humidity;
  float pressure;
  float battery;
  long  counter;
  uint8_t  sensorID; 
  long  dummy;
  time_t timeStamp;
} Tdata;

const char jsonStruc[] PROGMEM = R"rawliteral(
{"XC1":"%s",
"clock":"%02d:%02d:%02d &nbsp; %02d:%02d:%02d",
"time0":"%02d:%02d:%02d &nbsp; %02d:%02d:%02d",
"temp0":"%.2f",
"hum0" :"%.0f",
"pres0":"%.0f",
"bat0" :"%.2f",
"time1":"%02d:%02d:%02d &nbsp; %02d:%02d:%02d",
"temp1":"%.2f",
"hum1" :"%.0f",
"pres1":"%.0f",
"bat1" :"%.2f",
"time2":"%02d:%02d:%02d &nbsp; %02d:%02d:%02d",
"temp2":"%.2f",
"hum2" :"%.0f",
"pres2":"%.0f"}
)rawliteral";

const uint8_t sensorNumber = 3;
const uint8_t dataSize = 21; // data frame size

#if  DEBUG_ON
#define PRINT(s, v) { Serial.print(s); Serial.print(v); }    
#define PRINTX(s, v) { Serial.print(s); Serial.print(v, HEX); }  
#define PRINTS(s) Serial.print(s)   
#define PRINTLN Serial.println()
#else
#define PRINT(s, v)   
#define PRINTX(s, v)  
#define PRINTS(s)     
#define PRINTLN
#endif

Sketch index.h:

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang=pl>
<head>
....
</body>
</html>
)rawliteral";

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions