Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
7 tasks
amirgon opened this issue Jul 29, 2022 · 186 comments
Open
7 tasks

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

amirgon opened this issue Jul 29, 2022 · 186 comments
Labels
help wanted Extra attention is needed Sponsored Get payment for the implementation or fix

Comments

@amirgon
Copy link
Collaborator

amirgon commented Jul 29, 2022

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

@amirgon amirgon added help wanted Extra attention is needed Sponsored Get payment for the implementation or fix labels Jul 29, 2022
@424778940z
Copy link

Run in to this issue while I was looking for support for imxrt11xx platforms, since the main repo already supported them.

I would like to do it my own, but I could not find any detailed document for what exactly need to be done.

The readme of this repo is all about how to use this lvgl as a mp module, but mothing about porting.

Another article I could find is this https://blog.lvgl.io/2019-02-20/micropython-bindings
"Can I use LittlevGL binding on XXXX Micropython fork?
Probably yes!
You would need to add Micropython Binding for LittlevGL as a submodule in your fork, and make some small changes to the Makefile and mpconfigport.h in your port, but that’s about it.
For more details please have a look at the README."

The readme link is link to this repo's readme, bruh...
And about "make some small changes", sure, but what?
This is the same felling of MS error messages says "Something went wrong"
My honest suggestion, better use that $100 hire someone for documentation on and create some examples, that allows people who want help could help right the way, instad of read all sources and scripts to understand what to do first.

@amirgon
Copy link
Collaborator Author

amirgon commented Nov 19, 2022

@424778940z - See #242. That PR still needs some work, but when it's merged you will be able to add LVGL as a Micropython external C module, so porting to new architectures will be much easier.

This issue is about supporting ESP32-S2, ESP32-C3, ESP32-S3 because ESP ports have an extra complication where in addition to LVGL, the ESP BSP library API (ESP-IDF) is automatically converted too, so users can use it directly in Python code. (See Pure Micropython Display Driver in the blog).

You are right that the documentation focuses mostly on how to use the Micropython bindings. That's what interest most users. Advanced users who want to port to new architectures are welcome to diff micropython repo with lv_micropython and learn from the differences.

Remember that all the work, including the documentation, was done by volunteers on their spare time. So comparing this to Microsoft error message is not really fair.
If you are unhappy with the documentation or any other part, feel free to contribute by submitting a PR!

@ruihua-code
Copy link

I have been using esp32s3 for a whole day, and I keep reporting errors. It turns out that esp32s3 chip is not supported yet!!

@amirgon
Copy link
Collaborator Author

amirgon commented Nov 20, 2022

It turns out that esp32s3 chip is not supported yet!!

Correct.
See #243

@jd3096-mpy
Copy link

Waiting for Support ESP32-S2, ESP32-C3, ESP32-S3!
Lvgl docs has a lot of micropython examples codes, that's cool!
Especially ESP32-S3,many borads use it instead of ESP32, but they can't be used in micropython yet,
what's pity

@amirgon
Copy link
Collaborator Author

amirgon commented Dec 13, 2022

Especially ESP32-S3,many borads use it instead of ESP32, but they can't be used in micropython yet,

@jd3096-mpy see #243 - this adds ESP32-S3 support.
Could you try this PR on your side and see if it works for you?

@kdschlosser
Copy link
Contributor

I hope this gets added soon. I just wrote a python driver for the ili934 using an 8bit parallel interface. all of the work functions are decorated with micropython.viper so it should run with ample speed.

I am not able to test it because I only have s3's on hand at the moment.
It looks like it should work without an issue.

There are a couple of things that I have forced like setting the d0-d7 pins sequentially to GPIO pins that are also sequential and are all in the same GPIO register. Makes setting the state of the GPIOs easier to deal with. I still have to tie in the touch interface and this is going to be a tad more challenging to do because of the shared pins. I need to know more about the mechanics of how the input side of things works in lvgl to be able to do this. Or if a Python driver can be written for a touch interface. I don't know how the loop in lvgl works.

I am hoping that the use of viper code isn't going to mess with lvgl either. I am making an assumption that the viper code runs in the same manner as the native code and when the code is running things like ISRs don't break into the running code. The parallel interface should offer a HUGE speed increase because there is no need to swap the high and low bytes for the colors. I am also directly accessing the registers for the GPIOs through pointers and not using the built in machine.Pin class.

Maybe there is someone that would be willing to lend a hand with getting the touch interface working.

@kdschlosser
Copy link
Contributor

On a side note I will match the 100.00 already being given to get this done.

