1. 概述
eMMC(embedded Multi Media Card)是 JEDEC 制定的嵌入式存储标准(JESD84 系列,目前常见 eMMC 5.1)。主机与 eMMC 之间通过以下信号通信:
| 信号 | 方向 | 说明 |
|---|---|---|
| CLK | 主机 → 设备 | 时钟信号,命令和数据都在其上升沿被采样 |
| CMD | 双向(半双工) | 用于传输命令和应答,同一时刻只能有一个方向发送 |
| DAT0 ~ DAT7 | 双向 | 数据线,可工作于 x1 / x4 / x8 模式 |
所有命令与应答都通过 CMD 线以位流形式传输:主机发命令(主机 → 设备),设备回应答(设备 → 主机)。命令格式和应答格式本质上都是 48 位的一帧,唯一的方向标志就是传输位。下面逐一拆解每一帧里每一位的作用。
2. 命令请求格式(48 位)
主机发往设备的命令固定为 48 位,高位先发(MSB first),位布局如下:
|
|
各字段作用:
| 字段 | 位 | 宽度 | 作用 |
|---|---|---|---|
| 起始位 Start Bit | bit47 | 1 | 固定为 0,标志一帧的开始,接收方靠它识别帧边界 |
| 传输位 Transmission Bit | bit46 | 1 | 1 表示主机 → 设备(命令方向);应答时此位为 0 |
| 命令索引 Command Index | bit45 ~ bit40 | 6 | 命令号,范围 0 ~ 63(6 位可表示 64 个命令,如 CMD8 的二进制为 001000) |
| 参数 Argument | bit39 ~ bit8 | 32 | 命令携带的参数,具体含义随命令而定(见第 7 节) |
| CRC7 | bit7 ~ bit1 | 7 | 对"命令索引 + 参数"共 38 位计算的 CRC 校验值(见第 8 节) |
| 结束位 End Bit | bit0 | 1 | 固定为 1,标志一帧的结束 |
3. 应答格式(48 位)
设备对大部分命令会返回 48 位应答,其结构与命令格式几乎一样,唯一区别是传输位为 0(设备 → 主机),且 bit39 ~ bit8 不再是参数,而是应答内容(随应答类型解释,如 Card Status、OCR、RCA 等):
|
|
| 字段 | 位 | 作用 |
|---|---|---|
| 起始位 | bit47 | 固定 0 |
| 传输位 | bit46 | 0 = 设备 → 主机(应答方向) |
| 命令索引 | bit45 ~ bit40 | 回显本次应答对应的是哪条命令 |
| 应答内容 | bit39 ~ bit8 | 32 位,按应答类型解释(R1/R3/R6/R7 等) |
| CRC7 | bit7 ~ bit1 | 对"索引 + 应答内容"38 位的校验值 |
| 结束位 | bit0 | 固定 1 |
4. R2 长应答(136 位)
CID(CMD2 / CMD10 返回)和 CSD(CMD9 返回)寄存器本身是 128 位,装不进 48 位应答,因此 R2 应答是 136 位的长格式:
|
|
| 字段 | 位 | 说明 |
|---|---|---|
| 起始位 + 传输位 | bit135 ~ bit134 | 00 |
| 保留位 | bit133 ~ bit128 | 6 位,全部为 0 |
| CID / CSD 内容 | bit127 ~ bit8 | 120 位。寄存器低 8 位(bit7 ~ bit0)是寄存器自身的 CRC7 和结束位,不随应答传出,所以只传 [127:8] |
| CRC7 | bit7 ~ bit1 | 对上面 120 位内容计算的校验值 |
| 结束位 | bit0 | 固定 1 |
5. 响应类型(R1 ~ R7)
| 类型 | 长度 | 应答内容 | 典型命令 |
|---|---|---|---|
| R1 | 48 位 | 32 位 Card Status(卡状态寄存器) | CMD13、CMD55 等 |
| R1b | 48 位 + busy | 同 R1,应答后 DAT0 拉低表示忙 | CMD6、CMD12、CMD38 |
| R2 | 136 位 | CID 或 CSD 寄存器内容 | CMD2、CMD9、CMD10 |
| R3 | 48 位 | OCR 寄存器(操作条件) | CMD1 |
| R6 | 48 位 | RCA[31:16] + 卡状态[15:0] | CMD3 |
| R7 | 48 位 | 回显接口条件(电压 + 校验模式) | CMD8 |
关于 R1b 的忙信号:R1b 应答之后,设备会在 DAT0 上持续输出低电平表示"忙",主机必须等待忙信号结束才能发起下一条命令。实际驱动中常用 CMD13(SEND_STATUS)轮询设备状态,直到 READY_FOR_DATA 置位或设备进入目标状态。
6. R1 应答:Card Status 字段详解
R1 应答的 32 位内容就是卡的状态寄存器,是调试时最常解析的字段:
| 位 | 名称 | 类型 | 作用 |
|---|---|---|---|
| 31 | OUT_OF_RANGE | R | 命令参数超出设备支持范围(如地址越界) |
| 30 | ADDRESS_ERROR | R | 地址未对齐(例如不是块边界对齐) |
| 29 | BLOCK_LEN_ERROR | R | 块长度不支持 |
| 28 | ERASE_SEQ_ERROR | R | 擦除序列错误 |
| 27 | ERASE_PARAM | R | 擦除参数无效 |
| 26 | WP_VIOLATION | R | 尝试写入写保护区域 |
| 25 | CARD_IS_LOCKED | R | 卡处于锁定状态 |
| 24 | LOCK_UNLOCK_FAILED | R | 锁定/解锁操作失败 |
| 23 | COM_CRC_ERROR | E | 上一次命令 CRC 校验失败(总线传输错误) |
| 22 | ILLEGAL_COMMAND | E | 命令非法(设备不支持或当前状态下不允许) |
| 21 | DEVICE_ECC_FAILED | E | 设备内部 ECC 纠错失败 |
| 20 | CC_ERROR | E | 内部控制电路错误 |
| 19 | ERROR | E | 一般性错误 |
| 18 | UNDERRUN | E | 数据下溢(多块读时数据供应不及时) |
| 17 | OVERRUN | E | 数据上溢(多块写时数据接收不及时) |
| 16 | CID/CSD_OVERWRITE | E | CID/CSD 寄存器被改写 |
| 15 | WP_ERASE_SKIP | E | 因写保护跳过部分擦除区域 |
| 14 | CARD_ECC_DISABLED | E | ECC 被禁用 |
| 13 | ERASE_RESET | E | 擦除序列被重置 |
| 12:9 | CURRENT_STATE | X | 设备当前状态(见下表) |
| 8 | READY_FOR_DATA | X | 1 表示设备可收发数据 |
| 7 | SWITCH_ERROR | E | 模式切换(CMD6)失败 |
| 6 | EXCEPTION_EVENT | X | 异常事件标志,配合 EXT_CSD 的 EXCEPTION_EVENTS_STATUS 使用 |
| 5 | APP_CMD | X | 1 表示下一条命令将按 ACMD(应用命令)解释 |
| 4:0 | Reserved | — | 保留 |
类型说明:R 类错误位在命令执行时更新;E 类错误位在主机读取后清除;X 类为状态位,实时反映当前状态。
CURRENT_STATE(bit12:9)取值:
| 值 | 状态 | 说明 |
|---|---|---|
| 0 | idle | 空闲(上电或 CMD0 复位后) |
| 1 | ready | 就绪,等待识别 |
| 2 | ident | 识别中(CMD2/CMD3 阶段) |
| 3 | stby | 待机,已分配 RCA |
| 4 | tran | 数据传输状态(读写命令都在此状态下发出) |
| 5 | data | 数据接收中 |
| 6 | rcv | 数据发送中 |
| 7 | prg | 编程中(写入/擦除进行中) |
| 8 | dis | 断开(CMD7 取消选中) |
| 9 ~ 15 | — | 保留 |
驱动调试时最常见的场景:发完 CMD24(写)后卡停留在 prg 状态,说明上一次写操作还没完成;发命令后返回 ILLEGAL_COMMAND,则要检查命令是否在正确状态下发出(例如未完成初始化就发读写命令)。
7. 常见命令 Argument 参数作用
| 命令 | 名称 | Argument 作用 | 应答 |
|---|---|---|---|
| CMD0 | GO_IDLE_STATE | 无参数(全 0),复位设备到 idle 状态 | 无 |
| CMD1 | SEND_OP_COND | 主机 OCR:bit30 = HCS(高容量支持),bit29:24 = 电压窗口;设备在 R3 应答中回传自己的 OCR | R3 |
| CMD2 | ALL_SEND_CID | 无参数 | R2(CID) |
| CMD3 | SEND_RELATIVE_ADDR | 无参数;设备在 R6 应答中分配并返回自己的 RCA | R6 |
| CMD6 | SWITCH | 模式切换 / EXT_CSD 字节读写(见下方展开) | R1b |
| CMD7 | SELECT_CARD | RCA[15:0]:选中该 RCA 的设备进入 tran 状态;RCA 为 0 表示取消选中 | R1b |
| CMD8 | SEND_EXT_CSD | 无参数;应答后 DAT 上再传输 512 字节 EXT_CSD | R1 + 数据 |
| CMD9 | SEND_CSD | RCA[15:0]:指定要读 CSD 的设备 | R2(CSD) |
| CMD10 | SEND_CID | RCA[15:0]:指定要读 CID 的设备 | R2(CID) |
| CMD12 | STOP_TRANSMISSION | 无参数,中止正在进行的多块读写 | R1b |
| CMD13 | SEND_STATUS | RCA[15:0]:查询指定设备的状态 | R1(Card Status) |
| CMD16 | SET_BLOCKLEN | 块长度(如 512) | R1 |
| CMD17 | READ_SINGLE_BLOCK | 数据起始字节地址[31:0](须块对齐) | R1 + 数据 |
| CMD18 | READ_MULTIPLE_BLOCK | 数据起始字节地址[31:0] | R1 + 数据 |
| CMD23 | SET_BLOCK_COUNT | 块数[31:0](bit31 必须为 0),限定后续 CMD18/CMD25 传输的块数 | R1 |
| CMD24 | WRITE_BLOCK | 数据起始字节地址[31:0] | R1 + 数据 |
| CMD25 | WRITE_MULTIPLE_BLOCK | 数据起始字节地址[31:0] | R1 + 数据 |
| CMD38 | ERASE | 无参数(擦除范围由 CMD35/CMD36 的起始/结束地址设定) | R1b |
| CMD55 | APP_CMD | RCA[15:0];执行成功后设备状态寄存器 APP_CMD 位置 1,下一条命令按 ACMD 解释 | R1 |
| CMD56 | GEN_CMD | bit0:1 = 读、0 = 写;bit25:1 = 块偏移(块内传输,不经过地址映射) | R1 + 数据 |
几个需要展开的关键参数:
CMD1 的 OCR 参数:bit30 = HCS(Host Capacity Support,高容量支持,1 表示主机支持块寻址);bit29:24 = 电压窗口(如 110000 表示支持 2.7V ~ 3.6V)。设备在 R3 应答中返回自己的 OCR,其中 bit31 表示设备是否完成上电(busy 标志),初始化代码通常循环发 CMD1 直到该位置 1 且电压窗口匹配。
CMD6 的 SWITCH 参数(eMMC 5.1,Linux 内核 mmc_switch() 即按此编码):
|
|
| 字段 | 位 | 作用 |
|---|---|---|
| Access(访问模式) | bit25:24 | 00 = Command Set(按 Cmd Set 切换命令集);01 = Set Bits(按 Value 中为 1 的位置位);10 = Clear Bits(按 Value 中为 1 的位清零);11 = Write Byte(把 Value 写入指定字节) |
| Index | bit23:16 | EXT_CSD 字节偏移(0 ~ 191 有效;192 ~ 255 非法,设备不改写并置 SWITCH_ERROR) |
| Value | bit15:8 | 要写入/设置的 8 位值 |
| Cmd Set | bit2:0 | 命令集编号,默认 0 |
例如切换 HS400 模式(写 EXT_CSD byte 197)就是:arg = (0b11 << 24) | (197 << 16) | (value << 8),即 Write Byte 模式写偏移 197 的字节。CMD6 的应答是 R1b,写完后需等待忙结束,再用 CMD13 轮询确认 SWITCH_ERROR 没有置位。
CMD55 与 ACMD 机制:eMMC 很多功能命令(如 CMD6 的扩展、CMD22 等)以 ACMD 形式出现。发送 CMD55 后,设备状态寄存器的 APP_CMD 位置 1,此时紧接着发的下一条命令就按 ACMD 解释,并且这条命令的索引可以大于 63(因为 ACMD 用 CMD6/CMD56 等通道复用)。ACMD 结束后 APP_CMD 位自动清零。
RCA(相对卡地址):CMD3 应答(R6)的 bit31:16 就是设备被分配的 RCA(1 ~ 65535 范围内的某个值,0 表示未分配/取消)。之后 CMD7/CMD9/CMD13 等命令都靠 RCA[15:0] 指定目标设备——eMMC 是单设备总线,但规范保留了多设备编址能力。
8. CRC7 校验
命令与应答帧中的 CRC7 字段用于检测总线传输错误:
- 多项式:x⁷ + x³ + 1(即 0x89),初始值为 0,MSB 先出
- 覆盖范围:命令帧覆盖"索引 + 参数"共 38 位;R2 长应答覆盖 120 位 CID/CSD 内容
- 校验失败:设备认为命令无效并丢弃;主机侧则由控制器硬件校验应答,若失败会在状态寄存器置
COM_CRC_ERROR(bit23)
需要注意的是,这个 CRC7 只保护 CMD 线上的命令/应答帧,不保护 DAT 线上的数据——数据块的完整性由数据 CRC16 单独保证(x16 + x12 + x5 + 1,即 0x1021)。
9. 参考
- JEDEC JESD84-B51(eMMC 5.1 规范),命令格式见 §6.10,响应格式与 Card Status 见 §6.12/§6.13
- Linux 内核:
include/linux/mmc/mmc.h(R1 状态位定义)、drivers/mmc/core/mmc_ops.c(CMD6 参数编码mmc_switch()) - SD/MMC 协议相关参考手册(如 GD32、NXP 系列控制器手册中的命令定义表)