ESP32 Guru Meditation Error

Buonasera a tutti, sto cercando da tempo di realizzare un macropad (stile Streamdeck), quindi con pulsanti, un encoder magnetico e uno schermo ili9488, per la cui grafica ho usato, per semplicità, Squareline studio (che usa la libreria LVGL). Tuttavia sta dando molti più problemi di quel che mi aspettavo, in particolar modo negli ultimi giorni non da un effettivo errore ma compare sul monitor seriale "Guru Meditation Error", riportato per intero qui sotto:

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x400d8727  PS      : 0x00060b30  A0      : 0x800d9f61  A1      : 0x3ffb20d0  
A2      : 0x00000000  A3      : 0x00000001  A4      : 0x00060920  A5      : 0x3f46724c  
A6      : 0x00001017  A7      : 0x00000004  A8      : 0x00000000  A9      : 0x3ffb8188  
A10     : 0x80000001  A11     : 0xb33fffff  A12     : 0x80091c2f  A13     : 0x3ffbcbe0  
A14     : 0x00000003  A15     : 0x00060023  SAR     : 0x00000020  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000004  LBEG    : 0x4008bf4d  LEND    : 0x4008bf5d  LCOUNT  : 0xffffffff  

Backtrace: 0x400d8724:0x3ffb20d0 0x400d9f5e:0x3ffb20f0 0x400da2bd:0x3ffb21d0 0x400d1cfc:0x3ffb21f0 0x400d2986:0x3ffb2210 0x40107838:0x3ffb2270 0x400919ae:0x3ffb2290


ELF file SHA256: d2d544ab05d1f87b

Da quel che ho letto online ho capito che si tratta di un problema di allocazione della memoria, in quanto si sta chiedendo di accedere a dei byte "illegali", ma oltre a questo problema generale non sono in grado di leggerci di più.
La cosa strana è che non ho fatto chissà che modifiche (o addirittura nessuna) che mi spunta nuovamente. Ho già provato in molti modi (alleggerendo di molto il buffer per lvgl, togliendo varie librerie bluetoth che potrebbero dare problemi...) ma non sono riuscito a capirne il perché.
Vi lascio qui il codice, perdonatemi se non è proprio bellissimo e soprattutto se è un po' disortinato

#include <AS5600.h>
#include <lvgl.h>
#include <TFT_eSPI.h>
#include <ui.h>
#include <Keypad.h>
#include <WiFi.h>    
#include <HTTPClient.h>
#include <UrlEncode.h>
#include <WiFiUdp.h>


WiFiClient client;
HTTPClient http;

WiFiUDP udp;
const char* hostPC = "192.168.1.9"; 
const int udpPort = 4210;


//Var. encoder
AS5600 as5600;
float primoangolo;
float angolo;
int difangolo;

//Var. wifi
const char* ssid = "censurato"; 
const char* password = "censurato";

//Var. whatsapp bot
String phoneNumber = "censurato";
String apiKey = "censurato";

bool LED;

//Var. pagine
int screen = 1;
int enc = 0;

//Inizializzazione schermo
unsigned long mil = millis();
static const uint16_t screenWidth  = 480;
static const uint16_t screenHeight = 320;

#define LVGL_BUFFER_LINES 20

static lv_color_t buf1[screenWidth * LVGL_BUFFER_LINES];

TFT_eSPI tft = TFT_eSPI( screenWidth, screenHeight );

void my_disp_flush (lv_display_t *disp, const lv_area_t *area, uint8_t *pixelmap)
{
    uint32_t w = ( area->x2 - area->x1 + 1 );
    uint32_t h = ( area->y2 - area->y1 + 1 );

    if (LV_COLOR_16_SWAP) {
        size_t len = lv_area_get_size( area );
        lv_draw_sw_rgb565_swap( pixelmap, len );
    }

    tft.startWrite();
    tft.setAddrWindow( area->x1, area->y1, w, h );
    tft.pushColors( (uint16_t*) pixelmap, w * h, true );
    tft.endWrite();

    lv_disp_flush_ready( disp );
}

static uint32_t my_tick_get_cb (void) { return millis(); }

//Inizializzazione keypad
const byte ROWS = 3;
const byte COLS = 3; 
int keys[ROWS][COLS] = {
    {1,2,3},
    {4,5,6},
    {7,8,9}
};

byte rowPins[ROWS] = {23, 32, 25};
byte colPins[COLS] = {13, 14, 12};

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


