4、SDIO数据传输:数据线模式(1-bit/4-bit)、块读写、流读写、CRC校验
这一章我们聊聊SDIO的数据传输。这是整个协议最核心的部分,说白了,前面的命令阶段都是在为数据传输做准备。我个人在实际调试的时候发现,很多工程师对数据线的模式切换、读写方式的选择、以及CRC校验的细节理解不够深,结果板子调出来要么速度上不去,要么数据出错。我们先把这几个关键点拆开来讲。
4.1 数据线模式:1-bit 与 4-bit
SDIO的数据线可以工作在两种模式下:1-bit 和 4-bit。你可能会问,“那能不能用8-bit?”答案是不能,SDIO协议只定义了这两种模式。
1-bit模式:只用DATA0这一根线传数据。说白了就是单车道,简单,兼容性最好。几乎所有SDIO设备上电后默认就工作在1-bit模式。
4-bit模式:同时用DATA0-DATA3四根线传数据。相当于四车道并行,理论吞吐量是1-bit模式的4倍。但代价是信号完整性要求更高,PCB布线需要更小心。
我记得有个项目,WIFI模组在4-bit模式下偶尔丢包,降成1-bit就完全稳定。后来查出来是DATA2和DATA3的走线不等长,引入的skew超过了时钟沿的采样窗口。
模式切换流程:主机必须通过CMD7选中设备,然后发送ACMD6命令(包含参数选择模式)来切换数据宽度。注意:切换后必须等待设备准备好才能发送数据命令。
| 特性 | 1-bit模式 | 4-bit模式 |
|---|---|---|
| 数据线数量 | 1 (DATA0) | 4 (DATA0-DATA3) |
| 理论最大速度 | 25 MB/s (SDR25时钟下) | 100 MB/s (SDR25时钟下) |
| 信号完整性要求 | 低 | 高 |
| 引脚占用 | 少 | 多 |
| 默认模式 | 是 | 否 |
4.2 块读写(Block Read/Write)
块读写是SDIO最常用的数据传输方式。你可以把它想象成去仓库搬东西——每次搬一个箱子,箱子大小固定,搬够数量就停。
块的大小:通常是512字节。也有支持1024字节或2048字节的卡,但为了兼容性,我建议你优先按512字节来设计。
块读命令:CMD17 (READ_SINGLE_BLOCK) 用于读单个块,CMD18 (READ_MULTIPLE_BLOCK) 用于读多个连续块。多块读的时候,数据会连续出现在数据线上,直到主机发送CMD12 (STOP_TRANSMISSION) 或者收到最后一个块时自动停止。
块写命令:CMD24 (WRITE_BLOCK) 写单个块,CMD25 (WRITE_MULTIPLE_BLOCK) 写多个连续块。多块写需要主机在每块数据后面发送一个写指示(Busy信号),设备忙时DATA0会被拉低。
我个人习惯:在验证多块读写时,故意在中间某个块插入CRC错误,看设备能不能正确重传或中止。很多底层驱动在这个场景下会死锁,我遇到过好几次。
4.3 流读写(Stream Read/Write)
流读写是另一种方式。它不讲究块对齐,数据像水流一样连续传输。你给它一个起始地址,它就从这个地址开始一直往外吐数据,直到你喊停。
流读用的命令是CMD56,写也是CMD56(靠方向位区分)。流读写不要求数据长度是块大小的整数倍,这对一些需要连续数字信号采集的场景非常有用。比如,一个高速ADC通过SDIO接口输出数据,用流模式就很合适。
但注意:不是所有SDIO设备都支持流模式。很多设备只支持块模式。我建议你先查阅设备的数据手册,确定支持流模式后再在驱动里做这个分支。
我曾经踩过一个坑:流模式下,CRC的生成和校验方式和块模式完全不同。流模式的CRC是连续计算的,每个512字节的窗格会单独插入CRC值,但传输过程中不会因为CRC错误而中断。这意味着你需要在接收端自己检测CRC错误,并决定如何处理。
4.4 CRC校验
SDIO的CRC校验,说白了是为了保证数据在传输过程中没有被损坏。我见过有人为了省性能把CRC校验关了,结果生产线上1%的产品出现偶发数据错误,排查起来生不如死。
| 字段 | CRC位宽 | 生成多项式 | 覆盖范围 |
|---|---|---|---|
| 命令CRC | 7位 | 0x89 (x⁷ + x³ + 1) | 命令内容 (前40位) |
| 数据CRC | 16位 | 0x11021 (x¹⁶ + x¹² + x⁵ + 1) | 全部数据内容 |
命令的CRC是7位,它校验的是CMD索引和参数这40位内容。数据CRC是16位,它校验的是整个数据块或流窗格。你想想看,如果数据线受到外部电磁干扰,或者PCB走线上的串扰过大,CRC计算出来的值大概率对不上,这样主机或设备就能感知到传输出错了。
CRC在命令传输中的作用:主机发命令时,末尾带7位CRC。如果设备算出来不对,就不响应,也不发数据。我在一个项目中遇到过因为主机端CRC计算逻辑的初始余数设置错误,导致所有命令都被设备忽略,板子直接卡死。
CRC在数据传输中的作用:每个数据块后面跟着2字节的CRC16。主机收到数据后,重新算一遍CRC,和附带的CRC值比较。如果不一致,主机可以启动重传机制。这里有个关键点——SDIO协议没有规定重传策略,全靠主机自己实现。你的驱动里得有这个重传逻辑,不然数据可能在应用层就错了。
避坑指南:验证CRC时可以用示波器抓数据线上的波形,手工计算CRC来比对。我在开发新平台驱动时就常这么干,虽然麻烦,但能从根本上确认硬件模块有没有正确实现CRC生成。
4.5 本章核心流程图
下面这张图概括了SDIO数据传输的完整决策链。我个人觉得,理解这张图比死记命令索引更有用。
你可以顺着这张图的流程,从数据传输请求开始往下走:先确定数据线模式,再选择块还是流,最后进行CRC校验。每个决策点都对应着前面讲的知识点。嗯,这就是SDIO数据传输的核心骨架了。