SDIO学习记录
为了使用SDIO对SD卡进行读写,移植了ST的官方使用例程源码,但是移植后发现程序执行 BSP_SD_WriteBlocks() 后卡死在 while((BSP_SD_GetCardState() != SD_TRANSFER_OK)) ,后来比对野火的例程(也是移植的ST官方)做出下面修改,问题得到解决:
- 添加SDIO_IRQHandler、DMA2_Stream3_IRQHandler、DMA2_Stream6_IRQHandler的中断服务函数,并执行相应中断服务函数;
- 将BSP_SD_WriteBlocks()改为BSP_SD_WriteBlocks_DMA();
SDIO协议
在硬件上的物理连接有:
- CLK:上升沿时触发命令线/数据线的采样;
- CMD命令线:传输“命令”和“响应”
- 4条数据线(Data0~3)
STM32的SDIO外设由AHB总线接口和SDIO适配器组成,其中SDIO适配器直接连接并与SD卡进行通信,AHB总线负责外设驱动、中断、DMA等内容。
SDIO适配器的时钟频率SDIOCLK=HCLK,CLK线的时钟频率SDIO_CK来源于此,具体配置有:
- 设置BYPASS模式,适配器时钟SDIOCLK通过一个连通旁路直接供给CLK时钟线,即SDIO_CK=SDIOCLK;
- 不设置BYPASS模式,按照公式
由于SD卡普遍的时钟频率要求不超过25MHz,一般通过第二种方式配置STM32的SDIO外设时钟频率。
对SD操作需要发送命令,SDIO协议规定了命令内容,每个命令有其功能,规定“有响应”的命令发送后SD卡会返回对应响应类型,规定“有数据”的命令需要接着继续发送数据;
STM32控制器可以控制使用单线或4线传输,其中Data0线可以通过低电平来表示BUSY状态。数据传输的模式有以下两种:
- 数据块:常用,一般数据块的大小为512字节;
- 数据流
传输数据时数据线的内容组成为:数据块+CRC(+BUSY),其中忙状态在对SD卡做写操作时才有。传输可以是单个数据块,也可以是多个数据块,单块和多块传输有自己的命令,像在HAL库中就有函数 SDMMC_CmdSingleBlock 和 SDMMC_CmdWriteMultiBlock 之分。如果是多块传输,需要手动发送停止命令才能结束数据传输;
上面演示的是一个大体的数据线工作流程,一个完整的数据包除了数据块和CRC,还有起始位(低电平)和终止位(高电平)。使用四线进行数据传输时,每一根数据线都要具备起始、终止和CRC。数据包有两种:
- 8位宽数据包
- 宽位数据包
下图是四条数据线传输8位宽数据包的示意图,特征是:
- 先发低字节再发高字节
- 先发高位再发低位
与之相比,宽位数据包的传输没有前后字节之分,而是传输512位数据,并且依旧符合先发高位再发低位。
CPSM是命令路径状态机,负责命令的传输管理
DPSM是数据路径状态机,负责数据的传输管理
SDIO应用逻辑
下面是HAL库中对SD卡做发送数据的函数流程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异