Embedded HandbookApps
All sections › VI. Practice
STM32F411, STM32F407, STM32F429 · level intermediate · 11 min read
Open in the interactive handbook

41а. SD card over SDIO: four data lines, commands, DMA and FatFS

In section 41 the card is connected over SPI — four wires, any microcontroller, a speed of about 3 MB/s at best. The F4 (and the high-density F103) has its own SDIO block: it talks to the card in the card's native protocol, drives data over four lines at once, computes the checksums in hardware and feeds DMA. The same FatFS on top of it runs several times faster. The price is three extra wires, pull-ups and a startup protocol you need to understand when the card "is not detected".

The protocol rules, the divider formula, the FIFO structure and the DMA procedure are taken from the F4 reference manual (from the Keil pack); the startup command sequence is from the HAL 2.17.1 sources. Times, CRCs and dividers were recomputed by the program _verify/sdio41a/sdio_calc.c, built with gcc on a PC. The check is _verify/sdio41a_check.py.

Terms used in the documentation

Term Meaning
SDIO, SDMMC the block for SD/MMC cards (called SDMMC in newer families)
SDIO_CK, SDIO_CMD, SDIO_D0…D3 clock, command line, data lines
CPSM, DPSM the command and data state machines inside the block
command, response (R1…R7) a command and the card's answer
ACMD an "application" command — it comes after CMD55
OCR, CID, CSD, RCA, SCR card registers: power, identity, parameters, address, capabilities
SDSC, SDHC/SDXC standard-capacity and high-capacity card
block, DBLOCKSIZE a data block and the code for its size
wide bus four-bit mode

41а.1 How SDIO differs from a card over SPI

The card has two faces. In SPI mode it pretends to be an ordinary slave device: one line in, one line out, a chip select. In native mode it has a separate command line CMD, a clock CLK and up to four data lines D0…D3; bits go over all four at the same time. The SDIO block knows only the native mode — it has no SPI mode, and the manual says so directly.

What this gives at 24 MHz (the default working clock in HAL):

Mode One 512-byte block Data phase limit
SDIO, 1 line 4114 clocks — 171.4 µs 3.0 MB/s
SDIO, 4 lines 1042 clocks — 43.4 µs 11.8 MB/s
SPI at 25 Mbit/s ≈ 4100 clocks ≈ 3 MB/s

A block is a start bit, 4096 data bits, 16 CRC bits on each line and a stop bit: on four lines the data is divided by four, and the checksums are computed in parallel. Hence the almost fourfold gain.

That is the limit of the data transfer itself. The real throughput also includes the command and the response of 48 bits each, the card's access time before the first block, and for writes the time while the card holds D0 "busy": on cheap cards that is milliseconds per block. Only multi-block reads come close to the calculation.

An SDIO exchange: a 48-bit command with number, argument and CRC7 goes over the CMD line, then the card's 48-bit R1 response, also with CRC7; a 512-byte block goes over four lines D0…D3, 1024 bits on each, with a CRC16 on each line — start, 1024, 16 and stop give 1042 clocks, 43.4 µs and 11.8 MB/s at 24 MHz

Two more differences: checksums are always on — CRC7 for commands and responses, CRC16 for each data line, and the block computes them itself; and the lines are bidirectional and need pull-ups to the supply on all of D0…D3 and CMD — the manual requires external resistors on the data lines. Without them the card is silent or works only in one-bit mode.

The F411 has an SDIO block (the datasheet calls it "SD/MMC/eMMC"), and so do the F407 and F429; the BluePill on the F103C8 does not have one — only SPI there (section 41).


41а.2 Clock: the divider and two frequency modes

The card clock is derived from SDIOCLK by the divider in the CLKCR register:

SDIO_CK = SDIOCLK / (CLKDIV + 2)

SDIOCLK is the same 48 MHz used for USB (the manual: up to 50 MHz, 48 when working together with USB), so the PLL must deliver a true 48 MHz, otherwise the card gets the wrong frequency. There is also a divider bypass mode — then the card is clocked directly from SDIOCLK.

HAL keeps two dividers:

#define SDIO_INIT_CLK_DIV     ((uint8_t)0x76)    /* 48MHz / (SDMMC_INIT_CLK_DIV + 2) < 400KHz */
#define SDIO_TRANSFER_CLK_DIV ((uint8_t)0x0)     /* 48MHz / (SDMMC_TRANSFER_CLK_DIV + 2) < 25MHz */

0x76 is 118: 48 MHz / 120 = exactly 400 kHz, the limit for talking to the card during startup. 0 gives 48 / 2 = 24 MHz for data transfer. Starting at a low frequency is not a whim of HAL but a requirement of the card: at 24 MHz it will not answer the first commands, and the symptom will be "the card is not detected", with different cards behaving differently.


