3. SDIO命令与响应机制

命令与响应是 SDIO 协议的核心骨架。说白了,每一次数据传输都靠一条命令“发号施令”,然后设备给出响应,告诉你“收到”或“出错”。这一节我们把它们拆开揉碎,看看里面到底藏着哪些坑。

SDIO 命令与响应交互模型 主机 (Host) CMD 线 命令格式 起始位 + 方向 + 命令索引 + 参数(32位) + CRC7 + 结束位 寻址命令 (CMD + RCA) 广播命令 (无响应) SDIO 设备 响应线 (Data0) 响应格式 起始位 + 方向 + 命令索引 + 状态/数据 + CRC R1 / R1b / R2 … R3 / R4 / R5 / R6 ⚠ 避坑要点 • 响应超时检查:NCR 最大 64 时钟 • CRC7 错误可能因总线电容过大 • 无响应时检查 CMD 线方向配置

1. 命令格式:48 位定长帧

每条 SDIO 命令都是 48 位长,通过 CMD 线串行发送。我习惯把这 48 位拆成 6 个部分记:

  • 起始位(1 位):固定为 0,告诉设备“要发命令了”。
  • 方向位(1 位):主机→设备为 1,设备→主机为 0。
  • 命令索引(6 位):0~63,比如 CMD5 就是 000101。
  • 参数(32 位):具体含义看命令类型,比如 RCA、地址、块数等。
  • CRC7(7 位):对前面 40 位做校验,生成多项式是 x⁷ + x³ + 1。
  • 结束位(1 位):固定为 1,收尾。

注意一点:CRC7 并不覆盖方向位和起始位,只覆盖命令索引+参数。我在项目中遇到过 CRC 错误导致设备不响应,查了半天发现是 PCB 走线太长,信号反射把最后几位冲坏了。

调试小技巧:
用示波器抓 CMD 线时,先找 48 位波形。如果看到的位宽不对,先检查 Host 端的时钟频率是否超了设备支持上限。SDIO 设备在初始化阶段只能运行在 0~400kHz,很多新人上来就跑 25MHz,设备压根不认识命令。

2. 命令类型:广播 vs 寻址

SDIO 的命令按寻址方式分成两大类:

类型说明典型命令
bc (broadcast)广播命令,无响应。所有设备都能收到,但不用回答。CMD0 (GO_IDLE_STATE)
bcr (broadcast with response)广播带响应,所有设备在 Data0 线上同时发响应?——实际上 SDIO 不常用 bcr,SD 卡用 CMD2 时所有卡串行应答。
ac (addressed)点对点命令,需指定 RCA(相对卡地址)。设备返回响应。CMD7 (SELECT/DESELECT_CARD)
adtc (addressed data transfer)带数据传输的寻址命令,CMD 后跟数据块。CMD53 (IO_RW_EXTENDED)

我用 CMD3(SET_RELATIVE_ADDR)给每个 SDIO 设备分配 RCA,之后所有命令都带 RCA 参数。你想想看,如果没有 RCA,多个设备怎么区分?

3. 响应类型:R1~R6 与 SDIO 专属响应

响应长度有 48 位(短响应)和 136 位(长响应)。SDIO 协议主要用短响应,R1 最常见:

  • R1:48 位,包含卡状态字段。正常响应标志位为 0,出错则置位对应位。比如“Command CRC Error”位是 3,“Illegal Command”位是 5。
  • R1b:跟 R1 一样,但之后总线会保持忙信号(Data0 被拉低)。CMD7 选卡时经常遇到 R1b,如果卡正在忙,会一直拉着 Data0 不放。
  • R2:136 位,用于 CID/CSD 读取。SDIO 里较少用,但部分卡会返回。
  • R3:48 位,只用于 OCR 寄存器读取,没有 CRC 校验(因为 OCR 靠硬件冗余保护)。
  • R4:SDIO 专用,用于 CMD5(IO_SEND_OP_COND)。返回 32 位 OCR 的 IO 部分,还有电压窗口等信息。
  • R5:用于 CMD52(IO_RW_DIRECT),直接返回 1 字节数据(或 8 位 I/O 寄存器内容)。

我曾经被 R1b 的忙检测害过一次:写了 CMD7 选卡,没等 Data0 释放就发下一条命令,结果卡直接挂死。后来加了超时循环,最长等 64 个时钟(NCR),才算稳定。

⚠ 重要限制:
Host 必须在 NCR 时间内收到响应,否则认为超时。NCR 最大值为 64 个时钟。如果响应线(Data0)上一直没信号,先检查设备是否被正确上电,或者 CMD 线电平是否被拉死。

4. 命令与响应的时序关系

一个完整的命令‐响应周期包含以下几个阶段:

  1. 命令发起:Host 在 CMD 线上串出 48 位。
  2. 命令完成:最后一位结束位之后,CMD 线转为输入模式,等待设备响应。
  3. 响应窗口:从命令结束到响应开始,称为 NCR(响应超时窗口),一般是 2~64 个时钟。
  4. 响应接收:设备在 Data0 线上(或 CMD 线?实际响应也在 CMD 线,SDIO 规范指出响应在 CMD 线上传输)发送 48/136 位。
  5. 忙检测:如果是 R1b 响应,响应结束后 Data0 还会被设备拉低;Host 需要持续轮询直到 Data0 变高。

嗯,这里要注意:窄模式下响应走 CMD 线,所以 Data0 和 CMD 在响应阶段不能冲突。我建议你在逻辑分析仪上同时抓 CMD、CLK、Data0,看到响应波形时心里就有谱了。

5. 常见陷阱与我的经验

陷阱一:命令索引写错
SDIO 命令索引和 SD 卡有重叠,比如 CMD5 在 SD 卡是 SWITCH_FUNC,在 SDIO 是 IO_SEND_OP_COND。如果你拿 SD 卡的初始序列去初始化 SDIO 设备,大概率死在 CMD5 上。
陷阱二:CRC7 计算错误
我曾在软件模拟 SDIO 控制器时,把 CRC7 的生成多项式搞反了(应该左移,我做了右移)。结果每个命令都返回 CRC 错误,设备拒绝响应。
陷阱三:未处理 R1b 忙
前面提过的,CMD7 选卡后如果不等忙释放就发 CMD16/CMD17,卡会进入不稳定状态。我建议在状态机里单独留一个“Wait Not Busy”状态,每次发完 R1b 命令都跳转过去,等 Data0 变高再继续。
关于命令超时的处理经验:
如果设备不响应,先看 CLK 是否正常。很多 SDIO 设备在初始化阶段如果时钟不稳,会静默无视命令。我习惯在代码里加一个“Retry 3 次”逻辑,每次命令失败后复位卡(CMD0 + CMD5 重新协商),而不是无限等待。

6. 总结一下关键点

  • 每帧命令 48 位,含 6 位索引、32 位参数、7 位 CRC。
  • 响应类型分 R1~R6,SDIO 重点掌握 R1、R1b、R5。
  • NCR 超时窗口 2~64 时钟,别让代码死等。
  • R1b 忙信号会拉低 Data0,必须轮询释放。
  • CRC7 错误最常见原因是总线信号质量差,其次是软件算法写错。

命令与响应机制是整个 SDIO 验证的基石。搞懂这一节,后面 CMD53 的块传输、CMD52 的单字节读写,你就看懂了时序图。我个人花了两周才完全搞明白这些响应类型的细节,希望你们少走我的弯路。