lovyan03 / LovyanGFX

SPI LCD graphics library for ESP32 (ESP-IDF/ArduinoESP32) / ESP8266 (ArduinoESP8266) / SAMD51(Seeed ArduinoSAMD51)
Other
1.12k stars 200 forks source link

sprite::createSprite() Guru meditation error with psram #126

Closed tobozo closed 3 years ago

tobozo commented 3 years ago

Hardware: LoLin D32Pro (with psram) + TFT-2.4 @320x240

Problem description:

sprite::createSprite() crashes when used in combination with psram.

Expected behaviour:

createSprite should return NULL when allocation failed

How to reproduce:

// width = 240, height = 320 (portrait mode)
TFT_eSprite *sprite = new TFT_eSprite( &tft );

// this triggers a guru mediation error
sprite->setPsram(true);
void * sptr = sprite->createSprite( tft.width(), tft.height() );

// this triggers a guru mediation error
sprite->setPsram(false);
void * sptr = sprite->createSprite( tft.width(), tft.height() );

// this triggers a guru mediation error
sprite->setPsram(true);
sprite->setColorDepth(8);
void * sptr = sprite->createSprite( tft.width(), tft.height() );

// this succeeds
sprite->setPsram(false);
sprite->setColorDepth(8);
void * sptr = sprite->createSprite( tft.width(), tft.height() );

Error message in the console:


Guru Meditation Error: Core  1 panic'ed (StoreProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x4008bf06  PS      : 0x00060533  A0      : 0x8008ddf6  A1      : 0x3ffb1e50  
A2      : 0xb3ff0706  A3      : 0x0000abab  A4      : 0xb33fffff  A5      : 0x00000001  
A6      : 0x00060520  A7      : 0x0000cdcd  A8      : 0x0000abab  A9      : 0x3ffb1e20  
A10     : 0x00004000  A11     : 0x00000000  A12     : 0x3ff65000  A13     : 0x3ff650c0  
A14     : 0xd941d941  A15     : 0xd941d941  SAR     : 0x00000012  EXCCAUSE: 0x0000001d  
EXCVADDR: 0xb3ff0706  LBEG    : 0x40088a24  LEND    : 0x40088a40  LCOUNT  : 0x00000000  

ELF file SHA256: 0000000000000000

Backtrace: 0x4008bf06:0x3ffb1e50 0x4008ddf3:0x3ffb1e80 0x4008e42d:0x3ffb1ea0 0x40081e11:0x3ffb1ec0 0x400dac8f:0x3ffb1ee0 0x400d376a:0x3ffb1f00 0x400d3a4d:0x3ffb1f30 0x400e59a2:0x3ffb1fb0 0x4008b162:0x3ffb1fd0

Decoded backtrace:

Decoding 12 results
0x4008bf06: uxPortCompareSet at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c line 4560
:  (inlined by) vPortCPUAcquireMutexIntsDisabledInternal at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/portmux_impl.inc.h line 86
:  (inlined by) vPortCPUAcquireMutexIntsDisabled at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/portmux_impl.h line 98
:  (inlined by) vTaskEnterCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c line 4201
0x40088a24: memcpy at /home/mak/e/p/newlib_old/newlib_xtensa-bin/newlib_xtensa-2.2.0/xtensa-esp32-elf/newlib/libc/machine/xtensa/../../../../.././newlib/libc/machine/xtensa/memcpy.S line 175
0x40088a40: memcpy at /home/mak/e/p/newlib_old/newlib_xtensa-bin/newlib_xtensa-2.2.0/xtensa-esp32-elf/newlib/libc/machine/xtensa/../../../../.././newlib/libc/machine/xtensa/memcpy.S line 197
0x4008bf06: uxPortCompareSet at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c line 4560
:  (inlined by) vPortCPUAcquireMutexIntsDisabledInternal at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/portmux_impl.inc.h line 86
:  (inlined by) vPortCPUAcquireMutexIntsDisabled at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/portmux_impl.h line 98
:  (inlined by) vTaskEnterCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c line 4201
0x4008ddf3: multi_heap_internal_lock at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap.c line 380
0x4008e42d: multi_heap_malloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c line 321
0x40081e11: heap_caps_malloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 232
0x400dac8f: lgfx::v1::Panel_Sprite::createSprite(int, int, lgfx::v1::color_conv_t*, bool) at /home/tobozo/Arduino/libraries/LovyanGFX/src/lgfx/v1/misc/colortype.hpp line 84
:  (inlined by) lgfx::v1::SpriteBuffer::reset(unsigned int, lgfx::v1::AllocationSource) at /home/tobozo/Arduino/libraries/LovyanGFX/src/lgfx/v1/misc/SpriteBuffer.hpp line 162
:  (inlined by) lgfx::v1::Panel_Sprite::createSprite(int, int, lgfx::v1::color_conv_t*, bool) at /home/tobozo/Arduino/libraries/LovyanGFX/src/lgfx/v1/LGFX_Sprite.cpp line 98
0x400d376a: lgfx::v1::LGFX_Sprite::createSprite(int, int) at /home/tobozo/Arduino/libraries/ESP32-USB-Soft-Host/src/ESP32-USBSoftHost.hpp line 192
:  (inlined by) setupUI() at /home/tobozo/Arduino/libraries/SID6581/examples/SidUSBSoftHost/C64_UI.h line 137
0x400d3a4d: setup() at /home/tobozo/Arduino/libraries/ESP32-USB-Soft-Host/src/ESP32-USBSoftHost.hpp line 192
0x400e59a2: loopTask(void*) at /home/tobozo/.arduino15/packages/esp32/hardware/esp32/1.0.6/cores/esp32/main.cpp line 18
0x4008b162: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 355 (discriminator 1)
lovyan03 commented 3 years ago

