Xinyuan-LilyGO / TTGO-T-Display

MIT License
1.05k stars 337 forks source link

Guru Meditation Error when using print() in macro #51

Open Rhombur opened 3 years ago

Rhombur commented 3 years ago

Hello, I got this problem while using the board in an webradio application ( Edzelf / ESP32-Radio ). It works fine as long as I do not try to print text information, e.g. the VS1053 decoder board works properly, the web-based interface is up and running and the diplay is recognized and draws the lines defining the segments correctly. Means the radio station plays and I can see the volume bar, but no text is shown.

The display-related definitions are given below:

#include <TFT_eSPI.h>

// Color definitions for the screen 
#define BLACK   TFT_BLACK
#define BLUE    TFT_BLUE
#define RED     TFT_RED
#define GREEN   TFT_GREEN
#define CYAN    TFT_CYAN
#define MAGENTA TFT_MAGENTA
#define YELLOW  TFT_YELLOW
#define WHITE   TFT_WHITE

TFT_eSPI* tft = NULL ;

// Various macro's to mimic the display functions
#define dsp_setRotation()       tft->setRotation ( 1 )             // Use landscape format (3 for upside down)
#define dsp_fillRect(a,b,c,d,e) tft->fillRect ( a, b, c, d, e )    // Fill a rectange
#define dsp_print(a)            tft->print ( a )                   // Print a string 
#define dsp_println(b)          tft->println ( b )                 // Print a string followed by newline 
#define dsp_setTextSize(a)      tft->setTextSize( a )              // Set the text size
#define dsp_setTextColor(a)     tft->setTextColor(a)             // Set the text color
#define dsp_setCursor(a,b)      tft->setCursor ( a, b)             // Position the cursor
#define dsp_erase()             tft->fillScreen ( RED )            // Clear the screen
#define dsp_getwidth()          tft->width()                               // Get width of screen
#define dsp_getheight()         tft->height()                                // Get height of screen
#define dsp_update()                                               // Updates to the physical screen
#define dsp_usesSPI()           true                               // Does use SPI

bool dsp_begin()
{
  tft = new TFT_eSPI() ; 
  tft->init() ;
  return ( tft != NULL ) ;
  // return false ;
}

#define TFTSECS 4
scrseg_struct     tftdata[TFTSECS] =                        // Screen divided in 3 segments + 1 overlay
{                                                           // One text line is 8 pixels
  { false, WHITE,   0,  8, "" },                            // 1 top line
  { false, CYAN,   20, 64, "" },                            // 8 lines in the middle
  { false, YELLOW, 90, 32, "" },                            // 4 lines at the bottom
  { false, GREEN,  90, 32, "" }                             // 4 lines at the bottom for rotary encoder
} ;

The problem pops up if I added the definitions for dsp_print(a); dsp_println(b) as already shown above (to get all the informations on the station etc.). If I try to activate it, the whole thing fails and the messages are:

D: Start display
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x400df880  PS      : 0x00060f30  A0      : 0x80158f24  A1      : 0x3ffb1eb0  
A2      : 0x3ffb8590  A3      : 0x00000053  A4      : 0x0000001f  A5      : 0x00000053  
A6      : 0x3ff65090  A7      : 0x3ff6508c  A8      : 0xfefefefe  A9      : 0x3ffb1e90  
A10     : 0x00000053  A11     : 0x00000053  A12     : 0x3ffb86e8  A13     : 0x00000000  
A14     : 0x00000000  A15     : 0x3ffb0060  SAR     : 0x0000001c  EXCCAUSE: 0x0000001c  
EXCVADDR: 0xfefeff08  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xfffffffa  

Backtrace: 0x400df880:0x3ffb1eb0 0x40158f21:0x3ffb1ee0 0x400e2036:0x3ffb1f00 0x400e2119:0x3ffb1f20 0x400d8bdd:0x3ffb1f40 0x400e2fef:0x3ffb1fb0 0x4008a951:0x3ffb1fd0

Rebooting...

The exception decoder then yields:

PC: 0x400df880: TFT_eSPI::write(unsigned char) at D:\Broesel\Arduino\sketches\libraries\TFT_eSPI\TFT_eSPI.cpp line 3615
EXCVADDR: 0xfefeff08

Decoding stack results
0x400df880: TFT_eSPI::write(unsigned char) at D:\Broesel\Arduino\sketches\libraries\TFT_eSPI\TFT_eSPI.cpp line 3615
0x40158f21: Print::write(unsigned char const*, unsigned int) at C:\Users\Broesel\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32\Print.cpp line 42
0x400e2036: Print::write(char const*) at C:\Users\Broesel\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32/Print.h line 66
0x400e2119: Print::print(char const*) at C:\Users\Broesel\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32\Print.cpp line 89
0x400d8bdd: setup() at D:\Broesel\Arduino\sketches\ESP32-Radio-TTGOv2\Esp32_radio/Esp32_radio.ino line 3364
0x400e2fef: loopTask(void*) at C:\Users\Broesel\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32\main.cpp line 14
0x4008a951: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

With my limited knowledge, the problem is triggered when the display is initialized and the first time the dsp_print() is called (last line is Esp32_radio.ino line 3364):

dbgprint ( "Start display" ) ;
    if ( dsp_begin() )                                   // Init display
    {
      dsp_setRotation() ;                                // Use landscape format
      dsp_erase() ;                                      // Clear screen
      dsp_setTextSize ( 2 ) ;                            // Small character font
      dsp_setTextColor ( WHITE ) ;                       // Info in white
      dsp_setCursor ( 0, 0 ) ;                           // Top of screen
      dsp_print ( "Starting..." "\n" "Version:" ) ;

As the Esp32_radio code works with anumber of different displays that are already supported, I assume that the error is likely somewhere in the TFT_eSPI.cpp. The referenced line 3615 is: if (uniCode > pgm_read_word(&gfxFont->last )) return 1;

as part of the code loading custom fonts:

#ifdef LOAD_GFXFF
  } // Custom GFX font
  else {
    if(utf8 == '\n') {
      cursor_x  = 0;
      cursor_y += (int16_t)textsize *
                  (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
    }
    else {
      if (uniCode > pgm_read_word(&gfxFont->last )) return 1;
      if (uniCode < pgm_read_word(&gfxFont->first)) return 1;

      uint16_t   c2    = uniCode - pgm_read_word(&gfxFont->first);
      GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
      uint8_t   w     = pgm_read_byte(&glyph->width),
                h     = pgm_read_byte(&glyph->height);
      if((w > 0) && (h > 0)) { // Is there an associated bitmap?
        int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset);
        if(textwrapX && ((cursor_x + textsize * (xo + w)) > this->width())) {
          // Drawing character would go off right edge; wrap to new line
          cursor_x  = 0;
          cursor_y += (int16_t)textsize *
                      (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
        }
        if (textwrapY && (cursor_y >= (int32_t)this->height())) cursor_y = 0;
        drawChar(cursor_x, cursor_y, uniCode, textcolor, textbgcolor, textsize);
      }
      cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize;
    }
  }
#endif // LOAD_GFXFF

If there is any helpful hint what might trigger this issue, I would be very grateful.

Rhombur commented 3 years ago

One new finding: the issue can be avoided by an "adaption" to the display setup file (Setup25_TTGO_T_Display.h). Here, line 30 needs to be dissabled: // #define LOAD_GFXFF Don't know if this line is there by accident or if there is a mistake in the code that tries to load it.