SD/SDIO/eMMC 初始化:命令序列、总线宽度切换与控制器数据通路
更新时间:2026-09-19。前置:NAND 与 eMMC ECC、SPI 主机(SD 也有 SPI 模式,本文讲原生 SD/eMMC 模式)。
本文要回答的问题
- SD/eMMC 从上电到能读写,要发哪些命令、为什么有严格顺序?
- 为什么初始化必须用 ≤400kHz,之后又怎么提速?
- 1 位/4 位(eMMC 还有 8 位/DDR)总线怎么协商切换?
- 主机控制器的命令/数据通路、ADMA 描述符怎么组织?
一、SD 卡初始化序列
bash
上电(≥74 时钟,CMD/DAT 拉高)
CMD0 (GO_IDLE_STATE) → 软复位进 idle
CMD8 (SEND_IF_COND) → 探是否支持 VHS=2.7-3.6V / 版本2.0
├─ 无响应/非法 → V1.x 或 MMC,走老流程
└─ 有响应且 pattern 回显 → SD2.0/SDHC/SDXC
ACMD41 (SD_SEND_OP_COND, 需先 CMD55)
├─ 带 HCS(支持高容量) 位轮询
└─ 反复发直到 busy(HCS→CCS) 位 = 1(上电完成)
CMD2 (ALL_SEND_CID) → 读 CID
CMD3 (SEND_RELATIVE_ADDR) → 卡返回 RCA 地址
CMD9 (SEND_CSD, 带 RCA) → 读 CSD(容量/速率等级)
CMD7 (SELECT_CARD, 带 RCA) → 选中卡,进 Standby→Transfer
(可选)ACMD51 读 SCR → 判断支持位宽
ACMD6 (SET_BUS_WIDTH) = 0x2 → 切到 4-bit
CMD 切高速时钟(≤25/50/100MHz,UHS-I 更高)
CMD16 设块长(512) / CMD17/18 读 / CMD24/25 写关键握手:
- CMD8:区分老卡(V1/MMC)与新卡(SDHC/SDXC),并确认主机/卡电压一致。
- ACMD41:带 HCS 轮询,必须等卡内部上电初始化完成(busy 位变 1),不能只发一次。
- 容量解释:CCS=1 表示块寻址(SDHC/XC,地址单位=512B),老卡是字节寻址,直接乘会读错位置。
- 块长:SDHC/XC 固定 512 字节块。
二、eMMC 的差异
- 用 CMD1(不是 ACMD41)做 OCR 协商,支持 1.8/3V 双电压与 BUSY。
- 用 CMD0 + 0xF0F0F0F0 参数进 boot,支持 boot partitions(CMD0 alternate boot、EXT_CSD)。
- 标识用 CMD2/3,但相对地址可由主机分配;配置走 EXT_CSD(CMD8) 扩展寄存器。
- 总线宽度可达 8-bit(DAT0–7),支持 HS200/HS400(SDR/DDR,最高 200/400MB/s 级),HS400 需先在 HS200 调谐(tuning)。
三、总线宽度与时钟切换
- 识别阶段强制 ≤400kHz:保证不同工艺/电压的卡都能正确收到初始命令;进数据模式后才提时钟。
- 宽度是双方协商:主机从 SCR/EXT_CSD 知道卡能力,再用 ACMD6(SD)/SWITCH(eMMC CMD6)命令切换,硬件 DAT3-7 引脚才开始使用。
- DDR 模式双沿采样,需要对端支持且电压/时钟合规。
- 高速模式可能需要**调谐(tuning,CMD19/CMD21)**找最佳采样点。
四、控制器数据通路
bash
命令路径: 主机命令寄存器 → CMD 线(带CRC) → 卡响应 → 响应FIFO
数据路径: DAT0..7/DS
读: 卡→DAT(块+CRC+停止位)→接收FIFO→ADMA→内存
写: 内存→ADMA→发送FIFO→DAT
单块/多块(CMD18/25)、停止 CMD12、忙信号 DAT0 拉低- 每条数据块带 CRC16(SD),控制器硬件校验,错则重传/报错。
- ADMA/SDMA:控制器用描述符做散列传输,与 DMA 描述符环同类,注意 对齐与 cache 同步。
- DAT0 在写后/擦除期间被卡拉低表示 busy,控制器/驱动要等其释放。
五、常见的坑
- 识别时钟太快:一上来给 25/50MHz,老卡无响应;先 400kHz。
- 不发 CMD8 直接 ACMD41:无法识别高容量卡,电压协商错。
- ACMD41 没轮询 busy:只发一次就继续,卡没上电完成导致后续超时。
- ACMD 前漏 CMD55:ACMD41/ACMD6 必须先发 CMD55 标志下一命令是应用命令。
- 字节寻址/块寻址混用:SDHC 用块地址,套老卡字节偏移读到错位置。
- 只置控制器位宽不发 ACMD6:卡仍 1-bit 模式,4-bit 接线却收不到数据。
- 切宽度/电压时序错:UHS 切 1.8V 需 CMD11 握手,硬件稳压器没切导致掉线。
- 忽略 busy(DAT0):写/擦未完成就发下一条,命令被卡拒绝。
- CRC 错误当卡坏:多为信号完整性(走线、上拉、速度过快未调谐)。
- DMA 缓冲未对齐/未刷 cache:数据错位或读到旧值,见 DMA 一致性。
- eMMC 用 SD 命令:把 ACMD41 当 CMD1、不读 EXT_CSD,8-bit/HS400 配不上。
- SDIO 中断/IO 初始化遗漏 CMD5:SDIO 卡要用 CMD5 操作 OCR/IO 使能,与存储卡流程不同。
相关与延伸
存储与纠错见 NAND/eMMC ECC;SPI 模式见 SPI 主机;DMA 见 描述符环、突发对齐与 cache。
总结
SD/eMMC 必须先在 ≤400kHz 识别时钟下按顺序握手:SD 走 CMD0→CMD8 探版本/电压→带 HCS 轮询 ACMD41 等 busy→CMD2/3/9 取 CID/CSD→CMD7 选中→ACMD6 协商 4-bit,再提时钟到高速并做可能的 tuning;eMMC 用 CMD1、EXT_CSD、可 8-bit/HS400;高容量卡是块寻址不是字节寻址,数据走 DAT+CRC+FIFO+ADMA 并等 DAT0 busy——识别时钟过快、ACMD41 不等 busy、只改控制器不发宽度命令和字节/块地址混用是四大坑。