@kdschlosser
Copy link
Contributor

kdschlosser commented Dec 15, 2022

There is a choice to make here. Code can either be duplicated from the latest micropython esp32 port in the drivers for the esp32 port in lv_binding_micropython OR there can be a minimum micropython version that gets set into place for the esp32 port and includes from micropython can be made in the drivers for lvgl so the code isn't duplicated.

with the esp32s3 there is no adc_gpio_init function available and the way the adc blocks are handled is different. micropython has already sorted out the mechanics of this and created helper functions to deal with it. I think that setting a minimum version of micropython that lv_binding_micropython is allowed to use would the cleanest and also the easiest way to get it working with all of the different esp32 variants.

Most of the issues are differences in the macro names or some macros not being defined all together.

I corrected the errors in the gpio_to_adc array in the modrtch.c file using the following code

#define GPIO_TO_ADC_ELEMENT(adc, x) [x] = CONCAT3(CONCAT3(ADC, adc, _GPIO), x, _CHANNEL)
static const int gpio_to_adc[] = {
#if CONFIG_IDF_TARGET_ESP32
    GPIO_TO_ADC_ELEMENT(2, 0),
#elif CONFIG_IDF_TARGET_ESP32C3
    GPIO_TO_ADC_ELEMENT(1, 0),
#endif
#if CONFIG_IDF_TARGET_ESP32
    GPIO_TO_ADC_ELEMENT(2, 2),
    GPIO_TO_ADC_ELEMENT(2, 4),
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
    GPIO_TO_ADC_ELEMENT(1, 1),
    GPIO_TO_ADC_ELEMENT(1, 2),
    GPIO_TO_ADC_ELEMENT(1, 3),
    GPIO_TO_ADC_ELEMENT(1, 4),
#endif
#if CONFIG_IDF_TARGET_ESP32C3
    GPIO_TO_ADC_ELEMENT(2, 5),
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
    GPIO_TO_ADC_ELEMENT(1, 5),
#endif
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
    GPIO_TO_ADC_ELEMENT(1, 6),
    GPIO_TO_ADC_ELEMENT(1, 7),
    GPIO_TO_ADC_ELEMENT(1, 8),
    GPIO_TO_ADC_ELEMENT(1, 9),
    GPIO_TO_ADC_ELEMENT(1, 10),
    GPIO_TO_ADC_ELEMENT(2, 11),
#endif
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
    GPIO_TO_ADC_ELEMENT(2, 12),
    GPIO_TO_ADC_ELEMENT(2, 13),
    GPIO_TO_ADC_ELEMENT(2, 14),
    GPIO_TO_ADC_ELEMENT(2, 15),
#endif
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
    GPIO_TO_ADC_ELEMENT(2, 16),
    GPIO_TO_ADC_ELEMENT(2, 17),
    GPIO_TO_ADC_ELEMENT(2, 18),
    GPIO_TO_ADC_ELEMENT(2, 19),
    GPIO_TO_ADC_ELEMENT(2, 20),
#endif
#if CONFIG_IDF_TARGET_ESP32
    GPIO_TO_ADC_ELEMENT(2, 25),
    GPIO_TO_ADC_ELEMENT(2, 26),
    GPIO_TO_ADC_ELEMENT(2, 27),
    GPIO_TO_ADC_ELEMENT(1, 32),
    GPIO_TO_ADC_ELEMENT(1, 33),
    GPIO_TO_ADC_ELEMENT(1, 34),
    GPIO_TO_ADC_ELEMENT(1, 35),
    GPIO_TO_ADC_ELEMENT(1, 36),
    GPIO_TO_ADC_ELEMENT(1, 37),
    GPIO_TO_ADC_ELEMENT(1, 38),
    GPIO_TO_ADC_ELEMENT(1, 39)
#endif
};

and that has left me with the following compilation errors.

/home/***/lv_micropython/lib/lv_bindings/driver/esp32/modrtch.c: In function 'measure_axis':
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/modrtch.c:440:5: error: implicit declaration of function 'adc_gpio_init'; did you mean 'gpio_init'? [-Werror=implicit-function-declaration]
     adc_gpio_init(ADC_UNIT_1, adc_channel);
     ^~~~~~~~~~~~~
     gpio_init
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:85:18: error: implicit declaration of function 'I2S_TIMING_REG'; did you mean 'I2S_RX_TIMING_REG'? [-Werror=implicit-function-declaration]
     REG_SET_BIT( I2S_TIMING_REG(i2s_num), BIT(9));
                  ^~~~~~~~~~~~~~
