lvgl / lv_binding_micropython

LVGL binding for MicroPython
MIT License
259 stars 166 forks source link

Support ESP32-S2, ESP32-C3, ESP32-S3 #227

Open amirgon opened 2 years ago

amirgon commented 2 years ago

Micropython already supports ESP32, ESP32-S2, ESP32-C3, ESP32-S3. However lv_micropython only supports ESP32 today.

The goal is to add support for ESP32-S2, ESP32-C3, ESP32-S3 in lv_binding_micropython and lv_micropython.

This includes:

Related issues:


This is a sponsored issue, meaning that if someone implements it he or she gets a payment from the Accumulated donations of LVGL. Learn more HERE.

We can give 100 USD for fully implementing this.

CC: @kisvegabor @embeddedt

kdschlosser commented 1 year ago

already did that using gen_mpy. it builds it automatically. I don't have a screen to test with tho so I never brought it up. All I know is it compiles properly.

What I did exposes all of the esp_lcd component. i8080, spi, i2s and rgb.

I also exposed the esp_hid component, usb component and twai

fvstory commented 1 year ago

@kdschlosser I have test my work.perfect run,but if use the gen_mpy,you also need to write the c to link the flush_ready,is not ok from MP,I did try

kdschlosser commented 1 year ago

it would be from MP if you use @micropython.viper. You just need to know how to declare the types. I would set up a python callback for the flush and then pass only the needed parameters to a function that uses viper. The viper code emitter turns the function into machine instructions.

You can also set it up so yo write the flush function in C code and pass any additional commands that need to be done while it is flushing as parameters to that callback. Just have a python intermediate callback that calls the function written in c code.

halfred commented 1 year ago

I bought this : https://www.makerfabs.com/sunton-esp32-s3-4-3-inch-ips-with-touch.html Hoping to program it in micropython and with LVGL Unfortunately, after fighting for hours, I realised thank's to this ticket that the micropython port of LVGL doesn't support the ESP32S3 yet

I have no idea how to do it, otherwise I would have help :/

kdschlosser commented 1 year ago

you can give this a go. it is an altered version of the binding to work on the S3.

https://github.com/kdschlosser/lv_binding_micropython/tree/esp32-s-c-h_support

HonestQiao commented 1 year ago

I have an esp32-s3-box-lite with a product introduction at https://github.com/espressif/esp-box .

Refer to https://github.com/imliubo/lv_binding_micropython/tree/dev_esp32_s3, modified source code of lv_micropython , and then compiled it as GENERIC_S3_SPIRAM_OCT .

Now I can run the lvgl program. image

But there are still some problems:

  1. Sometimes when starting up, it will freeze for a while, and then continue to run.
  2. After running the lvgl program once, stop the program, and then run it again, the following error will appear:
    Traceback (most recent call last):
    File "<stdin>", line 29, in <module>
    File "ili9XXX.py", line 586, in __init__
    File "ili9XXX.py", line 161, in __init__
    File "ili9XXX.py", line 240, in disp_spi_init
    RuntimeError: Failed initializing SPI bus
             #File "ili9XXX.py", line 240, in disp_spi_init
            if ret != 0: raise RuntimeError("Failed initializing SPI bus")

    Even if i use machine.reset() it doesn't work unless I press the Reset button. The return code of esp.spi_bus_initialize is ESP_ERR_INVALID_STATE(259).

  3. Sometimes , the error of 2 is:
    Traceback (most recent call last):
    File "<stdin>", line 28, in <module>
    File "ili9XXX.py", line 802, in __init__
    File "ili9XXX.py", line 159, in __init__
    RuntimeError: Not enough DMA-able memory to allocate display buffer
HonestQiao commented 1 year ago

I have an esp32-s3-box-lite with a product introduction at https://github.com/espressif/esp-box .

Refer to https://github.com/imliubo/lv_binding_micropython/tree/dev_esp32_s3, modified source code of lv_micropython , and then compiled it as GENERIC_S3_SPIRAM_OCT .

Now I can run the lvgl program. image

But there are still some problems:

  1. Sometimes when starting up, it will freeze for a while, and then continue to run.
  2. After running the lvgl program once, stop the program, and then run it again, the following error will appear:
Traceback (most recent call last):
  File "<stdin>", line 29, in <module>
  File "ili9XXX.py", line 586, in __init__
  File "ili9XXX.py", line 161, in __init__
  File "ili9XXX.py", line 240, in disp_spi_init
RuntimeError: Failed initializing SPI bus
           #File "ili9XXX.py", line 240, in disp_spi_init
          if ret != 0: raise RuntimeError("Failed initializing SPI bus")

Even if i use machine.reset() it doesn't work unless I press the Reset button. The return code of esp.spi_bus_initialize is ESP_ERR_INVALID_STATE(259). 3. Sometimes , the error of 2 is:

