Not able to pre-Initialize SPI bus for ili9341

settings in ili9341.py file… then compilied

def __init__(self, miso=19, mosi=23, clk=18, cs=14, dc=27, rst=33, power=-1, backlight=32, backlight_on=1, power_on=1, spihost=esp.HSPI_HOST, mhz=40, factor=4, hybrid=True, width=320, height=240, colormode=COLOR_MODE_BGR, rot=LANDSCAPE, invert=False, double_buffer=True):

main.py file …

import lvgl as lv
import lvesp32
from machine import SPI, Pin

lv.init()

spi = SPI(1, sck=Pin(18), mosi=Pin(23), miso=Pin(19))

from ili9341 import ili9341
disp = ili9341(spihost=1, miso=-1, mosi=-1, clk=-1)

scr = lv.scr_act()
l = lv.label(scr)
l.set_text("HEY Dum A**")
l.align(scr, lv.ALIGN.CENTER, 0, 0)
lv.scr_load(scr)

print("sent text")

REPL output…

ILI9341 initialization completed
Enable backlight
Double buffer
sent text

Screen dimly lit with no label text and
No response from REPL… need to reboot

Why did you need to change the defaults on ili9341.py and compile?

You are allocating SPI through the machine module, but you are not using it later on.
ili9341 module is unrelated to SPI from machine module, and they were not designed to work together.

Setting miso/mosi/clk to -1 assumes that SPI was already allocated by esp.spi_bus_initialize.
However, I’m not sure how SPI from machine module calls it and what else it’s doing, so I’m not sure whether it’s compatible with the way ili9341 is using spi.

I used this technique when assigning both ili9341 and xpt2016 to the same spi bus, both are using espidf module’s spi_bus_initialize, and only one of them initialized the SPI bus. This is known to work.
But I’ve never tried using it with SPI from machine module.

Could you try removing SPI of machine and set miso/modi/clk to the right ports on ili9341 contrsuctor? Let’s see if it’s working on a simpler configuration.

The GOAL is to…
Share SPI with… ili9341 + xpt2046 + SDCard

Mike Teachman is the person who found the workaround using a modded modILI9341.c module.
I was able to use the modILI9341.c with machine.SDCard and it works perfectly.
The fix is basically not to initialize an already existing SPI bus!
ex:

import ILI9341
from machine import SPI, Pin, SDCard
uos.mount(SDCard(slot=2, sck=18, miso=19, mosi=23, cs=4), '/sd')
disp = ILI9341.display(spihost=2, cs=14, dc=27, rst=33, backlight=32, mhz=25, share=ILI9341.SHARED)

The “share=ILI9341.SHARED” prevents the driver from initializing SPI again.

But I also need the touch driver.
I asked him if he also had a fix for adding the modxpt2046.c touch driver.
https://forum.micropython.org/viewtopic.php?f=18&t=8352&start=20

By using either…
spi = SPI(2, sck=Pin(18), mosi=Pin(23), miso=Pin(19)) or
uos.mount(SDCard(slot=2, sck=18, miso=19, mosi=23, cs=4), ‘/sd’)
and…
disp = ili9341(spihost=2, miso=-1, mosi=-1, clk=-1)

The ili9341.py display driver is able to connect to the SPI bus
and the output confirms this…
'>>>
ILI9341 initialization completed
Enable backlight
Double buffer

mcu freezes

The c and py drivers both can connect to SPI…
but the py has other coding issues down line.
as you mentioned @ “https://github.com/lvgl/lv_binding_micropython/issues/69

I’m not sure why this is working at all with the C driver, but not with the micropython driver. Did you make sure it is working stably?
It might be related to the fact the the C driver is not really doing DMA in the background, like the micropython driver does. Instead, it sends the request and waits for it to complete. While very inefficient, it might prevent other devices from accessing the SPI bus while in progress.

btw…
I am aware of…
https://github.com/espressif/esp-idf/issues/1597
commit
https://github.com/espressif/esp-idf/commit/067f3d21c9f1f3bc76361a0e3cb656216f2583ff
and doc
https://github.com/espressif/esp-idf/blob/master/docs/en/api-reference/peripherals/sdspi_host.rst
and again as you stated in same post…

This problem was fixed in espressif/esp-idf@067f3d2, but that commit is not included yet in Micropython (at least not on the last release v1.12, which lv_micropython is aligned to).
If you want, you can try building lv_micropython with a more up to date esp-idf that includes this fix, but you’ll probably need to change the SD driver to use the new sdspi_host_init_device , sdspi_host_remove_device functions.

I believe if these conflicts can be sorted out…
then adding the xpt2046.py touch driver should be possible also.

Thank you for the clarifications.
Sharing SPI between ili9341 + xpt2046 is already supported.
Did you try it, without the SDCard? Let’s first make sure it works for you.

This is achieved on ili9341.py and xpt2046.py by passing -1 to SPI related parameters.
Here is the relevant code snippet from these drivers:

        if buscfg.miso_io_num >= 0 and \
           buscfg.mosi_io_num >= 0 and \
           buscfg.sclk_io_num >= 0:

                esp.gpio_pad_select_gpio(self.miso)
                esp.gpio_pad_select_gpio(self.mosi)
                esp.gpio_pad_select_gpio(self.clk)

                esp.gpio_set_direction(self.miso, esp.GPIO_MODE.INPUT)
                esp.gpio_set_pull_mode(self.miso, esp.GPIO.PULLUP_ONLY)
                esp.gpio_set_direction(self.mosi, esp.GPIO_MODE.OUTPUT)
                esp.gpio_set_direction(self.clk, esp.GPIO_MODE.OUTPUT)

                ret = esp.spi_bus_initialize(self.spihost, buscfg, 1)
                if ret != 0: raise RuntimeError("Failed initializing SPI bus")