@tobozo Thanks for the report.

I was not able to reproduce the problem, but I updated the develop branch with a change to discard the sprites once when setPsram is changed.

Are there any other prerequisites to reproduce the problem? If you change the board type, will the problem go away?

tobozo commented 3 years ago

[edit] simplified POC code [edit2] : pinpointed the issue

static LGFX_Sprite *sprite = new LGFX_Sprite( &tft ); // no crash when using this
static TFT_eSprite *sprite = new TFT_eSprite( &tft ); // will crash on createSprite()

The problem seems to be isolated to LoLin D32 Pro + TFT-2.4. No other component is connected.

I can't reproduce this issue on M5Stack or Odroid-Go.

Updating the develop branch did not solve it,

Are there any other prerequisites to reproduce the problem?

I have reduced the crash code to this:

#include <ESP32-Chimera-Core.h>
#define tft M5.Lcd

class BLAH {
  public:
    BLAH(){
      if( !psramInit() ) {
        log_e("Failed to init psram, crash will probably occur");
      } else {
        log_d("Psram successfully detected");
      }
    };
    ~BLAH() { };
};

static BLAH bleb;

// static LGFX_Sprite *keyNoteSprite = new LGFX_Sprite( &tft ); // no crash when using this
static TFT_eSprite *keyNoteSprite = new TFT_eSprite( &tft );

void setup()
{
  M5.begin();
  void* sptr = keyNoteSprite->createSprite( tft.width(), tft.height() );
  if( !sptr )  {
    log_e("Can't create sprite, aborting");
    while(1) vTaskDelay(1);
  }
}

void loop()
{

}

... is premature psramInit() causing this ?

lovyan03 commented 3 years ago

The psramInit function seems to be called at startup in the initArduino function. I don't see any need to call it explicitly from user code. If you call it in the constructor of a static object, I think it is called before initArduino.

Therefore, this is sufficient to reproduce the problem.

#include <Arduino.h>
#include <esp_log.h>

class BLAH {
  public:
    BLAH(){
      if( !psramInit() ) {
        log_e("Failed to init psram, crash will probably occur");
      } else {
        log_d("Psram successfully detected");
      }
    };
    ~BLAH() { };
};

static BLAH bleb;

void setup()
{
  void* sptr = heap_caps_malloc(320*240*2, MALLOC_CAP_SPIRAM);
  if( !sptr )  {
    log_e("Can't heap_caps_malloc, aborting");
  }
  else
  {
    log_e("success !");
  }
}

void loop()
{
  vTaskDelay(1);
}
tobozo commented 3 years ago

ok I understand this is a bad practice causing that, I'm not sure why it only crashes with LoLin D32 Pro + TFT-2.4 though.

closing this issue as not a LGFX problem