Traceback (most recent call last):
  File "<stdin>", line 28, in <module>
  File "ili9XXX.py", line 802, in __init__
  File "ili9XXX.py", line 159, in __init__
RuntimeError: Not enough DMA-able memory to allocate display buffer

import machine;machine.reset() can't release SPI1. import machine;machine.WDT(timeout=1000) can release SPI1.

kdschlosser commented 1 year ago

OK where you are having an issue... The ili9XXX display driver that in the binding doesn't have any mechanism in place to specify where the DMA is allocated from. There are several different version of the S3 and without knowing the actual chip model there is no way to know if you have a version that has SPIRAM that has DMA ability.. The absolute very first thing you need to do when the program starts is get that display initialized. This needs to be done first because there is not all that much DMA memory available for the built in RAM. Ideally if possible you want the buffers to get initialized in the built in RAM instead of the SPIRAM. The SPIRAM is slow in comparison to the built in ram even with it being octal SPI.

One of the things you can do is pass factor=8 to the driver. This will decrease the size of the frame buffers, Also make sure to specify double_buffer=True as well.

If you perform a reset this does not flush all of the memory and is the reason why you are getting the SPI error. Pushing the reset button does flush the memory. If you shrink the frame buffer size and get the display initialized first thing those errors will not show up.

HonestQiao commented 1 year ago

Specification

I use the following parameters to configure the display:

#init display
try:
    disp = st7789(
            mhz=4, 
            miso=TFT_MISO,
            mosi=TFT_MOSI,
            clk=TFT_SCK,
            cs=TFT_CS,
            dc=TFT_DC,
            rst=TFT_RST,
            backlight=-1,
            power=-1,
            width=320,
            height=240,
            start_x=0,
            start_y=0,                
            rot=ILI9341.REVERSE_LANDSCAPE,
            factor=10,
            double_buffer=True
            )
except Exception as e:
    print("Error:", e)
    machine.WDT(timeout=1000) # I added this to automatically restart so I can continue testing

The following parameters will still cause SPI initialization failure:

factor=8, double_buffer=True
# OR
factor=10, double_buffer=True

The error:

Double buffer
esp.spi_bus_initialize ret:  259
Error: Failed initializing SPI bus
kdschlosser commented 1 year ago

what version of LVGL are you using?

 disp = st7789(
            mhz=4, < this is wrong. should be set to 40, maybe even 80
            miso=TFT_MISO,
            mosi=TFT_MOSI,
            clk=TFT_SCK,
            cs=TFT_CS,
            dc=TFT_DC,
            rst=TFT_RST,
            backlight=-1,
            power=-1,
            width=320,
            height=240,
            start_x=0,
            start_y=0,                
            rot=ILI9341.REVERSE_LANDSCAPE, < where is this coming from?
            factor=10,  <-- I believe this has to be the result of 2 ^n. so 2^2 (4), 2^3(8), 2^4 (16)... etc
            double_buffer=True
            )

You should have your spihost set to VSPI_HOST. the st7789 class defaults to HSPI_HOST. you may also need to use the actual pins defined for that host.

I just double checked and it is connected to SPI3_HOST which is VSPI_HOST

byte order is BGR

color format is RGB565

clk is GPIO7 mosi is GPIO6 miso is -1

dc is GPIO4 cs is GPIO 5

the mhz is 40 spimode is 0

rst is GPIO48

They are doing almost exactly the same thing that is being done in the binding. I think you might be having an issue because of either one of the above things not being correct or the version of the binding you are using has issues in it.

kdschlosser commented 1 year ago

I can tell you that for the size display you can use a factor of 8 and it will work properly so long as you initialize the display driver first and foremost.

kdschlosser commented 1 year ago

from ili9XXX import LANDSCAPE, st7789
import espidf as esp
import lvgl as lv

disp = st7789(
            mhz=40
            miso=-1,
            mosi=6,
            clk=7,
            cs=5,
            dc=4,
            rst=48,
            backlight=45,
            power=-1,
            width=320,
            height=240,
            start_x=0,
            start_y=0,                
            rot=LANDSCAPE,
            spihost=esp.VSPI_HOST,
            spimode=0,
            factor=8,
            double_buffer=True,
            color_format=lv.COLOR_FORMAT.NATIVE_REVERSED
            )

this is what I came up with.

HonestQiao commented 1 year ago
import espidf as esp
import lvgl as lv
import ili9XXX as ILI9341
from ili9XXX import st7789
import machine
import time

TFT_MISO = -1
TFT_MOSI = 6
TFT_SCK  = 7
TFT_RST = 48
TFT_CS  = 5
TFT_DC  = 4
TFT_BL  = 45

#gc.collect()
#print(gc.mem_free())

