A µSD, slave SPI, and DMA Apr 2017

Connecting an SD card to a Blue Pill was described in a recent article. With the sdcard.fs code, it’s as simple as calling sd-init, and then sd-read / sd-write for accessing 512-byte blocks.

And since the eZ80 includes an SPI hardware device, we can also use SPI between the eZ80 and the Blue Pill, which - most conveniently - happens to have two SPI interfaces. By letting the eZ80 be the master, we can use very simple byte-by-byte transfers, and keep all the slave SPI complexity on the Blue Pill’s side. This has aleady been solved in another recent article.

All we need to do in the CP/M BIOS on the eZ80 side, is to initialise the SPI interface on cold boot, and divert all disk I/O requests for drives D:, E:, and F: to go through SPI.

This virtual disk I/O has been implemented in some 70 lines of (fairly dense) assembly code, and adds about 130 bytes to the size of the BIOS. There is no blocking or de-blocking involved, the eZ80 thinks these virtual disks are made up of 128-byte sectors. On the Blue Pill side, this gets turned into partial reads and writes of 512-byte blocks, as actually stored on SD cards.

A 4-byte sector read request packet on SPI looks as follows:

Bytes Content Notes
0 $20 + disk# only disks 3..5 are accepted, i.e. D: E: F:
1..3 24-bit sector# 0-based, converted from track/sector

The 128-byte read reply returned by the Blue Pill consists of:

Bytes Content Notes
0..127 sector data no error handling

A 132-byte sector write request packet looks like this:

Bytes Content Notes
0 $30 + disk# only disk 3 is accepted, i.e. D:
4..131 sector data comes immediately after the request details

And lastly, the write reply consists of a single byte:

Bytes Content Notes
0 error code always zero for now

For both reads and writes, the Blue Pill needs 1..3 milliseconds to perform the request.

As was expected, the eZ80 is the bottleneck in this process. Its SPI hardware only supports transfers up to 1/6th the clock rate, i.e. 1.33 MHz, and since all SPI transfers are driven by a software loop, there are in fact very substantial delays between each byte sent/received:

As you can see, the transfer rate is ≈ 33 µs/byte, i.e. 4.2 ms for a 128-byte sector. This is with the eZ80 running at 8 Mhz. Future clock speedups will reduce these SPI delays accordingly.

So for now, each sector read or write will take ≈ 6 ms, comparable to a traditional spinning hard disk, and substantially faster than floppy disk drives (which rotate at 300..360 RPM).

Weblog © Jean-Claude Wippler. Generated by Hugo.