/home/***/esp/components/soc/esp32s3/include/soc/soc.h:151:36: note: in definition of macro 'REG_SET_BIT'
             (*(volatile uint32_t*)(_r) |= (_b));                                                                       \
                                    ^~
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:86:18: error: implicit declaration of function 'I2S_CONF_REG'; did you mean 'I2S_TX_CONF_REG'? [-Werror=implicit-function-declaration]
     REG_SET_BIT( I2S_CONF_REG(i2s_num), I2S_RX_MSB_SHIFT);
                  ^~~~~~~~~~~~
/home/***/esp/components/soc/esp32s3/include/soc/soc.h:151:36: note: in definition of macro 'REG_SET_BIT'
             (*(volatile uint32_t*)(_r) |= (_b));                                                                       \
                                    ^~
In file included from /home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.c:7:
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h: At top level:
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:180:21: error: 'SPI_HOST' undeclared here (not in a function); did you mean 'SPI3_HOST'?
     ENUM_SPI_HOST = SPI_HOST,
                     ^~~~~~~~
                     SPI3_HOST
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:181:22: error: 'HSPI_HOST' undeclared here (not in a function); did you mean 'SPI3_HOST'?
     ENUM_HSPI_HOST = HSPI_HOST,
                      ^~~~~~~~~
                      SPI3_HOST
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:182:22: error: 'VSPI_HOST' undeclared here (not in a function); did you mean 'SPI3_HOST'?
     ENUM_VSPI_HOST = VSPI_HOST,
                      ^~~~~~~~~
                      SPI3_HOST

as you can see most of the issues at this point are simple macro naming problems. the only one that is a big hang up is the missing adc_gpio_init function and that function is not so simple to replicate what it does.

If a decision is made to use the already written functions to handle this issue in the esp32 port of micropython ass new esp32 boards get released changes will be made to micropython to handle those boards and little to no changes will need to be made in lv_binding_micropython to support the newer boards.

@kdschlosser
Copy link
Contributor

is there someone willing to give this a try?

decompress the attached file into driver/esp32

driver.esp32.zip

I was using this command to compile it

make -C ports/esp32 LV_CFLAGS="-DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP=1" BOARD=GENERIC_S3_SPIRAM IDF_TARGET=esp32s3

I am getting this error and it might be something in my setup and not with the code changes I have made.

