How to share the spi bus with touch or sdcard

Ok folks this is the skinny on how this works. This topic has come up many times.

There is some goofy handling of the SPI bus in micropython

In order to share the pins and the host that are used must be identical. Well all except the CS pin that has to be different

The CS pin is what selects the device so it can communicate on the bus.

The SPI host used in the binding for the display drivers is NOT host 1 = SPI 1 and host 2 = SPI 2.

0 = SPI 1
1 = SPI 2
2 = SPI 3

Machine.SPI uses 1, 2 and 3. Internally it subtracts 1 from the passed in host number.

Machine.SDCard works even funkier. You have to add 2 to the real SPI host number.

Host 2 is always a safe bet to use. So to make it work this is what you have to pass as the host

Display driver: 1
Machine.SPI: 2
Machine.SDCard: 3

Those are all SPI2.

Now if you are using an SD card and something like the touch you may have problems. While you are transferring from anything other than the display it is best to turn off the the isr that handles calling the task handler. This can be done by importing lv_utils and in that module is a class that you can used to get the running handler and you can shut it down.

So this is my hack to be able to READ/WRITE to SDcard (non machine)
with ili9341 display and xpt2046 touch
I am using lv_micropython master built with idf 4.4.6
My sd card has a directory SD/Data
with a file name… 2023-10-23.txt (lines of logs) you could have text “hello world”

Imports lv_utils…

has two functions…

NOW All three devices connect and function but I need to invoke disp.event_loop.disable()
inorder to read or write to the sdcard.
If I do not invoke disp.event_loop.disable()
I will get… sdcard timeout waiting for response or [Errno 5] EIO errors.

import lvgl as lv
from ili9XXX import ili9341
from xpt2046 import xpt2046
import os, time, sdcard
from machine import SPI, Pin

# Mount SD Card
sd = sdcard.SDCard(SPI(2), Pin(14), baudrate=20_000_000)
os.mount(sd, '/sd')
# Load Graphics Touch Drivers
disp = ili9341(spihost=2, miso=-1, mosi=-1, clk=-1, cs=15, mhz=20, dc=13, rst=-1, power=-1, factor=48, half_duplex=False, backlight=27, backlight_on=1)
touch = xpt2046(spihost=2, cs=5, mhz=5, half_duplex=False, cal_x0 = 242, cal_x1 = 3783)

def button_cb(e):
	if e.get_code() == lv.EVENT.CLICKED:
		u_name.set_text('Got Clicked')
		print('clicked !!!')

scr = lv.scr_act()
u_name = lv.label(scr)
u_name.align(lv.ALIGN.TOP_MID, 0, 40)
u_name.set_style_text_font(lv.font_montserrat_20, 0)
u_name.set_text('S P I  Issues')
btn = lv.btn(scr)
btn.align(lv.ALIGN.TOP_MID, 0, 200)
btn.add_event(button_cb, lv.EVENT.CLICKED, None)
btn_lbl = lv.label(btn)
btn_lbl.set_text("CLICK Me")

def sd_read(file):
		with open(file, 'r') as f:
			x =
	except Exception as e:
		x = "file error"

	return x

da_num = 1
# while da_num <= 20:		# Stops after 20 loops
while True:				# continuous
	except Exception as e:
	da_num += 1

Hopefully this sheds a little more light on this issue.