3. SDIO 命令与响应:命令格式、命令分类、响应类型

SDIO 协议里,主机和从机之间所有交互都靠“命令-响应”这对搭档完成。说白了,命令就是主机对从机喊话:「你给我做这个动作!」而从机回一句:「收到,这是你要的数据」或者「我不行」。我刚开始做 SDIO 验证时,总觉得这东西不就是发几个 bit 嘛,结果第一次上逻辑分析仪,看到波形才发现——门道多着呢。

咱们把这章拆成三块:命令长什么样、命令分几类、响应又有哪些花样。吃透这些,后面写测试用例心里就有底了。

3.1 命令格式:48 bit 的“暗号”

每条 SDIO 命令都是 48 位长的串行帧。我习惯把它看成一张打包表:

字段 位数 说明
起始位 1 固定为 0,标志帧开始
方向位 1 1 = 主机发给从机
命令索引 6 CMD0 ~ CMD63,决定操作类型
参数 32 具体内容跟着命令走,比如地址、RCA
CRC7 7 校验命令索引 + 参数,防止传错
结束位 1 固定为 1,帧结束

关键点:CRC7 覆盖的是 bit 2 ~ bit 46(命令索引 + 参数),起始位、方向位、结束位不参与校验。我曾经排查一个偶发超时问题,就是 CRC7 生成多项式写错了,导致 1% 的概率执行错误命令。

举个例子,CMD7(选卡)的参数就是目标卡的 RCA 0x0001。发送时硬件会自动把 48 位拼好,加上起始/结束位,从 CMD 线上送出。

3.2 命令分类:4 种“喊话”方式

SDIO 规范把命令按交互模式分成四类。你想想看,主机就像老师,有的问题要全班回答,有的只问一个人。分类就是规定喊话的对象和回应方式。

  • bc(广播命令):主机对总线上所有从机喊,不期待响应。典型例子:CMD0(复位)。
  • bcr(广播命令,带响应):同样喊给所有人,但每个从机都需要回应。用于初始化阶段,比如 CMD2(获取 CID)。
  • ac(点对点寻址命令):主机指定某台从机,对方必须响应。比如 CMD7(选卡)、CMD13(查询状态)。
  • adtc(点对点数据传输命令):除了响应,还要在后续的数据线上传数据块。比如 CMD17(读单块)、CMD24(写单块)。

我的习惯:写脚本测 adtc 类命令时,一定要先确认数据线的配置和块长度。有一次我测 CMD24,数据线配了 4 位,但从机只支持 1 位,结果数据全错位。

分类决定了后续的时序行为。验证工具里,你配置命令类型时选对了,工具才知道要不要等响应、要不要拉数据线。

3.3 响应类型:从机怎么回话

从机收到命令后,会按照规范定义的响应类型回复。每个类型有固定的长度和格式。为什么要有这么多类型?说白了,有的响应只告诉你“收到”,有的要传一大串寄存器值。

类型 长度 包含内容 CRC 常见命令
R1 48 bit 命令索引 + 32 bit 状态 CRC7 CMD13, CMD55
R1b 48 bit + 忙信号 同 R1,但从机会拉低 DAT0 直到准备就绪 CRC7 CMD7(选卡后跳忙)
R2 136 bit CID 或 CSD 寄存器(128 位数据 + 16 位 CRC + 起始/结束) CRC7 + CRC16 CMD2, CMD9
R3 48 bit OCR 寄存器内容,无 CRC 无 CMD5
R4 48 bit RCA 信息,用于快速 I/O CRC7 CMD38
R5 48 bit 从机状态 + 中断信息 CRC7 CMD40
R6 48 bit 新 RCA + 状态 CRC7 CMD3

避坑指南:我曾经在验证 CMD5(IO 发送操作条件)时,误以为 R3 也带 CRC7,结果测试脚本一直报 CRC 错误。后来翻规范才注意到——R3 就是故意不校验的,因为 OCR 寄存器内容在初始化阶段很容易变化。

实际测试时,我常用逻辑分析仪抓响应波形,然后对照响应类型表格看每位是否符合预期。比如 R1 响应中 bit 32 ~ 63 是状态位,其中第 22 位是“当前卡状态错误”,如果置 1 就说明命令不合法。那你想想看,这时候就得回头查命令索引和参数配置了。

3.4 结合一下:命令-响应流程图

下面这张图把命令发送、响应接收、CRC 校验、数据线握手串起来了。我建议你把它贴在工作台旁边,调逻辑时扫一眼就清楚。

SDIO 命令-响应流程图 主机 从机 CMD 帧(48 bit) 响应帧(R1/R1b/R2…) CRC7 校验(主机/从机) 校验结果? 成功 → 执行命令 失败 → 重发/超时报错 若为 adtc 命令 → 数据线传输 注意 R1b 有忙信号 注意 R3 无 CRC

整张图读下来就是:主机说一句话 → 从机回话 → 双方校验 CRC → 正确就干活,错了就重来。对于 adtc 命令,后面还得走数据线。这流程在验证工具里会被拆成多个 step,你得每个 step 都配好超时时间和重试次数。

一点小经验:我在自动化测试里专门写了个函数,把命令-响应交互封装成“cmd_tx_rx()”,内部自动识别响应类型、解析状态位、校验 CRC。这样上层脚本就只管业务逻辑,不用每次重复写时序细节。

3.5 常见陷阱与验证要点

  • CRC7 覆盖范围搞错:记得只校验 bit 2~46,别把起始位算进去。
  • R1b 的忙信号超时:从机拉低 DAT0 后,主机必须在规定时间内等它释放。我的经验是超时设为 1 秒保底,有的低速卡可能需要更久。
  • 响应类型配置遗漏:比如 CMD7 选卡成功后,从机可能返回 R1b(带忙),你要是按 R1 处理,就可能错过忙检测。
  • R2 的 136 bit 解析:前 128 位是寄存器数据,后 8 位是 CRC 和结束位。解析时注意字节序,我踩过坑——从机返回的 CID 字节顺序是 MSB 先出。