/home/****/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_lldesc_num2link_mpobj+0xc): undefined reference to `lldesc_num2link'

I want to rule out the code changes I have made.

@kdschlosser
Copy link
Contributor

ok I figured out what functions need to be removed from lv_espidf.c so the compiling completes without error. I need to figure out how to keep gen_mpy from creating those functions. The majority of lv_espidf.c doesn't even need to be created. There is no reason to expose the entire espidf to the python interpreter. The availability of running viper code pretty much negates exposing it all together. Using viper code the GPIO registers can be accessed directly which would allow for fast updates to the GPIO pins.

I am not sure what other need there is to expose any of the espidf other than being able to manipulate the GPIOs

@kdschlosser
Copy link
Contributor

If anyone wants to give this a go to see if it works I would appreciate it.

It should compile without errors. I do not have an SPI display to test it with.

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

@jd3096-mpy
Copy link

If anyone wants to give this a go to see if it works I would appreciate it.

It should compile without errors. I do not have an SPI display to test it with.

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

Good job!
I tried your ways, like this:
git clone https://github.com/lvgl/lv_micropython.git
cd lv_micropython
git submodule update --init --recursive lib/lv_bindings
download your dirvers.esp32.zip ,unzip the files and overwrite it.
try
make -C ports/esp32 LV_CFLAGS="-DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP=1" BOARD=GENERIC_S3_SPIRAM IDF_TARGET=esp32s3

but report errors in the last stage:
[1497/1499] Linking CXX executable micropython.elf
FAILED: micropython.elf

/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/driver/libdriver.a(gpio.c.obj):(.literal.gpio_force_hold_all+0x0): undefined reference to rtc_gpio_force_hold_all'
/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/driver/libdriver.a(gpio.c.obj): in function gpio_force_hold_all': /home/jd3096/esp/esp-idf/components/driver/gpio.c:685: undefined reference to rtc_gpio_force_hold_all'
/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.literal.esp_eth_phy_new_lan8720+0x0): undefined reference to esp_eth_phy_new_lan87xx' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj): in function esp_eth_phy_new_lan8720':
/home/jd3096/esp/esp-idf/components/esp_eth/include/esp_eth_phy.h:271: undefined reference to esp_eth_phy_new_lan87xx' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_xt_clock_freq_mpobj+0xc): undefined reference to xt_clock_freq'
/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_lldesc_build_chain_mpobj+0xc): undefined reference to lldesc_build_chain' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_gpio_input_get_high_mpobj+0xc): undefined reference to gpio_input_get_high'
/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_gpio_output_set_high_mpobj+0xc): undefined reference to gpio_output_set_high' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_ksz8081_mpobj+0xc): undefined reference to esp_eth_phy_new_ksz8081'
/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_ksz8041_mpobj+0xc): undefined reference to esp_eth_phy_new_ksz8041' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_dp83848_mpobj+0xc): undefined reference to esp_eth_phy_new_dp83848'
/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_lan87xx_mpobj+0xc): undefined reference to esp_eth_phy_new_lan87xx' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_rtl8201_mpobj+0xc): undefined reference to esp_eth_phy_new_rtl8201'
/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_ip101_mpobj+0xc): undefined reference to esp_eth_phy_new_ip101' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_lldesc_set_owner_mpobj+0xc): undefined reference to lldesc_set_owner'
/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_lldesc_num2link_mpobj+0xc): undefined reference to lldesc_num2link' collect2: error: ld returned 1 exit status ninja: build stopped: subcommand failed. ninja failed with exit code 1 make: *** [Makefile:34: all] Error 2 make: Leaving directory '/home/jd3096/Desktop/01/lv_micropython/ports/esp32'
the same error as yours?

@kdschlosser
Copy link
Contributor

kdschlosser commented Dec 17, 2022

did you use the repo I linked to or did you use the files I attached in a zip?? If you used the zipped files don't, use the linked repo instead

@jd3096-mpy
Copy link

did you use the repo I linked to or did you use the files I attached in a zip?? If you used the zipped files don't, use the linked repo instead

Sorry,I git the wrong repo branch.
Now it can be compiled without errors,I will test it later.

@jd3096-mpy
Copy link

jd3096-mpy commented Dec 18, 2022

did you use the repo I linked to or did you use the files I attached in a zip?? If you used the zipped files don't, use the linked repo instead

I think there is still something wrong with SPI,
Init the screen there is a mistake:
("Failed initializing SPI bus")
I tried to trace the source code in ili9XXX
ret = esp.spi_bus_initialize(self.spihost, buscfg, 1)
ret return value:258 that's not right.
I change to ret = esp.spi_bus_initialize(self.spihost, buscfg, 0)
it works,but the screen show like this:
7182ed39be5a68ab10226ff8d583ac7

I use lilygo t embed the screen is st7798v3 170x320
or mabey the screen driver init is not corrent

@kdschlosser
Copy link
Contributor

OK so there is a result at least. That's a good thing. going to have to hammer out any kinks in it.

Can you post the exact Micropython code you are using?

And do you have the exact model number of the Lillygo piece you are using? I want to see if everything is aligning properly between the screen the Micropython code and the c code..
Gotta develop a data path to see what is happening.

@kdschlosser
Copy link
Contributor

and that returned value is ESP_ERR_INVALID_ARG

hmmm...
Time to go digging.

@jd3096-mpy
Copy link

spi_bus_initialize

and that returned value is ESP_ERR_INVALID_ARG

hmmm... Time to go digging.

Yes,here is the error code form esp-idf WIKI
[ESP_ERR_INVALID_ARG](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/system/esp_err.html#c.
ESP_ERR_INVALID_ARG) (0x102): Invalid argument(258)

[ESP_ERR_INVALID_STATE](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/system/esp_err.html#c.
ESP_ERR_INVALID_STATE) (0x103): Invalid state(259)
Sometimes return 259,when I changed to esp.spi_bus_initialize(self.spihost, buscfg, 0) rutern 0 that's right
0 means dma_channel

here's my mpy code:
`import machine
import espidf as esp
from machine import Pin
from fbdriver import st7789
import lvgl as lv
power=machine.Pin(46, machine.Pin.OUT)
power.value(1)
bl=machine.Pin(15, machine.Pin.OUT)
bl.value(1)

disp = st7789(
mosi=11, clk=12, cs=10, dc=13, rst=9,width=135, height=240, rot=-1, factor=4,spihost=esp.VSPI_HOST)

lv.init()
scr = lv.obj()
btn = lv.btn(scr)
label = lv.label(btn)
label.set_text("Button")

Load the screen