//Funzione whatsapp bot
void sendMessage(String message){

  String url = "https://api.callmebot.com/whatsapp.php?phone=" + phoneNumber + "&apikey=" + apiKey + "&text=" + urlEncode(message);    
  HTTPClient http2;
  http2.begin(url);

  http2.addHeader("Content-Type", "application/x-www-form-urlencoded");
  
  int httpResponseCode = http2.POST(url);
  if (httpResponseCode == 200){
    Serial.print("Message sent successfully");
  }
  else{
    Serial.println("Error sending the message");
    Serial.print("HTTP response code: ");
    Serial.println(httpResponseCode);
  }
  http2.end();
}

//Funzione invio macro
void macro(String macro){
  udp.beginPacket(hostPC, udpPort);
  udp.print(macro);  
  udp.endPacket();

  Serial.println("Inviato: "+ macro);
  delay(100);
}

void setup ()
{   
    Serial.begin( 9600 );   
    Serial.println("Inizializzazione lv...");    
    lv_init();
    Serial.println("lvgl inizializzato");

    if (!buf1) {
      Serial.println("Allocazione buffer fallita!");
    while(1);
}
     

#if LV_USE_LOG != 0
    lv_log_register_print_cb( my_print );
#endif
    Serial.println("Inizializzazione tft");
    tft.begin();
    tft.setRotation( 3 );
    tft.setSwapBytes(true);  
    Serial.println("tft inizializzazione");
    

    static lv_disp_t* disp;
    disp = lv_display_create( screenWidth, screenHeight );
    Serial.println("flush start");
    lv_display_set_buffers( disp, buf1, NULL, screenWidth * LVGL_BUFFER_LINES, LV_DISPLAY_RENDER_MODE_PARTIAL);
    Serial.println("flush 2");
    lv_display_set_flush_cb( disp, my_disp_flush );

    Serial.println("display flush");

    lv_tick_set_cb( my_tick_get_cb );

    ui_init();
    Serial.println( "Setup done");

    delay(500);

     WiFi.begin(ssid, password);
    Serial.println("Connecting");
    while(WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("");
    Serial.print("Connected to WiFi network with IP Address: ");
    Serial.println(WiFi.localIP());

    keypad.addEventListener(keypadEvent);

    as5600.begin();
    as5600.setDirection(AS5600_CLOCK_WISE);
    primoangolo = as5600.rawAngle() * 360.0 / 4096;
    delay(100);
    macro("funziono");
    

}

lv_obj_t* schermi[]{ui_Screen1, ui_Screen2, ui_Screen3};
//Macro funzioni
void vuota(){
  Serial.println("vuoto")
}

void Change(int schermo){
  lv_scr_load(schermi[schermo]);
  screen = schermo;
}


void setLED(String aggiunta){
  http.useHTTP10(true);
  String urlLED = "http://192.168.1.14/win" + aggiunta;
  http.begin(client, urlLED);
  http.GET();
  http.end();
}

void setRGB(int red, int green, int blue){
  setLED("&FX=0&R="+String(red)+"&G="+String(green)+"&B="+String(blue));
}

void setLedColorHSV(float h, double s, double v) {
  double r=0; 
  double g=0; 
  double b=0;

  double hf=h/60.0;

  int i=(int)floor(h/60.0);
  double f = h/60.0 - i;
  double pv = v * (1 - s);
  double qv = v * (1 - s*f);
  double tv = v * (1 - s * (1 - f));

  switch (i)
  {
  case 0:
    r = v;
    g = tv;
    b = pv;
    break;
  case 1:
    r = qv;
    g = v;
    b = pv;
    break;
  case 2: 
    r = pv;
    g = v;
    b = tv;
    break;
  case 3:
    r = pv;
    g = qv;
    b = v;
    break;
  case 4:
    r = tv;
    g = pv;
    b = v;
    break;
  case 5:
    r = v;
    g = pv;
    b = qv;
    break;
  }

  int red=constrain((int)255*r,0,255);
  int green=constrain((int)255*g,0,255);
  int blue=constrain((int)255*b,0,255);

  setRGB(red,green,blue);
}
//Funzioni
void func1 (){
  macro("sospendi");
  Serial.println("func 1");
}

void func1HOLD (){
  macro("spegni");
  Serial.println("func 1");
}

void func2 (){
  Serial.println("func 2");
}
void func2HOLD (){
  Change(3);
  float partenza = angolo;
  Serial.println("func 2 hold");
}

void func3 (){
  macro("Google");
  Serial.println("func 3");
}
void func3HOLD (){
  macro("scuola");
  Serial.println("func 3 hold");
}

void func4 (){
  macro("screenshot1");
  Serial.println("func 4");
}
void func4HOLD (){
  macro("screenshot2");
  Serial.println("func 4 hold");
}

void func5 (){
  macro("pausa");
  Serial.println("func 5");
}

void func6 (){
  macro("next");
  Serial.println("func 6");
}

void func7 (){
  macro("spotify");
  Serial.println("func 7");
}

void func8 (){
  Change(2);
  Serial.println("func 8");
}

void func9 (){
  Change(1);
  Serial.println("func 9");
}

void func10(){
  sendMessage("/trova");
  Serial.println("func 10");
}

void func11 (){
  Serial.println("func 11");
}
void func12 (){
  Serial.println("func 12");
}

void func13 (){
  macro("note");
  Serial.println("func 13");
}

void func14 (){
  macro("AI");
  Serial.println("func 14");
}
void func14HOLD (){
  macro("AIfoto");
  Serial.println("func 14 hold");
}

void func15 (){
  Change(3);
  Serial.println("func 15");
}

void funcencoder(){
  enc = (enc+1)%5;
}

//Array funzioni
void (*function[2][8])(void) = 
{
  {func1,func2,func3,func4,func5,func6,func7,func8},
  {func9,func10,func11,func12,func13,func14,func15,vuota},

};

void (*functionHOLD[2][8])(void) = 
{
  {func1HOLD,func2HOLD,func3HOLD,func4HOLD,vuota,vuota,vuota,vuota},
  {vuota,vuota,vuota,vuota,func14HOLD,vuota,vuota,vuota},

};

void keypadEvent(KeypadEvent key){
  if (keypad.getState() == PRESSED){
    while (keypad.getState() == PRESSED){
      delay(1);
    }
    if (keypad.getState() == HOLD){
      Serial.println("HOLD");
      functionHOLD[screen][key]();
    }
    else{
      Serial.println("PRESSED");
      function[screen][key]();
    }
  }
}


void loop ()
{   
    delay(1000);
    Change(2);
    delay(1000);
    Change(1);
    macro(".");
    angolo = as5600.rawAngle() * (360.0 / 4096); 
    difangolo = int(primoangolo-angolo);
    if (abs(difangolo)>1 && screen != 4){
      switch(enc){
        case 1:
        if (difangolo > 0){
          for(int i=0;i<=abs(difangolo);i++){
          macro("volume up");
          delay(1);
          }
        }
        else{
          for(int i=0;i<=abs(difangolo);i++){
          macro("volume down");
          delay(1);
          }
        }
        case 2:
        setLED("&A=~"+String(difangolo));
      }
    }
    if (screen == 4){
      setLedColorHSV(angolo,1,1);

    }
    int key = keypad.getKey();
    lv_timer_handler();

}

A giudicare dai Serial.print usati per il debug, non è un problema di inizializzazione delle varie librerie, errore, da quel che ho letto, molto comune in questi casi.

Grazie in anticipo per chiunque provi almeno a darmi una mano!

Ok, proverò a vedere se posso aiutarti, usando Google Translate. L'inglese sarebbe più comodo, ma per quello dovresti postare in quella lingua nella sezione inglese.

Sì, è vero. Potresti provare a usare un decodificatore di eccezioni, ma non ne ho mai usato uno. La cosa più ovvia sarebbe una scrittura o una lettura oltre i limiti dell'array, e nel tuo caso l'array dei puntatori a funzione sarebbe il primo posto in cui cercare.

Supponendo che il tuo kepad non restituisca mai una chiave superiore a 7, la prima dimensione sembra più ovvia.

int screen = 1;

(...)

if (screen == 4)

(...)

function[screen][key]();

Apparentemente 'screen' può arrivare fino a 4, mentre l'array di callback della funzione arriva solo a 1 (0 e 1) e quindi tutto ciò che potrebbe essere recuperato potrebbe non essere affatto un puntatore a una funzione.

(edit)Tendo a usare switch()-case: per implementare qualcosa del genere

Anch'io ero un po' confuso, ma a un secondo sguardo era solo l'indentazione

    Serial.println("lvgl inizializzato");

    if (!buf1) {
      Serial.println("Allocazione buffer fallita!");
    while(1);
}
     

#if LV_USE_LOG != 0
    lv_log_register_print_cb( my_print );