41а.3 Command and response

A command is always 48 bits on the CMD line: a start bit, a direction bit, 6 bits of command number, 32 bits of argument, CRC7 and a stop bit. Responses are short — also 48 bits — or long, 136 bits: that is how the card returns the CID and CSD registers. The hardware (the command state machine, CPSM) inserts the CRC7 itself and checks it in the response; the exception is the R3 power response, where the CRC field is filled with ones and is not checked.

The frames of the first commands are the same as those computed by hand in 18.10 for SPI mode: CMD0 — CRC 0x95, CMD8 with argument 0x1AA — 0x87. Only here they are computed by the block, not by the program.

The responses you meet during startup:

Response Length What it carries
R1 48 the command number and the card state
R2 136 CID (identity) or CSD (parameters)
R3 48 OCR: voltage window, readiness, SDHC flag
R6 48 the published RCA address
R7 48 the answer to CMD8: voltage and the echoed pattern

Some commands are application commands, ACMD: their number can be the same as an ordinary command (ACMD41, ACMD6, ACMD51), and the card tells them apart only by the fact that a CMD55 with its address came before them. Without CMD55 the card executes the same number as an ordinary command — or answers with an error.


41а.4 Starting the card: what HAL_SD_Init does

HAL_SD_Init calls HAL_SD_InitCard, and that contains the whole startup protocol, in the same order as over SPI in section 41, but with different responses:

  1. The block is set to 1 bit and SDIO_INIT_CLK_DIV, pin power and the clock are switched on, then a pause HAL_Delay(2) — the card needs time after the clock is applied.
  2. CMD0 — the card goes to the idle state.
  3. CMD8 with the pattern 0x1AA. If it answered, it is a version 2 card; if not, version 1, and CMD0 is repeated.
  4. CMD55 + ACMD41 in a loop — up to 0xFFFF attempts: the argument carries the voltage window and bit 0x40000000 "the host supports SDHC". In the response bit 31 means "ready"; while it is zero, the loop goes on. Bit 30 in a ready card's response is SDHC/SDXC, otherwise SDSC.
  5. CMD2 — the card returns its CID (136 bits), CMD3 — it publishes its RCA address.
  6. CMD9 with the RCA — the CSD: from it HAL computes the number of blocks and the capacity.
  7. CMD7 — select the card: it goes to the transfer state.
  8. CMD16 — block length 512.

After that HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) reads the SCR register (ACMD51, an 8-byte block), makes sure the card supports 4 bits, sends ACMD6 and reconfigures the block to four lines and the working divider. The order cannot be swapped: 4 bits are enabled only after the card is selected, and the frequency is raised only after startup.

Starting an SD card over SDIO: HAL_SD_Init on one line at 400 kHz goes through eight steps — setup, CMD0, CMD8 with the pattern 0x1AA, CMD55 and ACMD41 in a loop until ready, CMD2 and CMD3, CMD9, CMD7, CMD16; then HAL_SD_ConfigWideBusOperation switches on four lines and 24 MHz via ACMD51 and ACMD6

if (HAL_SD_Init(&hsd) != HAL_OK)                  /* 1 бит, 400 кГц, весь протокол */
    return -1;
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
    return -2;                                    /* 4 линии, 24 МГц */

In hsd.Init.BusWide itself you leave SDIO_BUS_WIDE_1B: right after CMD7 HAL reconfigures the block from hsd.Init — both the divider and the bus width. With SDIO_BUS_WIDE_4B there, the block would switch to four lines before the card (41а.7).

Capacity and addressing: on SDSC the address in read commands is a byte address, on SDHC/SDXC it is a block number; HAL hides this inside HAL_SD_ReadBlocks, and what you always see outside is a block number in 512-byte blocks.


41а.5 Data block, FIFO and DMA

Data travels in 512-byte blocks — exactly a FAT sector. In the data control register the size is encoded as a power of two: DBLOCKSIZE = 0x9 means 2⁹ = 512. Inside the block there is a FIFO of 32 words of 32 bits; the "half" flag — 8 words — serves as the DMA request. The CPU can read the FIFO (HAL_SD_ReadBlocks does exactly that), but at 24 MHz on four lines a word arrives every 333 ns, and the CPU is busy with nothing else.

The right way is DMA, and the manual gives an exact recipe for it: DMA2, stream 3 or stream 6, channel 4; 32-bit words; the peripheral is the flow controller (PFCTRL: the length is known by SDIO, not by DMA); bursts of 4 words at least on the peripheral side. The order when writing a block: start DMA, send CMD24, wait for CMDREND, enable the data state machine with DMAEN, wait for DBCKEND. HAL_SD_WriteBlocks_DMA and HAL_SD_ReadBlocks_DMA do this themselves; the program has to provide two handlers — SDIO_IRQHandler and the DMA stream interrupt — and a buffer aligned to 4 bytes.

