kdschlosser / lvgl_micropython

LVGL module for MicroPython
MIT License
42 stars 10 forks source link

MemoryError during initialization of display driver on ESP32-S3 #66

Open tairabiteru opened 3 days ago

tairabiteru commented 3 days ago

Hello, I'm having an issue just trying to get a minimal example working. I'm using this, which has an ESP32-S3 onboard with 16 MB of flash and 2 MB of PSRAM. The display chip is a GC9A01 and it's got a CST816S capacitive touch screen too. (Though I'll look at getting that running later.) I compiled with the following command:

python3 make.py esp32 mpy_cross submodules clean BOARD=ESP32_GENERIC_S3 VARAINT=SPIRAM_OCT DISPLAY=gc9a01 LV_CFLAGS="-DLV_COLOR_DEPTH=16"

I've written a minimal example just trying to get a display object initialized to fool around with:

from machine import SPI, Pin
from micropython import const

import lcd_bus
import gc9a01
import lvgl

_WIDTH = const(240)
_HEIGHT = const(240)

# Refer to https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-1.28#Interface_Description
_SPI_HOST = const(2)
_SPI_SCK = const(10)
_SPI_MOSI = const(11)
_SPI_MISO = const(12)

_LCD_FREQ = const(400_000)
_LCD_DC = const(8)
_LCD_CS = const(9)
_LCD_RST = const(14)
_LCD_BACKLIGHT = const(2)

spi_bus = SPI(
    _SPI_HOST,
    _LCD_FREQ,
    mosi=_SPI_MOSI,
    miso=_SPI_MISO,
    sck=_SPI_SCK,
    cs=_LCD_CS
)

display_bus = lcd_bus.SPIBus(
    spi_bus=spi_bus,
    freq=_LCD_FREQ,
    dc=_LCD_DC,
    cs=_LCD_CS
)

display = gc9a01.GC9A01(
    data_bus=display_bus,
    display_width=_WIDTH,
    display_height=_HEIGHT,
    reset_pin=_LCD_RST,
    backlight_pin=_LCD_BACKLIGHT,
    color_space=lvgl.COLOR_FORMAT.RGB565,
)

However I get an error wherein it appears the library is attempting to allocate about a gigabyte of memory, heh:

Traceback (most recent call last):
  File "<stdin>", line 51, in <module>
  File "display_driver_framework.py", line 169, in __init__
MemoryError: memory allocation failed, allocating 1009131784 bytes

I wish I had that much to give it, but alas. Reading through what info I could find, I came upon #8 which seems similar, but comments suggest it should be fixed at this point in time. Any pointers are greatly appreciated!

kdschlosser commented 3 days ago

This is wrong....

python3 make.py esp32 mpy_cross submodules clean BOARD=ESP32_GENERIC_S3 VARAINT=SPIRAM_OCT DISPLAY=gc9a01 LV_CFLAGS="-DLV_COLOR_DEPTH=16"

it should be this...

python3 make.py esp32 mpy_cross submodules clean BOARD=ESP32_GENERIC_S3 VARAINT=SPIRAM DISPLAY=gc9a01 INDEV=cst816s --flash-size=16

and that should do ya.

You only have 2mb of PSRAM which means you do not have octal SPIRAM. octal refers to the number of SPI lanes attached to the ram, for the 2mb version of the MCU they only made a quad version. so only 4 lanes. This would be the reason why you are seeing the goofy allocation is because the MCU is not being booted correctly.

SPIRAM and PSRAM are one and the same thing.

kdschlosser commented 3 days ago

This is how the code should look.

from machine import SPI
from micropython import const

import lcd_bus

_WIDTH = const(240)
_HEIGHT = const(240)

# Refer to https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-1.28#Interface_Description
_SPI_HOST = const(2)
_SPI_SCK = const(10)
_SPI_MOSI = const(11)
_SPI_MISO = const(12)

_LCD_FREQ = const(80_000_000)
_LCD_DC = const(8)
_LCD_CS = const(9)
_LCD_RST = const(14)
_LCD_BACKLIGHT = const(2)

spi_bus = SPI(
    _SPI_HOST,
    _LCD_FREQ,
    mosi=_SPI_MOSI,
    miso=_SPI_MISO,
    sck=_SPI_SCK
)