lv_ver = "%d.%d.%d-%s" % (lv.version_major(), lv.version_minor(), lv.version_patch(), lv.version_info())
print(lv_ver)

# enable backlight
l=Pin(TFT_BL,Pin.OUT)
l.value(0)

lv.init()

#init display
try:
    disp = st7789(
            mhz=40, 
            miso=TFT_MISO,
            mosi=TFT_MOSI,
            clk=TFT_SCK,
            cs=TFT_CS,
            dc=TFT_DC,
            rst=TFT_RST,
            backlight=-1,
            power=-1,
            width=320,
            height=240,
            start_x=0,
            start_y=0,                
            rot=ILI9341.REVERSE_LANDSCAPE,
            factor=8,
            double_buffer=True
            )
except Exception as e:
    print("Error:", e)
    machine.WDT(timeout=1000)
    time.sleep(1)

My lcd already works fine, except for the problem I mentioned above.

    disp = st7789(
            mhz=40, 
            miso=TFT_MISO,
            mosi=TFT_MOSI,
            clk=TFT_SCK,
            cs=TFT_CS,
            dc=TFT_DC,
            rst=TFT_RST,
            backlight=-1,
            power=-1,
            width=320,
            height=240,
            start_x=0,
            start_y=0,                
            rot=ILI9341.REVERSE_LANDSCAPE,
            factor=8,
            double_buffer=True,
            spihost=esp.VSPI_HOST,
            spimode=0,
            color_format=lv.COLOR_FORMAT.NATIVE_REVERSED
            )

I use the above configuration, and when I run the code for the second time, an error still occurs: Error: Failed initializing SPI bus

So I use the following code to reset automatically:

try:
    ......
except Exception as e:
    print("Error:", e)
    machine.WDT(timeout=1000)
    time.sleep(1)
HonestQiao commented 1 year ago
color_format=lv.COLOR_FORMAT.NATIVE_REVERSED

On my box's lcd, the colors appear fine. The color of the picture above is not normal, just because I took the photo at night.

kdschlosser commented 1 year ago

I asked about the ILI9341.REVERSE_LANDSCAPE because i did not know where it was coming from due to the name that was being used at the front of it.

and that is the only code that is running, there is nothing that gets run before it?

so when you plug the ESP32 in and upload the main.py file to it and then press the reset button you get the SPI initialization failure?

You should not be using the watchdog timer in the manner you are using it.. The WDT also restarts the ESP it does not reset it. restarting leaves a lot of the thing in memory in tact where as a reset is a full reboot which clears everything. Reset is the same as pressing the reset button.

machine.reset()

I have had this issue on occasion if my program went all kinds of sideways and the MCU restarted for whatever reason. a simple press of the reset button usually fixed it. Where I would run into this issue is when I connected to the ESP over serial. sometimes it would reset and sometimes it would restart it was a crap shoot when it would do it. I would simply press the reset button if it happened and it would then load without any issue.

I think the DMA memory has something to do with it and transactions not getting cleared out properly when a restart occurs. There is no way to handle that other then making sure you clear out the transactions before restarting which is not going to happen because you are not really given any notification of when a watch dog timer fails and forces the restart.

kdschlosser commented 1 year ago

Oh also to let you know. I have been working on a CPython binding and the binding is going to have the MicroPython API available for it. Faster development when you don't have to keep on flashing code changes over and over again. runs right on the desktop (Windows Linux or OSX). I am still hammering out some issues with the MicroPython API portion of it, the C API portion works. it's still an alpha version and it does have some glitches in it but it mostly works without any issues.

HonestQiao commented 1 year ago
import ili9XXX as ILI9341

ILI9341.REVERSE_LANDSCAPE is same to ili9XXX.REVERSE_LANDSCAPE.

PORTRAIT = const(-1)
LANDSCAPE = const(-2)
REVERSE_PORTRAIT = const(-3)
REVERSE_LANDSCAPE = const(-4)

If I don't use this parameter, then my screen display is upside down.

About spi error, my test steps:

  1. Connect esp32-s3-box-lite to my computer with data cable, and then in thonny, run the program which contains lvgl, it can run correctly.
  2. In thonny, click stop button to stop the program.
  3. Click run button, run the program again, an error throws: Error: Failed initializing SPI bus
  4. use import machine; machine.reset(), run the program again, the same error throws: Error: Failed initializing SPI bus

How can it work again?

  1. reconnect it to my computer
  2. or push reset button
  3. or import machine;machine.WDT(timeout=1000);
kdschlosser commented 1 year ago

In thonny, click stop button to stop the program.

have you tried using a serial monitor and not thonny. Thonny connects to the ESP is an odd manner. I would try it just using a serial monitor like Putty.

HonestQiao commented 1 year ago

In thonny, click stop button to stop the program.

have you tried using a serial monitor and not thonny. Thonny connects to the ESP is an odd manner. I would try it just using a serial monitor like Putty.

