Step 28 of 56
SD cards: two hosts, one API shape
The universal SPI transport and the native SD bus — different speeds, different profile requirements, and the same 512-byte logical block interface.
Two routes to the same card
SD_SPI | SDMMC | |
|---|---|---|
| Bus | The SPI master, 4 lines | The real SD bus: clock, bidirectional command line, 1 or 4 data lines |
| Data path | Through SPI (and its GDMA) | PIO/FIFO — the CPU pushes each 512-byte block through the controller's FIFO |
| Speed | Lower | Faster; how you reach an SDHC/SDXC card at speed |
| Profile | embedded / full only (uses the SPI Session's finalization) | every profile, light-tasking included |
That last row is the surprise, and it falls out of the implementation: because
SDMMC moves data in PIO with no GDMA and no descriptors, it needs no
finalization — a library-level protected object serialises the single
shared controller. So the faster host is also the one available on the
lean runtime.
The shared API shape
type Block is array (0 .. 511) of Interfaces.Unsigned_8;
type Block_Address is new Interfaces.Unsigned_32;
Both are addressed in 512-byte logical blocks (LBA), always.
SDHC and SDXC cards use block addressing while older SDSC cards use byte
addressing; that difference is resolved inside the driver, so it never reaches
your code. Both also initialise the card at ≤400 kHz as the SD specification
requires, then switch to Data_Clock_Hz — which is precisely
what SPI's Set_Clock mid-hold exists
for.
Why SD-over-SPI needs a GPIO chip select
The chip select is driven as a plain GPIO, not
the SPI peripheral's hardware CS. The SD protocol needs CS held asserted across a
whole command / response / data sequence, and the peripheral's own CS pulses per
transfer — which the protocol cannot use. This is the concrete case behind
the CS_Pin option on SPI's
Acquire.
SD_SPI layers the SD "SPI mode" command protocol on top of the
task-safe SPI master: CMD0, CMD8, CMD58, ACMD41, CMD17, CMD24 and CRC7. Every
operation takes the SPI host's session for the whole transaction, so concurrent
callers serialise.
type Card_Kind is (Unknown, SD_V1, SD_V2_SC, SD_V2_HC);
SDMMC has two slots (Slot1, Slot2), one
card each, and a selectable Bus_Width of Width_1 or
Width_4. Its lines route through the GPIO matrix, so any free pins
will do.
Both drivers are marked in the repository's testing table as compiles, no-card smoke test only. They are the ones to verify against a real card before relying on them — see step 11.