display_bus = lcd_bus.SPIBus(
    spi_bus=spi_bus,
    freq=_LCD_FREQ,
    dc=_LCD_DC,
    cs=_LCD_CS
)
try:
    fb1 = display_bus.allocate_framebuffer(int(240 * 240 * 2 / 10), lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_SPIRAM)
except MemoryError:
    raise RuntimeError('Failing on first buffer')
try:
    fb2 = display_bus.allocate_framebuffer(int(240 * 240 * 2 / 10), lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_SPIRAM)
except MemoryError:
    raise RuntimeError('Failing on second buffer')

import gc9a01
import lvgl as lv

display = gc9a01.GC9A01(
    data_bus=display_bus,
    display_width=_WIDTH,
    display_height=_HEIGHT,
    frame_buffer1=fb1,
    frame_buffer2=fb2,
    reset_pin=_LCD_RST,
    backlight_pin=_LCD_BACKLIGHT,
    color_space=lv.COLOR_FORMAT.RGB565,
    rgb565_byte_swap=True
)
tairabiteru commented 2 days ago

Thanks for the quick response and for your help! I recompiled as you suggested, and tried running the code example you gave, but it unfortunately raises the RuntimeError for the first buffer. I tried to do a bit of experimentation to see if I can allocate any amount of memory, but even if I just run:

display_bus.allocate_framebuffer(8, lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_SPIRAM)

It still raises MemoryError: Unable to allocate frame buffer. I also tried setting frame_buffer1 and frame_buffer2 to None, but when I do that, it results in a core panic:

MPY version : a61c446-dirty on 2024-06-25
IDF version : 11eaf41b
Machine     : Generic ESP32S3 module with ESP32S3

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

Core  1 register dump:
PC      : 0x4207ebd4  PS      : 0x00060430  A0      : 0x8207e7be  A1      : 0x3fcbc4b0  
A2      : 0x3c262554  A3      : 0x00008b32  A4      : 0x3c262650  A5      : 0x00060a23  
A6      : 0x00000001  A7      : 0x3fcbc4b0  A8      : 0x00008d13  A9      : 0x3c262650  
A10     : 0x3c262650  A11     : 0x3c22dce4  A12     : 0x3c236d5c  A13     : 0x3c237a26  
A14     : 0x3c2623a4  A15     : 0x3fcbc480  SAR     : 0x00000020  EXCCAUSE: 0x0000001d  
EXCVADDR: 0x00008d13  LBEG    : 0x400570e8  LEND    : 0x400570f3  LCOUNT  : 0x00000000  

Backtrace: 0x4207ebd1:0x3fcbc4b0 0x4207e7bb:0x3fcbc4f0 0x4203a829:0x3fcbc530 0x42029962:0x3fcbc570 0x4200625d:0x3fcbc5b0 0x420c91b9:0x3fcbc5f0 0x420c9281:0x3fcbc610 0x403797ea:0x3fcbc630 0x420c2623:0x3fcbc6d0 0x420c91b9:0x3fcbc700 0x420c9281:0x3fcbc720 0x420c7ec8:0x3fcbc740 0x420c7cfd:0x3fcbc7a0 0x420c91b9:0x3fcbc7c0 0x420c9281:0x3fcbc7e0 0x403797ea:0x3fcbc800 0x420c2623:0x3fcbc8a0 0x420c91b9:0x3fcbc8d0 0x420c91ce:0x3fcbc8f0 0x420d561f:0x3fcbc910 0x420d5762:0x3fcbc9a0 0x420dcdfa:0x3fcbc9f0

ELF file SHA256: 5d0f452c4

Rebooting...
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x18 (SPI_FAST_FLASH_BOOT)
Saved PC:0x403829e2
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3820,len:0x105c
load:0x403c9700,len:0x4
load:0x403c9704,len:0xbd8
load:0x403cc700,len:0x2e30
entry 0x403c989c
kdschlosser commented 2 days ago

OK I want you to change the allocation to read...

try:
    fb1 = display_bus.allocate_framebuffer(int(240 * 240 * 2 / 10), lcd_bus.MEMORY_SPIRAM)
except MemoryError:
    raise RuntimeError('Failing on first buffer')
try:
    fb2 = display_bus.allocate_framebuffer(int(240 * 240 * 2 / 10), lcd_bus.MEMORY_SPIRAM)
