esp32arduino-idearduino-c++

ESP32, tft.init() causing "Guru Meditation Error: Core 1 panic'ed (StoreProhibited)"


I am using ESP32 S3 devkit to drive a display with ILI9341 driver using TFT_eSPI library. ESP 01s module is serial communication with the ESP32. When I gave power to the esp32 initially, it had this same code in the flash (Which I uploaded some while ago) and both the code and display were working fine. But when I changed the SPI_READ_FREQUENCY to 27MHZ from 40MHZ in the User_Setup.h file in the tft_espi library, and flashed the esp again this Guru Meditation Error occured. Even after changing the SPI_READ_FREQUENCY to previous value did not fixed the error. I also tried flashing one of the graphic_test examples provided with the tft_eSPI library (Which tested and worked fine previously) but still it's the same.

Error :

*ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
Saved PC:0x420bc5fe
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3808,len:0x4bc
load:0x403c9700,len:0xbd8
load:0x403cc700,len:0x2a0c
entry 0x403c98d0
1
1
Guru Meditation Error: Core  1 panic'ed (StoreProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x4200820b  PS      : 0x00060830  A0      : 0x820082e0  A1      : 0x3fcebb40  
A2      : 0x00000010  A3      : 0x00000000  A4      : 0x60004000  A5      : 0x0000000b  
A6      : 0x000000ff  A7      : 0x00000000  A8      : 0x08000000  A9      : 0x3fcebb10  
A10     : 0x3fc9a8a0  A11     : 0x00000001  A12     : 0xffffffff  A13     : 0x00000040  
A14     : 0x00000000  A15     : 0x3fc9437c  SAR     : 0x00000010  EXCCAUSE: 0x0000001d  
EXCVADDR: 0x00000010  LBEG    : 0x42031740  LEND    : 0x420317a3  LCOUNT  : 0x00000003  


Backtrace: 0x42008208:0x3fcebb40 0x420082dd:0x3fcebb70 0x42003d01:0x3fcebb90 0x4203270a:0x3fcebc50


ELF file SHA256: c5b17ef6fb480832

Rebooting...*

Code:

#include <WiFi.h>
#include "time.h"
#include <Preferences.h>
#include <TFT_eSPI.h>
#include <FS.h>

#include <Firebase_ESP_Client.h>
#include "addons/TokenHelper.h"
#include "addons/RTDBHelper.h"

#define TX_PIN 41
#define RX_PIN 40

#define API_KEY "key"
#define DATABASE_URL "link"

String deviceID = "100001";
String path;

TFT_eSPI tft = TFT_eSPI();
TFT_eSprite pwdField = TFT_eSprite(&tft);

unsigned long milliStart = 0;

