3、SDIO总线拓扑与设备识别
我个人做SDIO验证这些年,最常被问到的问题就是:“明明SDIO协议和SD协议一样,为什么我的卡总是初始化失败?” 说白了,很多人以为买个SD卡能跑就万事大吉,结果换了个SDIO Wi-Fi模块,系统直接挂死。这背后绕不开的就是总线拓扑和设备识别流程。今天咱们就彻底把这层窗户纸捅破。
SDIO总线从物理上看就是一组信号线:CLK、CMD、DAT[3:0]。但它的拓扑结构跟普通SPI或者I²C有本质区别。我给新人培训时打过个比方:“SPI是一对一谈恋爱,I²C是会议室里轮流发言,而SDIO是老师和一群学生,老师点名,学生举手回答。” 这个比喻虽然不是百分百严谨,但帮你理解主从结构和寻址方式足够了。
3.1 总线拓扑的两种形态
SDIO总线上真正的主设备只有Host端,比如SoC内部的SD/MMC控制器。卡端全都是从设备。但这里的“从”分两种:单卡模式和多卡模式。
单卡模式没什么好说的,一根CMD线、一根CLK线、4根DAT线直连。我遇到过有工程师把DAT[3]悬空,觉得“反正我只需要1位传输”。嗯,这里要注意,很多SDIO卡在初始化阶段会检测DAT[3]的电平来判断1位还是4位模式,强行悬空可能导致卡端误判。
多卡模式才是真正的坑。SDIO允许同一总线上挂多个卡吗?协议说是可以的,但实际我很少见到这么干的。为什么?因为物理层上DAT线是开漏共享的,CMD也是共享的,每个卡有自己的CS(片选)是靠CMD线上的地址来区分的。但SDIO卡的电气特性跟SD卡不完全一样,尤其是Wi-Fi模块的功耗和噪声,经常把同一根CLK线上的其他卡带崩。我曾在一个项目中排查了三天,最后发现是某个SDIO蓝牙模块的CLK回沟太大,影响了隔壁的eMMC。
3.2 设备识别流程:CMD5是关键战役
说到设备识别,很多工程师脑子里的第一反应是CMD0复位 -> CMD55 + ACMD41(SD卡)-> CMD2获取CID -> CMD3分配RCA。但这个流程只适用于纯粹的SD卡。SDIO卡有自己的身份识别命令:CMD5。
CMD5的作用是什么?它向卡端询问“你是不是一个SDIO卡?”,同时携带了电压范围和I/O功能信息。正常的SDIO卡收到CMD5后,会在CMD线上返回一个响应(R4)。如果没有SDIO能力的卡,会选择静默(No Response)。这个机制就是区分SD和SDIO的核心。
我记得有一次在调试某国产平板时,系统总是把SDIO Wi-Fi识别成SD卡,然后试图给它发ACMD41,结果卡直接死掉。查到最后,发现是底层驱动在初始化时没有先发CMD5,而是直接用SD卡流程。这其实是个很经典的设计缺陷。正确的流程应该是:
- CMD0:软复位所有卡
- CMD5:广播给所有卡问“谁是SDIO?”
- 如果有卡响应R4,读取OCR寄存器,判断电压兼容性
- 如果响应中的I/O功能有效,则继续CMD5轮询直到卡就绪
- 然后才是CMD2获取CID、CMD3分配RCA
3.3 OCR寄存器里的秘密
OCR(Operation Conditions Register)不仅仅告诉你支持的电压范围。对SDIO来说,它还包含了一个非常重要的标志位:I/O Number 和 Memory Present。
其中bit31是最关键的一比特:S18R(Switch to 1.8V Request)。如果卡端支持1.8V信令,它会把这一位置1。UHS-I模式、SDR104等高阶模式,全靠这一步初始化才能进入。我见过很多高速模式调不通的案例,最后发现是Host端压根没处理S18R位,一直用3.3V跑,卡端就不肯切到高速模式。
| OCR位域 | 含义 | 实测注意点 |
|---|---|---|
| Bit 31 | S18R:支持1.8V信令 | 如果卡端置1,Host必须执行电压切换序列 |
| Bit 30 | UHS-II支持(部分卡用) | 目前实际产品中很少见到 |
| Bit 24:7 | I/O功能编号(1:1功能,2:2功能...) | 如果全为0,说明这是个纯Memory卡,不是SDIO |
| Bit 6:0 | 电压窗(2.7-3.6V等) | 多数卡写0x80表示3.3V范围 |
实战技巧: 在做一致性测试时,我习惯先抓CMD5的响应波形,直接用示波器看OCROUT的内容。有时候卡端手册说支持1.8V,但实际量出来的bit31是0,那就是卡的问题。反过来,Host端发了CMD5但没收到任何响应,先别急着怀疑卡坏了,先量一下CLK有没有,CMD线的上拉电阻值对不对。很多开发板的CMD线电阻选的是47kΩ,但SDIO要求是10kΩ,差太远的话卡端根本拉不动信号。
3.4 CIS和FBR:设备描述的核心
一旦RCA分配完成,接下去的工作就是读取卡的功能信息。SDIO不直接用SD的CSD寄存器,而是用一套自己独有的描述体系:CIS(Card Information Structure) 和 FBR(Function Base Register)。
CIS说白了就是一张设备“简历”,里面包含制造商ID、产品名、支持的I/O函数数量、最大传输速率、中断模式等等。读取CIS是通过CMD52(IO_RW_DIRECT)和CMD53(IO_RW_EXTENDED)来完成的。这俩命令也是SDIO独有的,SD卡不认识。
CMD52用于读写单个寄存器,只占1字节。CMD53则支持块传输,效率高很多。我个人的建议是:在初始化阶段,尽量用CMD52读CIS的指针,然后用CMD53整块读CIS内容,别一个一个字节读,太慢了。
FBR则更细粒度地描述每个I/O函数自己的属性和配置。比如一个SDIO Wi-Fi模块可能有Function 0(控制函数)和Function 1(数据函数)。Function 0的寄存器必须通过CMD52访问,而Function 1的收发缓冲区则通过CMD53进行DMA传输。我第一次搞这个的时候,以为所有函数都共用一套寄存器,结果写数据管脚死活不拉高,后来发现FBR里明确写明了Function 1的基地址是0x1000,而不是0x0000。
3.5 设备识别的知识体系
为了帮你快速把握这一章的核心结构,我画了一张流程图,把上面讲的这些串起来。总线拓扑、CMD5识别、OCR解析、CIS/FBR读取,全都在里面了:
从这张图里你能看到,整个设备识别不是一个直线流程,而是有交互和判定的。很多测试工程师拿着Golden Sample卡跑一遍PASS就觉得完事了,但一致性验证的核心恰恰是边界情况:比如CMD5超时后是否重试、OCR中电压不匹配时Host的处理策略、CIS内容校验CRC等。这些才是卡真正的“底线”。
我个人习惯是准备一套完整的测试用例,覆盖CMD5无响应、OCR中S18R置位但Host拒绝切压、CIS中function数量异常这三种场景。别看简单,我在三家芯片公司的测试报告里都发现过类似漏洞。