eMMC 总线协议基础:命令、响应、数据传输

大家好。这一章我们来聊聊 eMMC 总线上到底在跑什么东西。说白了,Host 和 Device 之间就靠三组信号线打交道——命令线(CMD)、响应线(RESP)、数据线(DAT)。这三条“线”怎么用、什么时候用、用错了会怎样,是入门 HS400 的前提。

我记得刚开始做 eMMC 驱动时,总以为命令和数据是同时跑的。结果一上示波器,发现命令发完好久才等到响应……嗯,这里门道不少。下面我把它们拆开讲清楚。

1. 三根信号线,各司其职

先看一张总图,把这章的脉络印在脑子里:

eMMC总线协议框架 eMMC 总线协议框架 Host Controller eMMC Device CMD RESP DAT[7:0] 说明: • CMD:Host 发命令,Device 也可发指令(如忙信号)。 • RESP:Device 在固定时钟周期内返回响应,Host 必须采样。 • DAT:数据线,1/4/8 位可选,HS400 强制 8 位双沿。 • 所有事务都由 Host 发起,Device 不可主动发数据。

从图里你能看到:CMD 线是双向的,但绝大多数时候是 Host 在说;RESP 线是单向,Device 回应;DAT 线多条,走实际数据。为什么要画成双向箭头?我遇到过有人以为 CMD 只能 Host 发——其实 Device 也能在 CMD 上发 busy 信号,但规则很严格。

个人小经验: 调试时优先抓 CMD 和 RESP 的波形。如果命令发出去没有响应回来,八成是初始化时序不对。我曾经在某款方案上就是因为 CMD 线上的上拉电阻没焊,导致 Device 根本无法识别命令。

2. 命令(CMD)——Host 的“指令牌”

eMMC 命令的格式很固定。每个命令 48 位,结构如下:

位域 宽度 说明
起始位 1 bit 固定为 0
传输方向 1 bit Host→Device 为 1
命令索引 6 bits CMD0 ~ CMD63
参数 32 bits 具体含义依赖命令
CRC7 7 bits 校验命令本身
结束位 1 bit 固定为 1

你想想看,48 位里真正管事的只有命令索引和参数。比如 CMD1(发送操作条件)的参数就是 OCR 寄存器里的电压信息。我个人习惯把常用命令编个表贴在调试台前,省得每次都翻 spec。

核心要点: 命令的 CRC7 只校验命令本身,不校验后面跟的数据。数据有单独的 CRC16/CRC7 保护。我曾经见过有人把命令 CRC 当作数据 CRC 来算,结果总超时……

3. 响应(RESP)——Device 的“回执”

Device 收到命令后,必须在 64 个时钟周期内返回响应,否则 Host 就认为超时,重发或报错。响应类型有 R1、R1b、R2、R3、R4、R5 等,最常用的是 R1 和 R2。

咱们拿 R1 举例:它也是 48 位,结构几乎和命令一样,但传输方向位是 0(Device→Host),而且参数区域变成了状态位。R1 的 32 位参数里包含了错误标志(如地址错误、CRC 错误)、当前状态、卡识别等。

  • R1(48 位):普通命令响应,带状态信息。
  • R1b(48 位 + busy 信号):R1 基础上,Device 拉低 DAT0 表示忙。
  • R2(136 位):CID 或 CSD 寄存器内容,发送时实际分 2 个时钟周期。
  • R3(48 位):OCR 寄存器内容,仅用于 CMD1。
避坑指南: 我曾经在一个项目里忽略了 R1b 的 busy 检测,连续发了好几笔命令,结果 Device 还没就绪,响应全乱套了。记住:R1b 必须在 DAT0 拉高后再发下一个命令。

4. 数据传输——DAT 线上的搬运工

数据流通过 DAT[7:0] 线传输。eMMC 5.1 支持单线、4 线、8 线模式。HS400 强制使用 8 线双沿(DDR)模式,也就是每个时钟沿都传数据。

数据传输分为两种基本类型:

  • 块传输(Block Transfer):固定大小块,默认 512 字节,可通过 CMD16 设置。
  • 流传输(Stream Transfer):连续数据,无固定块边界(早期 MMC 支持,eMMC 已废弃)。

写数据的典型流程:Host 发写命令(CMD24/CMD25)→ Device 返回 R1 → Host 发数据块(带 CRC16)→ Device 回复 CRC 状态 → 最后 Device 拉低 DAT0 表示忙。

读数据类似:Host 发读命令(CMD17/CMD18)→ Device 返回 R1 + 数据块 + CRC16 → Host 检查 CRC。

小提示: HS400 模式下数据采样由时钟上升沿和下降沿共同完成,相当于双倍传输速率。但这也意味着对时钟抖动和信号完整性要求更高。我在某款 4K 录像设备的 eMMC 调试中,就是因为在 8 位模式下有一根 DAT 线时序不够,导致写入偶发 CRC 错误——找了好久才定位到是 PCB 走线长度差太大。

5. 信号时序与状态机

eMMC 设备内部有一个有限状态机,从上电 idle 开始,经过初始化、识别、传输等状态。命令只能在特定状态下执行。比如 CMD6(切换功能)只能在 transfer state 下发。我在刚学的时候把 CMD2(获取 CID)在 transfer 状态下发,当然没反应……

不多展开状态机细节,但记住一条:命令和状态是绑定的。调程序时先读一遍状态,再决定发什么命令。

注意: 数据线上有 CRC 保护。接收方发现 CRC 错误后会不返回 CRC 状态,Host 侧会超时重发。我曾经在驱动里忘了开启 CRC 校验,结果数据写进去了但读出来全是错的——被坑得很惨。

6. 小结几个容易忘的点

  1. CMD 线是开漏/推挽模式切换的。初始化阶段开漏,之后切换成推挽。
  2. 响应必须在 64 个时钟内到达,否则视为超时。
  3. 数据块大小默认为 512 字节,但可以通过 CMD16 改变,不过 HS400 模式下建议用 512 对齐。
  4. DAT0 线除了传数据,还用于 busy 指示。Device 拉低 DAT0 时,Host 必须等待。

这章基础必须打牢。后面讲 HS400 切换、时钟配置、校准流程时,都会用到这里的命令-响应-数据流模型。嗯,今天就到这儿。