lv.scr_load(scr)`

fbdriver is the copy of ili9XXX.py so I can test the driver.

@jd3096-mpy
Copy link

OK so there is a result at least. That's a good thing. going to have to hammer out any kinks in it.

Can you post the exact Micropython code you are using?

And do you have the exact model number of the Lillygo piece you are using? I want to see if everything is aligning properly between the screen the Micropython code and the c code.. Gotta develop a data path to see what is happening.

Here is the offical repo:
https://github.com/Xinyuan-LilyGO/T-Embed

The GPIO marked in the picture is wrong, I am sure.
I tried to use other st7789 driver on this board,it works normally.
You can find the right GPIO in source code .h they defined.

https://github.com/Xinyuan-LilyGO/T-Embed/blob/main/example/tft/pin_config.h

#define PIN_LCD_BL 15
#define PIN_LCD_DC 13
#define PIN_LCD_CS 10
#define PIN_LCD_CLK 12
#define PIN_LCD_MOSI 11
#define PIN_LCD_RES 9

@kdschlosser
Copy link
Contributor

I believe I found the issue.

I committed the changes to that same branch on my fork that I linked to in a previous post.

Give it a try again. It has to do with the DMA channel being used. If you have the repl open when you boot the ESP it will spit out any error codes if one does show up.

@kdschlosser
Copy link
Contributor

Use the script below to run the test with

import machine
import ili9XXX
import lvgl as lv

disp = ili9XXX.st7789(
    mosi=11, 
    clk=12, 
    cs=10, 
    dc=13, 
    rst=9,
    power=46,
    backlight=15,
    backlight_on=0,
    power_on=0,
    width=170, 
    height=240,
    rot=ili9XXX.LANDSCAPE
)

lv.init()
scr = lv.obj()
btn = lv.btn(scr)
label = lv.label(btn)
label.set_text("Button")

@jd3096-mpy
Copy link

Traceback (most recent call last):
File "", line 2, in
File "ili9XXX.py", line 64, in
AttributeError: 'module' object has no attribute 'ENUM_SPI_HOST'

Also no attribute:
SPI_DMA_DISABLED
ENUM_VSPI_HOST
ENUM_HSPI_HOST

import espidf as esp
help(esp)

SPI_HOST -- 0
VSPI_HOST -- 1
HSPI_HOST -- 2
SPI1_HOST -- 0
SPI2_HOST -- 1
SPI3_HOST -- 2
portMAX_DELAY -- -1
I2S_PIN_NO_CHANGE -- -1

only these const are defined

I try to chagne these const with value instead

It shows the same screen.
I think mabey I should change another st7789 screen 320x240
That's more easy to use.

@jd3096-mpy
Copy link

Especially ESP32-S3,many borads use it instead of ESP32, but they can't be used in micropython yet,

@jd3096-mpy see #243 - this adds ESP32-S3 support. Could you try this PR on your side and see if it works for you?

Oh my god ,this repo works!!!
Here is my mpy code:
import machine
import ili9XXX
import lvgl as lv

power=machine.Pin(46, machine.Pin.OUT)
power.value(1)
bl=machine.Pin(15, machine.Pin.OUT)
bl.value(1)

disp = ili9XXX.st7789(
mosi=11,
clk=12,
cs=10,
dc=13,
rst=9,
width=320,
height=170,
start_x=0,
start_y=35,
rot=-2
)

lv.init()

style_base = lv.style_t()
style_base.init()
style_base.set_bg_color(lv.palette_main(lv.PALETTE.LIGHT_BLUE))
style_base.set_border_color(lv.palette_darken(lv.PALETTE.LIGHT_BLUE, 3))
style_base.set_border_width(2)
style_base.set_radius(10)
style_base.set_shadow_width(10)
style_base.set_shadow_ofs_y(5)
style_base.set_shadow_opa(lv.OPA._50)
style_base.set_text_color(lv.color_white())
style_base.set_width(100)
style_base.set_height(lv.SIZE_CONTENT)

Set only the properties that should be different

style_warning = lv.style_t()
style_warning.init()
style_warning.set_bg_color(lv.palette_main(lv.PALETTE.YELLOW))
style_warning.set_border_color(lv.palette_darken(lv.PALETTE.YELLOW, 3))
style_warning.set_text_color(lv.palette_darken(lv.PALETTE.YELLOW, 4))

Create an object with the base style only

obj_base = lv.obj(lv.scr_act())
obj_base.add_style(style_base, 0)
obj_base.align(lv.ALIGN.LEFT_MID, 20, 0)

label = lv.label(obj_base)
label.set_text("Base")
label.center()

Create another object with the base style and earnings style too

obj_warning = lv.obj(lv.scr_act())
obj_warning.add_style(style_base, 0)
obj_warning.add_style(style_warning, 0)
obj_warning.align(lv.ALIGN.RIGHT_MID, -20, 0)

label = lv.label(obj_warning)
label.set_text("Warning")
label.center()

screen:
0aa98da879ff9222534de6bde4bebaa

@jd3096-mpy
Copy link

If anyone wants to give this a go to see if it works I would appreciate it.

It should compile without errors. I do not have an SPI display to test it with.

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

GOD,I just found this repo works!
https://github.com/imliubo/lv_binding_micropython/tree/dev_esp32_s3

Thanks for you working,too.

@kdschlosser
Copy link
Contributor

OooooOOoOO I forgot one other thing. Just like before you need to specify the color depth in the same manner when compiling.

LVFLAGS="LV_COLOR_DEPTH=16"

changing 16 to whatever the color depth is for your display. That needs to be added onto the make.py compile line.

python3 make.py esp32 -mpy_cross -submodules -clean BOARD=ESP32_GENERIC BOARD_VARIANT=SPIRAM LVFLAGS="LV_COLOR_DEPTH=16"

@AndreoBotelho
Copy link

There's some typing errors but after compiling it is stil hanging on task handler, the driver sends the first chunk of data to display and lvgl hangs, display is blank.
*driver/esp32/lcd_bus/src/../include/modlcd_bus.h:96:14: error: 'self' is a pointer; did you mean to use '->'?
*driver/esp32/lcd_bus/src/../include/modlcd_bus.h:98:21: error: 'self' is a pointer; did you mean to use '->'?
*driver/esp32/lcd_bus/src/modlcd_bus.c:23:16: error: 'bus_obj' is a pointer; did you mean to use '->'?

@kdschlosser
Copy link
Contributor

OK i fixed the type errors and committed the changes. So that should be good to go.

Let me see about returning the buffers as an array.array object. Maybe that will correct the problem.

@kdschlosser
Copy link
Contributor

I just pushed a commit. see if that fixes the issue with the buffers. I have not tested the code at all so lemme know how you make out.

@AndreoBotelho
Copy link

Error compiling /include/modlcd_bus.h:173:48: error: 'BYTEARRAY_TYPECODE' undeclared (first use in this function)

@kdschlosser
Copy link
Contributor

Ok I missed an include. I will see if I can get that fixed from where I am. I am not at home

@kdschlosser
Copy link
Contributor

OK I added the include.

@kdschlosser
Copy link
Contributor

I made a bunch of changes.

I am hoping that this time I have the buffers fixed. It would be nice if it is.

I updated the make.py script. The second go around compiling after changing the partition size is now a whole lot faster, it doesn't compile the entire things again. I also updated it so it resizes up and also down if needs be. I added a command line switch to turn off the resizing, -skip-partition-resize is what you add when you run make.py

I also have the script automatically disabling I2C for the time being. This is due to an upstream bug in MicroPython. It has been reported and hopefully it will be fixed along with the btree issue in the next release. Fingers crossed there.

A added some additional output to the build that is easily seen so the user will know what is taking place when the build starts over again. Just informative messages is all.

I did test compile before I committed and pushed the changes. So there should be no type errors when compiling.

@AndreoBotelho
Copy link

AndreoBotelho commented Dec 2, 2023

The code compliled but SPI display still not working, I've made some tests using a upy driver and the problem is that disp_drv.flush_ready() is never called in your code, this hags lgvl waiting the display, there's some problem with SPI transfer. Using soft SPI (without DMA) LVGL is running fine.

@AndreoBotelho
Copy link

There's too a error in framework line 274 " lv.flush_ready(disp_drv)" (not the cause of hang) , you could fix LVGL V8.3 for now because V9.0 API is a mess.

@kdschlosser
Copy link
Contributor

OK I will have a look and see what's up with it. So the issue is in the bus driver somewhere.

Just as a question what are the parameters you are passing to the bus driver. I would like to se if maybe I am initializing it incorrectly and if that is the source of the hang.

I am going to dig out my MCU's and displays. I will put together a couple of testing setups. I probably will not do any more updating of the repo until I get everything working properly.

@AndreoBotelho
Copy link

AndreoBotelho commented Dec 3, 2023

import` lcd_bus
from micropython import const
import lvgl as lv
from machine import Pin,Timer
import st7789lv as st7789
import time