I didn't expect that thonny would have this problem.

I tested with minicom/picocom:

everything looks good.

kdschlosser commented 1 year ago

Thonny has a weird way of making the connection to MIcroPython. I know this because I had an issue with it as well. specifically when I changed the bitrate of the serial port and setting it to match in Thonny had to be done at the code level and it took me some time to locate where to change it.

I don't know if you know how to change the bitrate of the repl uart in MicroPython or not. I set the port to 921600 bps instead of 115200. I do this to upload scripts to it. I use ampy which I have modified so it doesn't get any errors. It creates an identical directory structure as what is fed into it and it checks any file that is not a python source file to see if it needs to be updated if it already exists.

I have come across the same issue as you when using ampy, sometimes the board doesn't properly reset and I need to manually press the button on the ESP32 after the upload of files. Not a big deal. I have not screwed around with the serial port and setting the RTS / CTS states on the serial port to get the ESP32 to reset. I am sure if I took a look at it I could fix it. I think it's RTS/CTS it could be RTS and DTR I would have to check the schematics for the ESP32 S3 devkit. I don't remember off the top of my head.

I wrote a binding to a kernel mode driver for Windows that would make the ESP32 look like a removable drive to Windows. Never finished up working with that because aat the time the ability to set the speed of UART0 in MicroPython on the ESP32 could not be done.

HonestQiao commented 1 year ago

I wrote a binding to a kernel mode driver for Windows that would make the ESP32 look like a removable drive to Windows. Never finished up working with that because aat the time the ability to set the speed of UART0 in MicroPython on the ESP32 could not be done.

Like tinyuf2?

kdschlosser commented 1 year ago

No. This doesn't get flashed to the MCU. It gets run on the PC connected to the ESP. The connection can be over WiFi too. It uses the repl to do the transfers. If the connection is over the USB you can change the bitrate of UART0 to close to a megabit which speeds things up quite a bit.

kdschlosser commented 1 year ago

I put some work into it again today and got it working doing a simple mirror of a local folder. It should be fairly simple to get it working with MicroPython. Currently it is only going to work for Windows.

pak-man commented 1 year ago

Hello all, I would like to tackle the problem "running lv_micropython on recent ESP32 hardware" by having lvgl run as user C module (from what I understood it seems the most future-proof and MCU-agnostic way to do).

I´ve read all your comments and remarks here, but i lack somehow a clear roadmap to achieve it. And for sure i will hit here or there the elastic wall of my own knowledge about C or Micropython, which is indeed to be happily challenged.

amirgon commented 1 year ago

Hi @pak-man,

Running LVGL as a user C module does not automatically solve the problem of "running lv_micropython on recent ESP32 hardware". That's mostly because the challenge is fixing display drivers and ESP-IDF differences.

If you look at https://github.com/lvgl/lv_binding_micropython/pull/243, which is a PR by @imliubo for supporting esp32-s3, you'll notice most of the changes there are related to ESP-IDF and driver compatibility.
Unfortunately that PR seems abandoned, I believe it requires relatively small additional effort to fix and test it before it can be merged. Personally, I'm currently not using esp32-s3 so I'm waiting for some volunteer to step in and complete this work.

There are also some private forks you can try (by @kdschlosser for example), but I'd rather see this merged upstream and maintained in a single location, instead of scattered around GitHub.

If there are any volunteers, I'll be happy to review PRs for "running lv_micropython on recent ESP32 hardware", but I cannot test it on my side for now so someone else would need to actively push this effort.

Regardless, if you are still interested in running LVGL as an external user C module, there's an open PR (https://github.com/lvgl/lv_binding_micropython/pull/242) which is waiting for aligning to Micropython v1.20 (https://github.com/lvgl/lv_micropython/pull/65) which I'm actively working on.
But as said, I don't think this will help achieving your goal of "running lv_micropython on recent ESP32 hardware".

pak-man commented 1 year ago

Thank you for the hints, I will likely start by updating #243 for a recent ESP-IDF version. But I´m not sure about putting efforts into supporting a "old" (v4.4) ESP-IDF release that will be abandoned in 2024 https://github.com/micropython/micropython/issues/11078#top , maybe following micropython efforts in supporting esp-idf v5.x would be wiser.

Concerning the display drivers: there are a lot of display drivers around, also several display drivers for the same chipsets, sometimes C and also micropython.

I believe there is a need for a clean C display driver stub with lvgl hooks for micropython, along with -most important- a clear document describing generally how displays work (spi vs i2c protocol, bus speed, signals like reset, backlight, d/c, and concepts like double buffering, RGB/BGR.. encoding) and some guidelines with a hands-on example how to cleanly implement a new driver:

