Once more: esp32, ILI9341 + xpt2046 + sdcard on same spi

Is this a µP binding limitation or ESP-IDF limitation? Could you point me to the API you are referring to?
The µP binding is generated from ESP-IDF headers so I would like to know where is the discrepancy.

Maybe a DMAable RAM allocation problem? The ILI driver allocates lots of DMAable RAM. You can try to minimize it by lowering the factor parameter.

Anyway, I’m very curious about your findings on this.

So how is it implemented in the original SD card driver? How did they work around this issue?

It’s an ESP-IDF thing. It’s this field: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html#_CPPv4N17spi_transaction_t4addrE

They are doing everything manually byte by byte and they are controlling cs also manually and keep it asserted as long as they want. See https://github.com/micropython/micropython/blob/master/drivers/sdcard/sdcard.py

I am not surprised that this collides with some DMA spi going on in the background.

A related question: The docs several times mention this default/example mapping:
ILI9341: miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, power=14, backlight=15, spihost=esp.HSPI_HOST, mhz=40, factor=4, hybrid=True

What confuses me here is that this uses HSPI but the default pin numbers are for VSPI pins. This is possible as there’s the pin multiplexer but IMHO it doesn’t make too much sense. Why is this using HSPI?

Where did you see that the address is limited to 16 bit?
In the docs it says address_bits 0-64 bits.

Probably a mistake.
It doesn’t matter too much because, as you said, almost any pins can be used and the multiplexer would handle this. (On the other hand it probably limits the maximum frequency because of the multiplexer timing).

Feel free to send a PR to change that.

When i try to write anything > 65535 into that field within µP i get this error:
OverflowError: overflow converting long int to machine word

For some reason µP thinks this is an integer.

Actually none of this works for me as my version of µP doesn’t even have esp.HSPI_HOST and I am just using constants 1 and 2. So i don’t have an idea what should be used there.

So I did fire up the logic analyzer under slight protest from the kids as they had rewired the sd card to the second spi.

I have this code i wrote an basis of the xpt driver which just sends a few commands to the sd card full duplex and reads a few bytes back and i see that this sort of makes sense and i see the expected reply to several commands. I see this in the logic analyzer and the esp32 reports these as well. Once i load the ili driver beforehand the esp32 reports unexpected vakues that don’t make much sense. And here’s the interesting part: In the logic analyzer i still see the correct bytes.

So the transfer itself is still working. The result just doesn’t reach memory. Since the xpt driver does work this may be related to the fact I need to do full duplex transfers and the ili does half duplex and this won’t coexist.

Anyway. For the sd card full duplex is not the way to go, anyway. But as pointed out before half duplex does not work as i cannot write the address field as i’d need.

Biggest problem here: The setup using the second spi for the sd card is working and the kids are satisfied :slight_smile: So they don’t want me to go one step backwards and try to understand what’s going in with the shared bus.

I’d like to do similar with the ili driver and the original sdcard.py (or its equivalent in machine.sdcard). But i cannot manage that to load at all. Whatever I try either the ili or the sdcard complains that the spi bus is already in use.

Actually… this might be a bug in the LVGL micropython bindings.
I noticed that it tries to convert 64bit integers with mp_obj_new_int/mp_obj_get_int, while the correct functions are probably mp_obj_new_int_from_ll and I’m not sure what is the other one to convert mp integer back to long long.
I’ve opened an issue to track this.

That’s strange.
Macros are not automatically converted, but HSPI/VSPI is handled specially here with an enum, which is converted automatically.

That’s great! I can’t wait until my kids are old enough to wire anything on my projects. Currently they barely wire their own shoe laces…

Both ili and xpt can be configure to work either half duplex or full duplex. There’s a half_duplex argument in the constructor.

I can’t remember seeing anything in the docs that prevents half-duplex and full-duplex coexistence on the same SPI bus. But I think I’ve seen issues (this, this) mentioning problems when mixing half/full duplex. Maybe some esp-idf problem? here is a post in esp forum.