_DISPLAY_WIDTH = const(240)
_DISPLAY_HEIGHT = const(280)


bus = lcd_bus.SPIBus(
    dc=5,
    host=1,
    mosi=6,
    miso=-1,
    sclk=4,
    cs=7,
    freq=80000000,
    wp=-1,
    hd=-1,
    quad_spi=False,
    tx_only=True,
    cmd_bits=8,
    param_bits=8,
    buffer_size=int((_DISPLAY_WIDTH * _DISPLAY_HEIGHT) // 4) * lv.color_t.__SIZE__,
    fb_in_psram=False,
    use_dma=True,
    dc_low_on_data=True,
    sio_mode=False,
    lsb_first=False,
    cs_high_active=False,
    spi_mode=0
)

disp = st7789.ST7789(bus, 240, 280, offset_y = 20)
disp.init()

btn=lv.btn(lv.scr_act())
lbl=lv.label(btn)
lbl.set_text("Press me!")
btn.center()
btn.add_event(lambda event: print('Button clicked!'),lv.EVENT.CLICKED,None)

#testTimer = lv.timer_create(test, 500, None)


start_time = time.time_ns()

left_over = 0
while True:
    # user_code here
    curr_time = time.time_ns()
    new_amount = time.ticks_diff(curr_time, start_time) + left_over
    left_over = new_amount & 0x3E8
    lv.tick_inc(new_amount >> 12)
    print("btask")
    lv.task_handler()
    print("atask")
    start_time = curr_time

this is the simple code I'm using to test

@kdschlosser
Copy link
Contributor

kdschlosser commented Dec 3, 2023

ok so first thing is your frame buffer is WAYYYYY to big. it's not going to fit into DMA'able SRAM. I still have to add exceptions for the buffers failing to be made.

    buffer_size=int((_DISPLAY_WIDTH * _DISPLAY_HEIGHT) // 10) * lv.color_t.__SIZE__,

That should fit without any issues.

just a heads up with the ESP and using SPI.
unless you use these pins for these specific hosts your SPI transfer rate is going to be limited to 22 mhz.

host 1
mosi: 13
miso: 12
sck: 14
cs:15
wp: 2
hd: 4

host 2
mosi: 23
miso: 19
sck: 18
cs: 5
wp: 22
hd: 21

The reason why is due to it not being 100% hardware and a redirect needs to take place. That limits the speed the SPI is able to do.

If you want full speed to be available then connect to those pins. You can save some pin connections still and set miso and cs to -1. the wp and hd pins are also set to -1 if you are not using quad spi.

@kdschlosser
Copy link
Contributor

the speed is actually limited to 26.6 mhz. my bad on that one.

@kdschlosser
Copy link
Contributor

I made a couple of small changes. so I would update your code and try it again with the buffer size change

@kdschlosser
Copy link
Contributor

I added the exceptions for memory allocation.

@kdschlosser
Copy link
Contributor

Also, version 9.0 isn't a mess. the API has changed. It works just fine.

@AndreoBotelho
Copy link

Tested reducing the framebuffer and the hang stopped but screen still blank( cant recall when I increased buffer size), recompiled new version and there's some errors on buffer error msg but compiled fine, the problem now is another error on flush cb:
RuntimeError: maximum recursion depth exceeded

@AndreoBotelho
Copy link

the speed is actually limited to 26.6 mhz. my bad on that one.

ESP32-C3/S3/S2 SPI can go up to 80Mhz using gpio matrix. only original ESP32 have this 26.6Mhz limit but I've tested and could reach 60Mhz on a ESP32 rev3 using SPI through GPIO matrix

@kdschlosser
Copy link
Contributor

kdschlosser commented Dec 4, 2023

says it right here in the documentation

https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/spi_master.html#_CPPv418spi_bus_add_device17spi_host_device_tPK29spi_device_interface_config_tP19spi_device_handle_t

While in general, speeds up to 80MHz on the dedicated SPI pins and 40MHz on GPIO-matrix-routed pins are supported, full-duplex transfers routed over the GPIO matrix only support speeds up to 26MHz.

so 26.6 mhz is as fast as it will go using full duplex over the GPIO matrix.

scroll to the top and check for yourself. The documentation is set to the ESP32S3.

@AndreoBotelho
Copy link

AndreoBotelho commented Dec 4, 2023

says it right here in the documentation

https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/spi_master.html#_CPPv418spi_bus_add_device17spi_host_device_tPK29spi_device_interface_config_tP19spi_device_handle_t

While in general, speeds up to 80MHz on the dedicated SPI pins and 40MHz on GPIO-matrix-routed pins are supported, full-duplex transfers routed over the GPIO matrix only support speeds up to 26MHz.

so 26.6 mhz is as fast as it will go using full duplex over the GPIO matrix.

scroll to the top and check for yourself. The documentation is set to the ESP32S3.

Yes, this note exists in all ESP32 model docs but only on ESP32 original there's a note about timing linking to it, all othes says

When an SPI Host is set to 80 MHz or lower frequencies, routing SPI pins via the GPIO matrix will behave the same compared to routing them via IOMUX.

on esp32 original there's this note:


Increases the input delay of the MISO signal, which makes MISO setup time violations more likely. If SPI needs to operate at high speeds, use dedicated IO_MUX pins.

Allows signals with clock frequencies only up to 40 MHz, as opposed to 80 MHz if IO_MUX pins are used.

Note

For more details about the influence of the MISO input delay on the maximum clock frequency, see [Timing Considerations](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html#timing-considerations). `

The 26Mhz is only full duplex but I can't much use for full duplex on a display bus

@AndreoBotelho
Copy link

Update: fixed some code and now the LCD BUS using Spi is sending perfect data to display with or without DMA, the only problem is that the transmission needs to be syncronous because the code is unable to call a python function from C, direct calling gives infinite recurssion and sheduled call never gets called on Py VM.

@AndreoBotelho
Copy link

PS: I'm using the code with mpy malloc and works fine, the bus passing a array buffer and sending back with dereference from py

@kdschlosser
Copy link
Contributor

Yes you can create a byte array and pass it to C code and it will work as a buffer. Problem is no ability to specify where that data is to be stored, DMA SRAM, DMA SPIRAM, SRAM or SPIRAM, It goes into where ever it is going to fit.

@AndreoBotelho
Copy link

I'm using your commit d782fec before change the frame buffers, on framework flush_cb need to uncomment the code

        size = (x2 - x1 + 1) * (y2 - y1 + 1)
        data_view = color_p.__dereference__(size * lv.color_t.__SIZE__)  # NOQA

to not get segfault when passing the buffer back to C and include

disp_drv.flush_ready()

after flush_cb code to not hang LVGL on wainting flush loop, this way the LCD_BUS works in sincronous (slow) or unmanaged DMA (a little faster)

@kdschlosser
Copy link
Contributor

kdschlosser commented Dec 10, 2023

I know what is going on with the flush function I am trying to dereference more memory than has been allocated. That is what is causing the segfault/hang.

SIZE can no longer be used to determine the color depth that is being used.

It should now read

        data_view = color_p.__dereference__(size * lv.color_format_get_size(disp.get_color_format()))  # NOQA

That should fix the issue in the flush function.

@kdschlosser
Copy link
Contributor

How things are done is when the buffer gets passed to the display driver initially that buffer gets converted into an LVGL CArray. That CArray then gets passed to the flush function and this is the reason why you need to use the dereference. doing that converts the object into a MicroPython MemoryView object I have to change the C code to handle collecting the pointer from that memoryview object to pass it to the driver as an actual C pointer.

I just figurred all of this out in the last couple of days.

@AndreoBotelho
Copy link

I know what is going on with the flush function I am trying to dereference more memory than has been allocated. That is what is causing the segfault/hang.

SIZE can no longer be used to determine the color depth that is being used.

It should now read

        data_view = color_p.__dereference__(size * lv.color_format_get_size(disp.get_color_format()))  # NOQA

That should fix the issue in the flush function.

The hang is due to mp_sched_schedule never beeing called on python code ( maybe the lvgl wait flush never returns the control to mpy) and if you change to mp_call_function get recursion error

@MathyV
Copy link

MathyV commented May 16, 2024

After spending countless hours/days/weeks trying to get a mix of MicroPython 1.22, IDF 5.1.2 and LVGL 9.1 working as a USER_C_MODULE I could directly use from my MicroPython build using any and all resources I could find I finally caved and gave up trying to adapt existing solutions.

I crafted a custom repository that is specialized for my use case but still worth sharing in case others find it useful and perhaps it is useful to get this issue, PR #242 or PR #341 moving.

You can find the repository here: https://github.com/MathyV/lvgl_esp32_mpy

If you have an ESP32 connected to an ST7789 display over SPI, this solution will probably work out-of-the-box for you.

Finally, a small movie that shows it's working:

PXL_20240516_011152235.TS.2.mp4

@kisvegabor
Copy link
Member

Thank you the countless hours/days/weeks you put into it and for sharing the result! 👍

@kdschlosser is into approaching it from a new perspective too and he also made good progress, but I'm not sure what is the exact status on his end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed Sponsored Get payment for the implementation or fix
Projects
None yet
Development

No branches or pull requests