this would make so much easier the writing of new drivers (and a cleaner implementation of the existing ones) while providing a consistent micropython and LVGL integration. A bit like what circuitpython does - but i personally dislike the whole circuitpython fork precisely because of all the forced dependencies to a whole lot of circuitpython libraries .

Concerning ESP32 newest chips: If anybody want to join me in the effort, like @kdschlosser , I would consider sending boards free of charge if it can accelerate the process. I see that there is a program to reward developers, but it does not seem to get much traction, maybe because the people who would consider helping don´t have the right hardware on hand at first. I personally have a wide range of hardware available (most ESP32 version, RP2, STM32, as well as all supported or partially supported TFT displays in various resolutions with or without touchscreen...)

halfred commented 1 year ago

I tried to understand how to work with the custom bindings (kdschlosser or imliubo) for the S3, but I failed... And I don't know why :/

Here is my complete procedure:

Everything works fine, until I monitor the serial of the ESP The error that I got at this point is:

ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x10 (RTCWDT_RTC_RST),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fce3808,len:0xf34 load:0x403c9700,len:0xc44 load:0x00000000,len:0x0 Checksum failure. Calculated 0x57 stored 0x00 ets_main.c 329

Could anyone please help me ?

pak-man commented 1 year ago

Sometimes a make -C ports/esp32 (...) erase helps, did you try ?

amirgon commented 1 year ago

I believe there is a need for a clean C display driver stub with lvgl hooks for micropython, along with -most important- a clear document describing generally how displays work

In the long term, I think the goal is to have drivers part of LVGL and not part of the bindings.

It makes sense to maintain all LVGL drivers in one place and use them on both C code and Micropython (or any other language with LVGL bindings for that matter).
Some work in that direction has already began: https://github.com/lvgl/lvgl/issues/4011, https://github.com/lvgl/lvgl/issues/2720 and Linux SDL/FB drivers are already part of LVGL and removed from the Micropython bindings.

@kisvegabor Could you comment on the timeline for pushing some display controller drivers (such as ILI9341) to LVGL?

I think that eventually, in the long term, we will only keep the pure Micropython generic drivers which are not architecture specific. These are naturally slower but have the advantage that they should work on any Micropython port.

kdschlosser commented 1 year ago

you are not specifying the board.

make -c /ports/esp32 BOARD=GENERIC_S3_SPIRAM_OCT make -c /ports/esp32 BOARD=GENERIC_S3_SPIRAM or make -c /ports/esp32 BOARD=GENERIC_S3

kdschlosser commented 1 year ago

at this point in the game it is pointless to add or change anything specific for the ESP32 until the devs over at MicroPython finish up with getting the IDF 5.1 to work. The reason why is they are removing support for anything lower than IDF 5.1 so whatever code changes get made are going to end up having to get changed again.

If that PR that @amirgon made would get merged it would make it a whole lot easier for everyone because micropython would not have to be customized in the manner that is seen currently. There are a bunch of PRs that are not stale but are not getting merged and no real reasoning as to why they aren't It's quite frustrating because one of them is CAN interface for the ESP32. I have been waiting 2 years for that to get merged. I do not think that @amirgon 's PR will ever get merged either. it has been sitting there too long and I don't believe the author of MicroPython feels there is enough value in adding it because he is not importing modules have have as many QSTR's in it as this binding does.

kisvegabor commented 1 year ago

Could you comment on the timeline for pushing some display controller drivers (such as ILI9341) to LVGL?

I think in 1 month we can have ILI9341 integrated.

halfred commented 1 year ago

you are not specifying the board.

make -c /ports/esp32 BOARD=GENERIC_S3_SPIRAM_OCT make -c /ports/esp32 BOARD=GENERIC_S3_SPIRAM or make -c /ports/esp32 BOARD=GENERIC_S3

it makes sense... Thanks @kdschlosser

I don't know which one is my ESP32, so I tried with the 3 boards, but none is working :/

S3 : it crashes at the last compilation step : Error: app partition is too small for binary micropython.bin size 0x1fb650: Part 'factory' 0/0 @ 0x10000 size 0x1f0000 (overflow 0xb650) ninja: build stopped: subcommand failed.

S3_SPIRAM: Compilation and flash work, but when I screen the serial port : Build:Mar 27 2021 rst:0x7 (TG0WDT_SYS_RST),boot:0x8 (SPI_FAST_FLASH_BOOT) Saved PC:0x40043ac8 Invalid chip id. Expected 9 read 0. Bootloader for wrong chip? ets_main.c 329

S3_SPIRAM_OCT: doesn't start the cimpilation : CMake Error at CMakeLists.txt:18 (message): Invalid MICROPY_BOARD specified: GENERIC_S3_SPIRAM_OCT

kdschlosser commented 1 year ago

ok you need to know which board you have. how much RAM does your board have? if it has 8mb then you need to use the board that has OCT in the name. If it has anything above 1MB or ram then you need to use the board that has SPIRAM without the oct and all others get used for the last board.