so basically, when you pass -1 the miso/mosi/clk pins are not initialized and spi_bus_initialize is not called, assuming a previous driver already did that.

Did you try to debug why the mcu freezes? If you can connect a debugger through JTAG it can be helpful.
If you cannot, try adding some prints (or even flash a led) to find out where the code reaches and where it doesn’t inside the driver.

One more thing you can try is using SPI functions from espidf module instead of machine module, the same way ili9341.py and xpt2046.py do.

I made a decision to maintain the Python driver and not the C driver.
The Python can work in hybrid mode where initialization is done in Python and fast operations such as handling DMA (“flush” function) is done in C.
The C driver is inferior as it’s less configurable, slower and not really doing DMA in the background.
The downside of the Python driver is that it’s a bit more complex, and apparently doesn’t work well with SD-card on the same bus (but it works well with other drivers on the same bus, such as xpt2046).
I’m not using SD card for my projects so I never had the chance to actually try and debug this, hopefully you or someone else from the community would eventually get to the bottom of this.

I’m planning, at some point, to update lv_micropython to newer micropython version. Micropython didn’t publish new releases recently and no one knows when it will (not even its maintainer…), so I might as well update it to recent mainline.
See https://github.com/micropython/micropython/issues/6017

I’m not sure aligning to Micropython upstream would solve this problem, though, especially when we are not sure what the problem is yet.

Currently I cannot debug it myself, but I’ll do my best answering questions etc.
Please let us know if you make any progress!

I’m aware of that

it works without SD card

I’m aware of that also

ili9341.py does like sharing the same SPI bus with SDCard and no I do not have a JTAG or experience using one.

An example would be appreciated.

Doesn’t work at all… and defeats the whole concept of the SPI bus.

Are you not the developer of this “Pure Micropython Display Driver”
https://blog.lvgl.io/2019-08-05/micropython-pure-display-driver
In this community you are the most qualified… it’s your code.

my build is…
ESP-IDF v4.0.1 4c81978a3e2220674a432a588292a4c860eef27b
LVGL master 983cc35210730d45764e7f97785578a9b19b01f2
Micropython commit… 22806ed5df27c10131af0cedb2f7e8b134fe6e7a
all basically the latest!

The SDCard with "Python Display Driver (ili9341.py) " will not work on the same SPI bus.
The SDCard with “C driver (modILI9341.c)” will work on the same SPI bus.
I believe the problem is the ili9341.py driver that is not playing nice.

I put in a request for “Dedicated support” on the LVGL web site @ $100 per hr.
for fixing an issue with the “Pure Micropython Display Driver”

While I have no technical knowledge about the SD card driver or the ILI9341 driver, I’d like to point out that this logic isn’t necessarily correct. The ILI9341 Python driver might be working fine, and the SD card driver might have a bug in it which causes issues with the ILI9341 driver. I suspect that this might be the case because other SPI devices (like XPT2046) don’t seem to have this issue.

His code works for ILI9341 (and XPT2046). This is an open-source driver developed by one individual on his free time. While he is probably the most qualified to answer questions about it, he is not the most qualified to debug your hardware (I am not sure he even has an SD peripheral at the moment).

1 Like

FYI, the change mentioned in FYI about DMA issues on esp32 might be worth a try, it’s only a matter of deleting one line…

@GC-RmG Did you try changing ili9341 and xpt2046 to full duplex, as @tve suggested?
If you find out this solves the problem, I’ll add full duplex support to the ESP32 SPI drivers.

See also https://github.com/lvgl/lv_binding_micropython/issues/80

with… “flags”: esp.SPI_DEVICE.HALFDUPLEX,

If add… disp = ili9341(mhz=25) then it works
still trying to add SDCard to same bus

Which clk/miso/mosi pins and which spihost are you using?

from sdcard import SDCard

spi = SPI(1, sck=Pin(18), mosi=Pin(23), miso=Pin(19))  #<----- set spi master
sd = SDCard(spi, Pin(4))
uos.mount(sd, '/sd')
print(uos.listdir('/sd/data'))

lv.init()
disp = ili9341(spihost=1, miso=-1, mosi=-1, clk=-1, mhz=25)  #<----- should initialize with current spi master

and the tft display is half lit… every other column is white.

also tried…

from machine import SDCard
uos.mount(SDCard(slot=2, cs=4), '/sd')  #<----- set spi master sck=18, mosi=23, miso=19  ARE PREDEFINED IN SLOT=2
print(uos.listdir('/sd/data'))

lv.init()
disp = ili9341(spihost=2, miso=-1, mosi=-1, clk=-1, mhz=25)  #<----- should initialize with current spi master

same outcome

LVGL should accept a pre-set SPI bus, like…

SPI(1, sck=Pin(18), mosi=Pin(23), miso=Pin(19))  #<----- set spi master
lv.init()
disp = ili9341(spihost=1, miso=-1, mosi=-1, clk=-1, mhz=25)