except MemoryError:
    raise RuntimeError('Failing on second buffer')
kdschlosser commented 2 days ago

It also looks like you need to change the SPI host to 1. I came across an issue on GitHub that mentions using "HSPI" which is host 1 and the pins that are being used align with that.

tairabiteru commented 1 day ago

Thanks again! We seem to have some progress: I made the changes you suggested, and I was able to run the sample code successfully! I then went on to try to get the display to do stuff, tagging this onto the end of the code:

display.init()
display.set_backlight(100)

scr = lv.screen_active()
scr.set_style_bg_color(lv.color_hex(0xFF0000), 0)
lv.refr_now(lv.display_get_default())

import task_handler

th = task_handler.TaskHandler()

This resulted in another core panic:

MPY version : a61c446-dirty on 2024-06-25
IDF version : 11eaf41b
Machine     : Generic ESP32S3 module with ESP32S3

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

Core  1 register dump:
PC      : 0x00004c5a  PS      : 0x00060030  A0      : 0x8203a906  A1      : 0x3fcbc500  
A2      : 0x3c262670  A3      : 0x00000310  A4      : 0x00000002  A5      : 0x00000005  
A6      : 0x00000000  A7      : 0x3fcbc500  A8      : 0x8208eb9e  A9      : 0x3c2623b0  
A10     : 0x3c262670  A11     : 0x0000003c  A12     : 0x00000310  A13     : 0x00060223  
A14     : 0x00000001  A15     : 0x3fcbc4c0  SAR     : 0x0000001a  EXCCAUSE: 0x00000014  
EXCVADDR: 0x00004c58  LBEG    : 0x400570e8  LEND    : 0x400570f3  LCOUNT  : 0x00000000  

Backtrace: 0x00004c57:0x3fcbc500 0x4203a903:0x3fcbc530 0x42029962:0x3fcbc570 0x4200625d:0x3fcbc5b0 0x420c91b9:0x3fcbc5f0 0x420c9281:0x3fcbc610 0x403797ea:0x3fcbc630 0x420c2623:0x3fcbc6d0 0x420c91b9:0x3fcbc700 0x420c9281:0x3fcbc720 0x420c7ec8:0x3fcbc740 0x420c7cfd:0x3fcbc7a0 0x420c91b9:0x3fcbc7c0 0x420c9281:0x3fcbc7e0 0x403797ea:0x3fcbc800 0x420c2623:0x3fcbc8a0 0x420c91b9:0x3fcbc8d0 0x420c91ce:0x3fcbc8f0 0x420d561f:0x3fcbc910 0x420d5762:0x3fcbc9a0 0x420dcdfa:0x3fcbc9f0

ELF file SHA256: 5d0f452c4

Rebooting...
���ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x18 (SPI_FAST_FLASH_BOOT)
Saved PC:0x403829e2
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3820,len:0x105c
load:0x403c9700,len:0x4
load:0x403c9704,len:0xbd8
load:0x403cc700,len:0x2e30
entry 0x403c989c

What is odd is that I tried commenting lines out to see which one resulted in the panic, but after commenting out all of them after the sample code, it still panics. It's only when I comment out the entire driver constructor:

display = gc9a01.GC9A01(
    data_bus=display_bus,
    display_width=_WIDTH,
    display_height=_HEIGHT,
    frame_buffer1=fb1,
    frame_buffer2=fb2,
    reset_pin=_LCD_RST,
    backlight_pin=_LCD_BACKLIGHT,
    color_space=lv.COLOR_FORMAT.RGB565,
    rgb565_byte_swap=True
)

that it executes successfully. I ended up not being able to get the sample code to run again without panicking, so I decided to just re-flash, and was able to get it to run again. But the second I run the code I added, it panics, and then cannot be run successfully again without re-flashing.

kdschlosser commented 22 hours ago

what is the exact make and model of the ESP32-S3 you are using??

tairabiteru commented 13 hours ago

Based on the info I have on this page, it's an ESP32-S3R2. The flash memory also seems to not be apart of the chip itself, but is instead a separate chip on the circuit board. If you need the numbers off the chip itself, I can probably get you those too, though it'll be a minute because I don't have a magnifier that can resolve them. 😅

Out of curiosity, should I try decoding the stack trace, or do you already know what it says? I know Micropython has an option to compile with debugging enabled...