The error you are getting at the last step is because the partition sizes are not set up properly. That is the one that is more than likely going to work once that issue is solved. If you give me a few hours I can make the changes needed to get you running using the one that failed at the last step.

pak-man commented 1 year ago

@kdschlosser: Maybe I´m wrong, but I thought quad and oct spiram was not related to the capacity SPI RAM chip, but spi parallel data transfer features. Quad-SPI aka QSPI having respectively four data lines https://embeddedinventor.com/quad-spi-everything-you-need-to-know/ and DDR-QSPI 8 data lines https://www.apmemory.com/wp-content/uploads/APM_PSRAM_OPI_Xccela-APS256XXN-OBRx-v1.0-PKG.pdf

And the relevant compilation flags are used to configure this: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/kconfig.html#config-esptoolpy-oct-flash

Also you write about "8mb" and "1MB" which is basically the same.

kdschlosser commented 1 year ago

It's for the SPI connected to the SPIRAM. 8mb memory uses OCTAL and 4 MB uses QUAD as does 2MB. There are low voltage variations of the MCU where that changes but they are not all that common.

kdschlosser commented 1 year ago

sorry for incorrect capitalization. my bad. I am talking about megabytes. I usually type in mbit for megabit so there is no confusion that way.

kdschlosser commented 1 year ago

image

as you can see the 8MB is OCTAL and the 2MB is QUAD.

halfred commented 1 year ago

Sorry but I'm not sure to understand... On my module is written ESP32-S3-WROOM-1 Does it mean that I should try to compile with BOARD=GENERIC_S3_SPIRAM_QUAD ? Because there is no such board description in the boards folder

kdschlosser commented 1 year ago

As I said. You have to know how much memory there is. If it has 8MB of RAM then you use the board that has OCTAL in it. If the board has 2 MB of RAM then you use the one that just says SPIRAM and if the board has less than 2MB of memory then you use the last one.

Here are the choices you have for the boards and the amount of memory you need to have in order to use that boaard

GENERIC_S3: < 2MB GENERIC_S3_SPIRAM: 2MB GENERIC_S3_SPIRAM_OCT: 8MB

calmera commented 1 year ago

I have been trying the last few days to get this thing compiled for an ESP32-S3, but it seems compilation keeps on failing on me. I'm not a c or cpp dev, but it seems something is off on the lv_bindings side since the error looks like pointing to something in there.