String symbol[8][12] = {
  { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=" },
  { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]" },
  { "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "\\" },
  { "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "`", " " },

  { "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+" },
  { "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "{", "}" },
  { "A", "S", "D", "F", "G", "H", "J", "K", "L", ":", "\"", "|" },
  { "Z", "X", "C", "V", "B", "N", "M", "<", ">", "?", "~", " " }
};


uint16_t calData[5] = { 396, 3350, 270, 3369, 7 };

const int buzzerPin = 5;
int pressTone = 2000;

unsigned long startTime = 0;
unsigned long elapsedTime = 0;

FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
bool signupOK = false;


const char* ssidMem = "ssid";
const char* passwordMem = "password"; 

const char* isConnected = "isConnected";

Preferences preferences;

const char* ntpServer = "in.pool.ntp.org";
const long gmtOffset_sec = 19800;  //GMT+5:30
const int daylightOffset_sec = 0;

int prevIntTime;
String msg;
bool buzzerOn;
byte buzzerCount;

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  //Initializing serial communication betweeen master ESP01s
  Serial2.begin(115200, SERIAL_8N1, RX_PIN, TX_PIN);
  Serial.println(1);

  pinMode(buzzerPin, OUTPUT);

  //initializing tft object and initial display
  Serial.println(1);
  tft.init();
  Serial.println(123);
  tft.setRotation(1);
  tft.setTouch(calData);
  tft.fillScreen(TFT_BLACK);
  tft.setTextDatum(MC_DATUM);
  tft.setTextSize(2);
  Serial.println(2);

  //opens a preferences library with the namespace "WiFiVars" search for stored ssid and pwd in the preferences and return "" found none
  preferences.begin("WiFiVars");
  String ssid = preferences.getString(ssidMem, "");
  String password = preferences.getString(passwordMem, "");
  String isCon = preferences.getString(isConnected, "0");  //this memorize whether the device was connected to a wifi before the last turn off

  welcomeScreen();

  Serial.println(3);
  if (isCon == "0") {
    initialConnection();
  } else {
    if (!connectWifi(ssid, password)) {
      ESP.restart();
    };
  }
  // Init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

  config.api_key = API_KEY;
  config.database_url = DATABASE_URL;

  Serial.print("Sign up new user... ");
  if (Firebase.signUp(&config, &auth, "", "")) {
    Serial.println("ok");
    signupOK = true;
  } else {
    Serial.printf("%s\n", config.signer.signupError.message.c_str());
  }

  // Assign the callback function for the long running token generation task.
  config.token_status_callback = tokenStatusCallback;  //--> see addons/TokenHelper.h

  Firebase.begin(&config, &auth);
  Firebase.reconnectWiFi(true);
}


int hh, mm, day, month, monthDay, intTime;

void loop() {
  serialInteruptHandler();

  struct tm time = getLocalTime();

  hh = (int)time.tm_hour;
  mm = (int)time.tm_min;
  day = (int)time.tm_wday;
  month = (int)time.tm_mon;
  monthDay = (int)time.tm_mday;


  int intTime = hh * 100 + mm;

  if (WiFi.status() != 3) {
    Serial.println("WiFi Connection lost");

    byte input = wifiConnectionLost();  // Read touch input... 1 - new wifi, 2 wait
    if (input == 1) {
      String isCon = "0";
      preferences.putString(isConnected, isCon.c_str());
      ESP.restart();
    } else {
      tft.fillScreen(TFT_BLACK);
      tft.setTextColor(TFT_WHITE);
      tft.drawString("Restart if you want to", 160, 120, 1);
      tft.drawString("change networks", 160, 140, 1);
      delay(3000);
      while (WiFi.status() != 3) {
        clockNoAlarm(hh, mm, day, month, monthDay);
        tft.setTextColor(TFT_WHITE);
        tft.drawString("No Connection", 160, 200, 1);
        delay(20000);
      }
    }
  }

  if (prevIntTime != intTime) {
    prevIntTime = intTime;
    Serial.println(&time, "%A, %B %d %H:%M");

    path = deviceID + "/Alarms/" + day + "/" + intTime;
    if (Firebase.ready() && signupOK) {
      if (Firebase.RTDB.getString(&fbdo, path)) {
        msg = fbdo.stringData();
        Serial.println(msg);
        buzzerOn = true;
        buzzerCount = 0;
        alarmDisplay(hh, mm, msg);
      } else {
        if ((String)fbdo.errorReason() == "path not exist") {
          Serial.print("No alarms at : ");
          Serial.println(&time, "%H:%M");
          buzzerOn = false;
          clockNoAlarm(hh, mm, day, month, monthDay);
        }
      }
    }
  }

  if (prevIntTime == intTime && buzzerOn && buzzerCount < 20) {
    tone(buzzerPin, 1000);
    delay(400);
    tone(buzzerPin, 3000);
    delay(400);
    noTone(buzzerPin);
    delay(400);
    buzzerCount++;
  }
}

uint32_t btnID;
float battery;

//Callback used when it is need to send button press event to the firebase
void serialInteruptHandler() {
  //put a tone here
  if (Serial2.available()) {
    btnID = Serial2.readStringUntil('\n').toInt();
    Serial.println(btnID);
    battery = Serial2.readStringUntil('\n').toFloat();
    Serial.println(battery);

    String btnPathStatus = deviceID + "/Buttons/" + btnID + "/Status/";
    String btnPathBat = deviceID + "/Buttons/" + btnID + "/Battery/";

    if (Firebase.ready() && signupOK && btnID != 0) {
      // Write an btn status and battery percentage on the database path specified for the button ID.
      if (Firebase.RTDB.setInt(&fbdo, btnPathStatus, 1)) {
        Firebase.RTDB.setFloat(&fbdo, btnPathBat, battery);
        Serial.println("PASSED");
        tone(buzzerPin, 3000);
        delay(2000);
        noTone(buzzerPin);
        Firebase.RTDB.setInt(&fbdo, btnPathStatus, 0);
      } else {
        Serial.println("Failed: " + fbdo.errorReason());
      }
    } else if (btnID != 0) {
      Serial.print("Firebase Sign up error... SignUp status : ");
      Serial.println(signupOK);
    }
  }
}



//put a button namer prompts and function here


struct tm getLocalTime() {
  struct tm timeinfo;

  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return {};
  }
  return timeinfo;
}


void initialConnection() {

  //remove when touch available
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE);
  tft.setTextDatum(BL_DATUM);
  tft.drawString("Select a Network", 15, 20, 1);

  byte numNetworks = WiFi.scanNetworks();  //scan for wifi networks and return number of networks found

  //display this after sorting according to RSSI
  String temp;
  for (int i = 0; i < numNetworks; ++i) {
    temp = String(i + 1) + ") " + String(WiFi.SSID(i));
    tft.drawString(temp, 5, 40 + i * 20, 1);
    tft.drawRoundRect(2, 22 + i * 20, 318, 18, 5, TFT_CYAN);
    //Iterate over WiFi object (global arduino core object) i times
  }

  uint16_t x = 0, y = 0;  // To store the touch coordinates

  int pressedIndex = 0;
  while (pressedIndex == 0) {
    bool pressed = tft.getTouch(&x, &y);
    if (pressed) {
      for (int i = 1; i <= 11; i++) {
        if (y > i * 20 && y < (i + 1) * 20) {
          pressedIndex = i;
          tone(buzzerPin, pressTone);
          delay(100);
          noTone(buzzerPin);
          break;
        }
      }
    }
  }

  String inpSSID = WiFi.SSID(pressedIndex - 1);


  String inpPassword = getKeyboardOut(inpSSID);
  Serial.print("Final Password is : ");
  Serial.println(inpPassword);

  bool connectWifiResponse = connectWifi(inpSSID, inpPassword);

  if (connectWifiResponse) {
    preferences.putString(isConnected, "1");
  }
  ESP.restart();
}


bool connectWifi(String id, String pwd) {
  // Connect to Wi-Fi
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE);
  String temp = "Connecting to " + id;
  tft.setTextDatum(MC_DATUM);
  tft.drawString(temp, 160, 120, 1);
  WiFi.begin(id.c_str(), pwd.c_str(), 1);

  byte attempts = 0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    attempts++;
    Serial.print(".");
    //Serial.println(WiFi.status());
    if (attempts > 20) {
      tft.fillScreen(TFT_BLACK);
      tft.setTextColor(TFT_RED);
      temp = "Can't connect to " + id;
      tft.drawString(temp, 160, 120, 1);
      tft.drawString("Check your credentials", 160, 145, 1);
      preferences.putString(isConnected, "0");
      delay(2000);
      WiFi.disconnect(true);
      return false;
    }
  }

  if (WiFi.status() == WL_CONNECTED) {
    tft.fillScreen(TFT_BLACK);
    tft.setTextColor(TFT_GREEN);
    tft.drawString("WiFi Connected...", 160, 120, 2);
    preferences.putString(ssidMem, id.c_str());  //stores the successfully conneted wifi credentials on the preferences namespace named WiFiVars
    preferences.putString(passwordMem, pwd.c_str());
    return true;
  }
}

void welcomeScreen() {
  //Welcome Screen
  tft.setTextDatum(MC_DATUM);
  tft.setTextSize(2);
  tft.drawString("Guardian", 160, 60, 4);
  tft.drawString("Call", 160, 180, 4);
  delay(500);
  tft.drawString("<           >", 160, 120, 4);
  delay(500);
  tft.drawString(".", 120, 120, 4);
  delay(500);
  tft.drawString(".", 140, 120, 4);
  delay(500);
  tft.drawString(".", 160, 120, 4);
  delay(500);
  tft.drawString(".", 180, 120, 4);
  delay(500);
  tft.drawString(".", 200, 120, 4);
  delay(1000);
}

I erased the flash using esptool and tried reinstalling TFT_eSPI library but to no avail.


Solution

  • The issue was in the new updates to ESP32 boards provided by the espressif systems. I recently updated all updatable libraries and board packages. I step by step downgraded all the libraries with recent commits in their github repos. I first downgraded Adafruit BusIO to 1.16.1 to 1.15.0 and ESP32 board package to 2.0.14. This was the fix for this issue.