The data checksums are CRC16 with polynomial 0x1021, one for each line. A block of 512 bytes of 0xFF on one line gives 0x7FA1 (in four-bit mode each line carries 128 bytes of 0xFF, and the per-line sum is 0xEDA9) — the number everyone who has written a card driver by hand uses to check their implementation; here the hardware computes it, and an error arrives as the DCRCFAIL flag. The second guard is the data timer DTIMER: if the card has not answered a read or holds the line "busy" longer than set, the block raises DTIMEOUT instead of waiting forever.


41а.6 FatFS on top of SDIO

The disk layer for FatFS (section 42) is the same five functions as for SPI, only with HAL inside them:

static volatile int rx_done;

void HAL_SD_RxCpltCallback(SD_HandleTypeDef *h) { (void)h; rx_done = 1; }

DRESULT disk_read(BYTE pdrv, BYTE *buf, LBA_t sector, UINT count)
{
    (void)pdrv;
    rx_done = 0;
    if (HAL_SD_ReadBlocks_DMA(&hsd, buf, (uint32_t)sector, count) != HAL_OK)
        return RES_ERROR;
    uint32_t t0 = HAL_GetTick();
    while (!rx_done)                                            /* DMA перенёс всё */
        if (HAL_GetTick() - t0 > 1000u) return RES_ERROR;
    while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)   /* карта снова готова */
        if (HAL_GetTick() - t0 > 1000u) return RES_ERROR;
    return RES_OK;
}

HAL_SD_ReadBlocks_DMA only starts the exchange and returns immediately. The end of the transfer is marked by the callback HAL_SD_RxCpltCallback: it is called from the DMA interrupt when the last word has landed in memory, and for multi-block reads HAL sends CMD12 itself before it. So you first wait for the callback and only then for the TRANSFER state: that state is about the card, not about memory — DMA may not yet have unloaded the tail of the FIFO, and polling with CMD13 in the middle of the exchange collides with the CMD12 from the interrupt. Both waits have a timeout, otherwise a removed card will hang the program forever.

disk_write works the same way, with HAL_SD_TxCpltCallback, and there the wait for TRANSFER is doubly mandatory: the card answers "accepted" before it has physically written the block, and the next command without this pause gets a "busy" error. The buffer from FatFS can be unaligned, while DMA needs an address that is a multiple of 4 (41а.5): you check ((uintptr_t)buf & 3) != 0 and in that case send the sectors one at a time through your own aligned buffer. The sector size is 512, the number of sectors comes from HAL_SD_GetCardInfo, LogBlockNbr. Everything else in FatFS does not depend on the bus.


41а.7 Pitfalls

Symptom Cause
the card does not answer at all no pull-ups on CMD and D0…D3 — the lines are bidirectional
works with 1 bit, CRC errors with 4 bits pull-ups only on D0; or D1…D3 are taken by another peripheral
HAL_SD_Init passed, but the very first read fails hsd.Init.BusWide is SDIO_BUS_WIDE_4B: after CMD7 HAL switched the block to four lines, while the card, without ACMD6, stayed on one
"not detected" on some cards, works on others startup at the working frequency right away instead of 400 kHz
the clock frequency is not what was calculated SDIOCLK comes from the 48 MHz PLL output, and that is not configured
ACMD41 loops until timeout no CMD55 before the application command; or a version 1 card that does not answer CMD8
DMA transfers garbage or hangs not stream 3/6 of DMA2, no PFCTRL, the buffer is not aligned to 4 bytes
a write returns "busy" every other time the next command before the card has gone to TRANSFER
disk_read returned success, but the buffer is incomplete you waited only for TRANSFER, not for the end-of-DMA callback
the card was removed and the program hangs waiting for the callback or for TRANSFER without a timeout
after a write the data reads back old the SDIO_IRQHandler and DMA stream handlers are not connected — the callbacks never arrive
CRC errors on long wires 24 MHz over a ribbon cable: lower it with the divider or shorten the wires
DCRCFAIL on writes with short wires the F4 has hardware flow control enabled (HWFC_EN, bit 14 of SDIO_CLKCR) or NEGEDGE: according to the errata both corrupt data — do not enable them
a reset when accessing the card current peak of up to 100 mA, no capacitor at the holder (section 41)

41а.8 Summary

Next: section 41б "FSMC and FMC: 8080 display, external SRAM and SDRAM" — a parallel bus on which external memory and a display become a range of addresses.

Open in the interactive handbook