These are the steps I am executing (inside WSL, but don't think that matters):

The result of this can be found in this gist: https://gist.github.com/calmera/1b1217fa96f3c2ef855cf5f976d41a4a

I have no idea what is going on here, but it feels like something off with modrtch.c and some things it is expecting but can't find.

moefear85 commented 1 year ago

This issue is way too long to fully read & comprehend in human time, so I have to ask: Is the 100$ offer still up, and what exactly still needs to be done, given that it seems kdschlosser has already done all the heavy lifting? I'm currently having trouble getting lv_bindings to compile with micropython 1.21 & idf-5.0-release-branch. I'd like to go bump it to v5.2 even. Any financial motivation would be welcome, but not necessary. Currently I'm trying to compile for the esp32. Afterwards I'll work on the other variants.

kdschlosser commented 1 year ago

This no longer needs to be done because of MicroPython dropping support for all version of the IDF except for version 5 and newer.

what does need to be fixed and I am willing to give you 100 bucks to do it is to get LVGL to compile properly using MicroPython 1.21. The build system has been changed and now it will not compile.

kdschlosser commented 1 year ago

Compiling LVGL with Micropython for boards other than the ESP32 should be a non issue because LVGL is compiled as a user module. It would be nice if LVGL can be compiled as a user module for all boards and that is really the direction we are trying to go with it. only bus drivers would be supplied with the compilation and those would be compiled as a separate user module.

I have already written the bus drivers for the ESP32. need drivers written for the rest of the boards.

moefear85 commented 1 year ago

@kdschlosser so currently there are difficulties compiling lvgl with micropython as a user C module, if and only if the target is an esp32/s2/s3? Because I'm facing exactly that right now, and am working around the problem.

i didnt see your first post before. i'm working on it (v1.21.0) right now. i hope to have it finished in a few days

kdschlosser commented 1 year ago

If you separate the ESP_IDF specific stuff from the build I believe that you will have more success with getting it to compile properly as a user module. LVGL it self already compiles without any issues as a user module for other boards, it only has a problem on the ESP32. I think the goal is to compile the ESP specific stuff as a separate user module and remove as much as possible from the micropython build files. I already have the bus drivers compiling properly as as user module. just need to write the python display drivers which should be fairly simple to do.

moefear85 commented 1 year ago

I don't think the esp32 currently works for lv_binding_micropython, it only works for lv_micropython, w.r.t. esp-idf-v5.x. Is this correct? Right now, I've successfully managed to get lv_binding_micropython to compile for esp32 for micropython v1.22 preview & esp-idf-v5.0.x (release branch; later I intent to go to v5.2.x), but a simple test to display something to screen meditates at random moments, before the screen is done rendering. Here's a snapshot: PXL_20231118_150753945

Here's the output from the repl:

MicroPython v1.22.0-preview.65.gbb6d085ee.dirty on 2023-11-18; Generic ESP32 module with ESP32
Type "help()" for more information.
>>> import test
[Info]  (0.000, +0)  lv_init: begin     (in lv_obj.c line #122)
[Warn]  (0.000, +0)  lv_init: Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower  (in lv_obj.c line #206)
[Warn]  (0.000, +0)  lv_init: Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower   (in lv_obj.c line #210)
[Warn]  (0.000, +0)  lv_init: Style sanity checks are enabled that uses more RAM    (in lv_obj.c line #214)
Double buffer
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
ILI9341 initialization completed
Enable backlight
[Warn]  (0.000, +0)  lv_init: lv_init: already inited   (in lv_obj.c line #118)
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
[Info]  (0.000, +0)  lv_btn_create: begin   (in lv_btn.c line #49)
[Info]  (0.000, +0)  lv_label_create: begin     (in lv_label.c line #82)
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x400835ee  PS      : 0x00050731  A0      : 0x80084e29  A1      : 0x3ffc2210  
A2      : 0x00000040  A3      : 0x00018040  A4      : 0x000637ff  A5      : 0x3ffc21d0  
A6      : 0x00000000  A7      : 0x3ffdffa4  A8      : 0x3ffc21d4  A9      : 0x00000000  
A10     : 0x00000000  A11     : 0x3ffdfec8  A12     : 0x8023840c  A13     : 0x3ffc21b0  
A14     : 0x00000001  A15     : 0x00000001  SAR     : 0x0000001e  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x80084e35  LBEG    : 0x401ddc24  LEND    : 0x401ddc2d  LCOUNT  : 0x00000000  

Backtrace: 0x400835eb:0x3ffc2210 0x40084e26:0x3ffda500 0x400e9936:0x3ffda540 0x400e96fb:0x3ffda580 0x400e948d:0x3ffda5e0 0x400e90c0:0x3ffda610 0x40132019:0x3ffda660 0x40131ca7:0x3ffda6b0 0x401b8492:0x3ffda6f0 0x401b67fb:0x3ffda710 0x401b7da1:0x3ffda730 0x4019e80d:0x3ffda750 0x4019e8d1:0x3ffda770 0x40085e29:0x3ffda790 0x40197a9c:0x3ffda830 0x4019e80d:0x3ffda860 0x401ed80f:0x3ffda880 0x401ed861:0x3ffda8c0 0x4019e80d:0x3ffda8e0 0x4019e891:0x3ffda900 0x401f0444:0x3ffda930 0x4019f56d:0x3ffda9b0 0x401
b1dd0:0x3ffda9d0 0x401a67dd:0x3ffdaa00 0x40197991:0x3ffdaa20 0x4019e80d:0x3ffdaa40 0x40085d79:0x3ffdaa60 0x40197a9c:0x3ffdab00 0x4019e80d:0x3ffdab30 0x4019e878:0x3ffdab50 0x401de725:0x3ffdab90 0x401dea52:0x3ffdabc0 0x4019e94d:0x3ffdacb0 0x400860c6:0x3ffdacf0 0x40197a9c:0x3ffdad90 0x4019e80d:0x3ffdade0 0x4019e822:0x3ffdae00 0x401f332a:0x3ffdae20 0x401f366c:0x3ffdaeb0 0x401b1a94:0x3ffdaef0 0x4031ce76:0x3ffdaf20

ELF file SHA256: 2aaf5124b292e992

CPU halted.

... another test....

>>> import test
import test
[Info]  (0.000, +0)  lv_init: begin     (in lv_obj.c line #122)
[Warn]  (0.000, +0)  lv_init: Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower  (in lv_obj.c line #206)
[Warn]  (0.000, +0)  lv_init: Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower   (in lv_obj.c line #210)
[Warn]  (0.000, +0)  lv_init: Style sanity checks are enabled that uses more RAM    (in lv_obj.c line #214)
Double buffer
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
ILI9341 initialization completed
Enable backlight
[Warn]  (0.000, +0)  lv_init: lv_init: already inited   (in lv_obj.c line #118)
[Info]  (0.000, +0)  lv_obj_create: begin   (in lv_obj.c line #305)
[Info]  (0.040, +40)     lv_sysmon_create: begin    (in lv_sysmon.c line #75)
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x400835ee  PS      : 0x00050f31  A0      : 0x80084e29  A1      : 0x3ffc2210  
A2      : 0x00000040  A3      : 0x00018040  A4      : 0x000637ff  A5      : 0x3ffc21d0  
A6      : 0x00000000  A7      : 0x3ffdffa4  A8      : 0x3ffc21d4  A9      : 0x00000000  
A10     : 0x00000000  A11     : 0x3ffdfec8  A12     : 0x8023840c  A13     : 0x3ffc21b0  
A14     : 0x00000001  A15     : 0x00000001  SAR     : 0x0000001e  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x80084e35  LBEG    : 0x401ddc24  LEND    : 0x401ddc2d  LCOUNT  : 0x00000000  

Backtrace: 0x400835eb:0x3ffc2210 0x40084e26:0x3ffbc9f0 0x4017c34a:0x3ffbca10 0x4017d9eb:0x3ffbca30 0x4031da58:0x3ffbca50 0x4031ce76:0x3ffbca80

ELF file SHA256: 7142343a3d6a3660

CPU halted.

The test code is:

from ili9XXX import ili9341
import lvgl as lv
from espidf import HSPI_HOST,VSPI_HOST
from time import sleep

display=ili9341(miso=15, mosi=27, clk=26, cs=13, dc=14, rst=12, spihost=HSPI_HOST, mhz=20, factor=8, hybrid=False)
lv.init()

scr = lv.obj()
#btn = lv.btn(scr)
#btn.align_to(lv.scr_act(), lv.ALIGN.CENTER, 0, 0)
#label = lv.label(btn)
#label.set_text("Hello World!")
#lv.scr_load(scr)
sleep(5)

coredump.txt lv_conf.h.txt

The top #0 & #1 functions of the currently running task (mp_task), are always identical, and it is always mp_task that is crashing (is the last thread running at moment of crash). The PC address and the prohibited load address (VADDR) are always identical across crashes, although the length of the stack and the exact moment of the crash is non-deterministic. Also, at various moments, I've uncommented various lines in the test file. So once I even got the button with its label to show up. So its not any one specific line from the test file that is causing the crash. At certain times, even only lv.init() or just creating the display causes it to crash, at others, reaching lv.init() will complete without any errors, and return to repl without crashing.

Just wanted to ask if anyone has an idea off the top of their heads what is going on, to save me some time debugging. At first I thought it was a gc issue, but I've attached lv_conf.h and I'm definately sure this file and this file only is getting picked up. I even changed some defines to rule out kconfig getting chosen, and any changes to lv_conf.h are manifesting themselves correctly, such as turning logging on/off.

The execvaddr is obviously bogus, triggering the loadprohibited, because it is in another galaxy compared to the edge of the solar system of accessible/defined memory locations (that end somewhere around 0x50001FFF after RTC).

kdschlosser commented 1 year ago

As I had stated previously, strip all of the esp specific parts of the LVGL build out and build it as a user c module. Then we can add in the drivers. It would only take me 30 minutes to code a driver for the display you are using.

We don't know if it is something LVGL is doing that is causing the problem or something that the driver is doing.

Try eliminating making a driver. provide an empty flush callback and call lv.flush_ready(disp) from inside of the function. That way you are removing the driver from the equation. see if it still crashes. if it doesn't then we know where the problem is stemming from.

moefear85 commented 1 year ago

u still didnt answer the qjestion, and it has been over a year since this issue was opened, i think you would have finished the driver by now?

ill try empty flushing

Update: The crashing is sporadic, with something like a 50% chance. Hence it was possible to get a complete screen: PXL_20231118_204117401

More importantly, I found out the crashing only happens when hybrid=False. When hybrid=True, it works perfectly and robustly (hence I doubt its the garbage collector). Hence no need to try empty flushing. This is with latest mpy master (v1.22) & esp-idf release/v5.0.

LVGL is a child of lv_bindings, but lv_bindings is a separate user c module, not within micropython/lib anymore. However, some (not all), configuration settings are still in various makefiles within micropython. I'm working on moving those out. Once that is complete, everything is done, at least for the esp32.

I'll try then for s2/s3/c3. I have them lying around, but I need to break them out (which will take time, as I need to design the breakout pcbs, I don't want to waste chips doing things quick n' dirty). As for other screens besides the ili9341 & ssd1306, that might take a while, because I don't have the others, and will have to buy them. If I were to buy all of them, that alone would cost about 50€ and take about 2 weeks to arrive (through aliexpress).

kdschlosser commented 1 year ago

Again if you remove all code that gets generated in the cmake files that is not for LVGL you will no longer have an issue with the ESP32S3 and such as that is where the problems stem from. There is a different driver framework that we are going to be doing that will be a separate thing. Right now the gen_mpy script converts some of the ESP-IDF into Micropython C code and that is where the current compatibility issues stem from.