If you provide “-1” to ili miso/mosi/clk, it will not try to initialize the bus. But you need to make sure that whichever code that initializes the bus also sets a large enough max_transfer_sz.
Another option is to let ili initialize the bus and remove the bus initialization code from the sdcard driver.

That’s indeed great. I am doing this for a small toy controller where they can select and run their own python scripts from sd card.

Uhm … and there it reads #if ... && ESP_IDF_VERSION_MAJOR >= 4 which explains it as I am using IDF 3 since 4 is still marked as experimental.

Thinks like you are all using version 4 …

I finally found it. a) IDF 4 seems to be needed for that and b) then this shows up as esp.HSPI_HOST only after a import espidf as esp. This is somewhat confusing as a module named esp actually exists and also one named esp32 which many examples import esp32 as esp

Well, both esp32 and espidf modules provide µP API to the same ESP-IDF C API.
esp32 is manually-written and provided by Micropython while espidf is auto generated from ESP-IDF header files and specific to lv_micropython. espidf is provided in addition to the original esp32 module.

I agree it’s a bit confusing, but that’s how it is right now.

Update: This problem is resolved on latest lv_binding_micropython.

esp32, ili9XXX + xpt2046 + SDCard on same spi
Still no fix ???
Tim conceded ?

last post…
Update : This problem is resolved on latest lv_binding_micropython.

I am using esp-idf v4.1, lv_micropython dev, micropython v1.14
And not working.

Update: favnec5 created a SPI driver that can work with sdcard and ili9xxx on the same bus.

Let us know if this solves your problem.

See:

Hello
I can’t conect to my SD card with lv_spi and lvdisplay running in the same SPI bus.
I am running :
spi = lv_spi.SPI(mosi=23, miso=19, clk=18)
sd = sdcard.SDCard(spi, machine.Pin(5))
os.mount(sd, “/sd”)
print(os.listdir(’/sd’))

And it works …

rst:0xc (SW_CPU_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:4348
load:0x40078000,len:12384
load:0x40080400,len:3432
entry 0x40080610
[‘SD_VIDEO’, ‘DCIM’, ‘MISC’, ‘System Volume Information’]
MicroPython v1.18-601-g01f31ac23-dirty on 2022-09-11; ESP32 module (spiram) with ESP32
Type “help()” for more information.
but if I run this:

disp = ili9341()
touch=xpt2046(inverted = True)
obj=lv.scr_act()

sd = sdcard.SDCard(lv_spi.SPI(), machine.Pin(5))
os.mount(sd, “/sd”)
print(os.listdir(’/sd’))

I get and error …
ILI9341 initialization completed
Traceback (most recent call last):
File “main.py”, line 15, in
File “sdcard.py”, line 54, in init
File “sdcard.py”, line 87, in init_card
File “sdcard.py”, line 135, in init_card_v2
OSError: timeout waiting for v2 card
MicroPython v1.18-601-g01f31ac23-dirty on 2022-09-11; ESP32 module (spiram) with ESP32
Type “help()” for more information.

Any help please …

have you resolved your problem? I also encountered this error message’OSError: timeout waiting for v2 card‘
thanks.

no luck so far. SDcard is not the main point of my project, so I have put it aside. But it would be great if we can manage a way to deal with it. I may try to use the new lv-micropython version, I hope it will help.

So I have been able to move a little farther along !!!

see…

Allmost there…

since you are using the CS line it should only be a matter of flipping the states on the CS pins for the different devices. You can delete the lv timer object that is stored in lv_indev_t and recreate it when you are done doing whatever needs to be done with the SD card. It really shouldn’t be all that difficult to do.

So what I ended up doing is using…
disp.event_loop.disable()
disp.event_loop.enable()
These comands apear to stop and start lvgl.

def sd_write(file,info,w):
    disp.event_loop.disable()
    time.sleep(.05)
    try:
        with open(file, w) as f:
            f.write(info)
    except Exception as e:
            print(e)
    disp.event_loop.enable()

This discussion is too advanced for me.

Does anyone know an intermediate solution?

So I can use TouchScreen and SDCard?

I put details of my problem in this post: https://forum.lvgl.io/t/sd-card-disable-my-touch-screen-help-me/14130v