4. SDIO 命令与响应机制归纳总结

SDIO 协议里,命令和响应就是主机和设备之间对话的基本单元。

说白了,你想想看,主机想干什么,就得先发一个命令。设备听到了,要么照做,要么回一个响应告诉你“我知道了”或者“我干不了”。

我刚开始学 SDIO 的时候,也是被这一堆命令搞得头疼。但后来做测试做多了,说白了就那么几类。

这章我把命令和响应机制给你捋清楚。特别是那些容易踩坑的地方。

4.1 命令结构——主机说了算

SDIO 命令一共 48 位,主机通过 CMD 线串行发出去。

结构其实很简单:

  • 第 1 位:起始位,固定为 0
  • 第 2 位:传输方向位,固定为 1(表示主机→设备)
  • 第 3–14 位(12 位):命令索引,也就是 CMD0、CMD5 这种编号
  • 第 15–46 位(32 位):参数,具体含义看命令定义
  • 第 47–48 位(7 位):CRC7 校验
避坑提醒
CRC7 必须正确。我在实际测试中遇到过,主机发的命令参数全对,但 CRC7 算错了,设备根本不认。

4.2 命令分类——四大金刚

你可能觉得 59 个命令很多。但常用的,说实话,也就那么几个。

我按功能分成四大类,这样好记:

类别 典型命令 干啥用的 我的经验
广播命令 CMD0、CMD2 对所有设备发,不期待响应 CMD0 我用来复位所有设备
寻址命令 CMD3、CMD7、CMD45 指定 RCA 或地址,期待响应 CMD3 分配 RCA,这个命令一定要耐心等
数据传输命令 CMD17、CMD18、CMD24、CMD25 启动读/写操作,配合 DAT 线用 CMD18 多块读,我曾经遇到过 CRC 错
I/O 命令 CMD52、CMD53 读写卡内寄存器或 FIFO CMD52 最常用,但 CMD53 更快

4.3 响应机制——设备怎么回话

设备收到命令后,大部分情况都要回一个响应。

响应也是 48 位,格式跟命令挺像,但方向和校验方法不一样。

常用的响应类型

  • R1(正常响应):最常见。包含卡状态。你解读状态位的时候,要小心。
  • R2(CID/CSD 响应):长响应,136 位。用来拿设备的身份和参数。
  • R3(OCR 响应):固定为 0x00FF8000,告诉你电压范围。
  • R4/R5(I/O 响应):用于 CMD52/CMD53,包含读写的数据和状态。
我个人习惯
调试时,我习惯用示波器抓 CMD 线的波形。一看响应里的 CRC 状态位,马上就知道有没有错误。

4.4 状态机与状态流转——主机和设备的配合

SDIO 协议里,主机和设备各自都有状态机。

主机发命令,设备根据当前状态,要么进入新状态,要么报错。

我画了张图,帮你把命令和响应的状态流转搞清楚:

SDIO 命令-响应状态流转 主机发送命令 设备接收命令 CMD0/CMD15 其他命令 无响应(广播命令) 设备准备响应 状态保持/进入 Idle R1/R2/R3/R4/R5 主机解析响应状态

这张图表达的核心是:

  • 主机发命令后,设备必须根据命令类型决定是否回响应
  • 广播命令(如 CMD0、CMD15)不期待响应
  • 其他命令都需要 R1/R2/R3 等响应
  • 如果响应超时或者 CRC 错,主机一般会重试或者报错

4.5 命令与响应的时序参数

协议里规定了几个关键的时序参数,你一定要知道:

参数 最小值 最大值 说明 我踩过的坑
NCR 0 8 个时钟周期 命令到响应的延迟 有些低速卡 NCR 会到 8
NAC 0 100 ms 数据访问时间 曾经遇到过 NAC 超时,最后发现是卡坏道
NRO 0 64 个时钟周期 读操作结束到停止命令 DMA 传输如果 NRO 没给够,会丢数据
NRAC 0 5 个时钟周期 读操作重发延迟 高速模式下这个参数容易错

4.6 常见问题和验证技巧

经验之谈:响应超时
你调试的时候,如果发现卡不回复响应。别急着怀疑卡坏了。
先检查 CMD 线上的 CRC7 算对了没有。我曾经有一次,就是 CRC 多算了 1 位,浪费了半天。

怎么验证命令和响应机制?

  1. 先确认基本时序:用示波器抓 CMD 线,看 NCR 是否小于等于 8 个时钟
  2. 检查响应内容:用逻辑分析仪解析 R1 状态位,确认没有错误标志
  3. 验证每个状态流转:比如发 CMD7 选择卡,确认卡从 Standby 进入 Transfer
  4. 做边界测试:故意让主机早发命令,看卡是否处理

4.7 本章小结

命令和响应机制,是 SDIO 通信的基石。

你只要理解了命令结构、响应类型和状态流转,调试起来就会顺手很多。

我建议你上手的时候,先把 CMD0、CMD5、CMD3、CMD7 这几个走一遍。自己用逻辑分析仪看看波形。很快就熟了。

嗯,这里要注意,本章没有涉及数据传输。那些多发命令和读/写操作,我们在后面专门再聊。