Sharing the SPI Bus Among SD Cards and Other SPI Devices
The SD card has an SPI mode, enabling it to function as an SPI device, but there are some restrictions that we need to pay attention to.
Pin Loading of Other Devices
When adding more devices onto the same bus, the overall pin loading increases. The loading consists of AC loading (pin capacitor) and DC loading (pull-ups).
AC Loading
SD cards, designed for high-speed communications, have small pin capacitors (AC loading) to work until 50 MHz. However, the other attached devices will increase the pin’s AC loading.
Heavy AC loading of a pin may prevent the pin from being toggled quickly. By using an oscilloscope, you will see the edges of the pin become smoother, i.e., the gradient of the edge is smaller. The setup timing requirements of an SD card may be violated when the card is connected to a bus with a high AC load. Even worse, high AC loads may cause the SD card and other SPI devices to fail to properly resolve clock signals from the host, affecting communication stability.
This issue may be more obvious if other attached devices are not designed to work at the same frequency as the SD card, because they may have larger pin capacitors. The larger the pin capacity, the greater the pin response time, the smaller the max frequency the SD bus can work.
To see if your pin AC loading is too heavy, you can try the following tests:
Terminology:
launch edge: at which clock edge the data starts to toggle;
latch edge: at which clock edge the data is supposed to be sampled by the receiver. For SD card, it is the rising edge.
Use an oscilloscope to see the clock and compare the data line to the clock.
If you see the clock is not fast enough, e.g., the rising/falling edge is longer than 1/4 of the clock cycle, it means the clock is skewed too much.
If you see the data line unstable before the latch edge of the clock, it means the load of the data line is too large.
You may also observe the corresponding phenomenon that data delayed largely from the launching edge of the clock with logic analyzers. But it is not as obvious as with an oscilloscope.
Try to use a slower clock frequency.
If the lower frequency can work while the higher frequency cannot, it is an indication that the AC loading on the pins is too large.
If the AC loading of the pins is too large, you can either use other faster devices with lower pin load or slow down the clock speed.
DC Loading
The pull-ups required by SD cards are usually around 10 kOhm to 50 kOhm, which may be too strong for some other SPI devices.
Check the specification of your device about its DC output current, it should be larger than 700 μA, otherwise, the device output may not be read correctly.
Initialization Sequence
Note
If you see any problem in the following steps, please make sure the timing is correct first. You can try to slow down the clock speed, such as setting SDMMC_FREQ_PROBING
to 400 kHz for SD card, to avoid the influence of pin AC loading, as discussed in the previous section.
When using an SD card with other SPI devices on the same SPI bus, due to the restrictions of the SD card startup flow, the following initialization sequence should be followed. Refer to storage/sd_card for further details.
Initialize the SPI bus properly by
spi_bus_initialize()
.Tie the CS lines of all other devices than the SD card to idle state (by default it’s high). This is to avoid conflicts with the SD card in the following step.
You can do this by either:
Attach devices to the SPI bus by calling
spi_bus_add_device()
. This function will by default initialize the GPIO that is used as CS to the idle level: high.Initialize GPIO on the CS pin that needs to be tied up before actually adding a new device.
Rely on the internal/external pull-up (not recommended) to pull up all the CS pins when the GPIOs of ESP are not initialized yet. You need to check carefully the pull-up is strong enough and there are no other pull-downs that will influence the pull-up. For example, internal pull-down should be enabled.
Mount the card to the filesystem by calling
esp_vfs_fat_sdspi_mount()
.This step will put the SD card into the SPI mode, which should be done before all other SPI communications on the same bus. Otherwise, the card will stay in the SD mode, in which mode it may randomly respond to any SPI communications on the bus, even when its CS line is not addressed.
If you want to test this behavior, please also note that, once the card is put into SPI mode, it will not return to SD mode before the next power cycle, i.e., powered down and powered up again.
Now you can talk to other SPI devices freely!