STM32F407 在调试 SD I/O 卡的数据读写命令 CMD53 时,发现 DMA 传输数据时卡在了等待传输完成这一步,DMA2_FLAG_TC3 始终未置位。
(相关资料图)
SDIO 使用四位总线,时钟为 24 MHz;DMA 使用 LL 库,配置如下:
在网络上搜索后,发现很多人都遇到了这个问题,而且解决方法那叫一个百花齐放——但是全部木大。经过不断的调试,这里也为各位提供一种全新的方法。
首先,怀疑 DMA 提供的标志位 DMA2_FLAG_TC3 与 SDIO 状态不同步,于是改为 SDIO_FLAG_DATAEND,结果还是卡在同样的地方。
想了一遍数据传输过程,似乎操作 SDIO 接口的顺序有问题,修改后如下图所示。
可以看到,读取时 SDIO_FLAG_CMDACT 和 SDIO_FLAG_DATAEND 可以一起判断,不必先等待命令发送再传输数据。其实是我写反了......但是能用( ̄▽ ̄)
然而,SDIO 卡住的问题仍然没有解决。既然 CMD53 已经找不到问题了,那就看看初始化过程:
看起来平平无奇,对吧?但是注意,“如果在 CMD53 中不停启用 DMA,DMA 将锁住”,DMA 已经提前启用的情况下依然锁住,说明问题不在于此,至少不仅在于此。完全没有头绪的我开始来回翻看参考手册,突然发现 SDIO 一章几乎每个寄存器下都有这样一句话:
经过查看,只有 __SDIO_OPERATION_ENABLE 和 __SDIO_DMA_ENABLE 在短时间内连续写入同一寄存器,而之前的 SDIO 中断配置恰好将这段间隔补上了——这也解释了为什么不能等到调用 CMD53 时再启用 DMA。
解决方法很简单,同时写入即可:
这件事告诉我们,遇到问题时数据手册和参考手册比网络搜索有用多了,当然也别忘记查看库函数实现!
参考手册内容摘自:/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4//files//jcr:content/translations/
插个题外话,为什么要关注库函数实现呢?看看远处的 stm32f4xx_ll_ 吧家人们:
__SDIO_GET_IT 后面的空格直接改变了宏定义,在不修改库函数的前提下只能使用 __SDIO_GET_FLAG 代替,强迫症震怒。
最后,小声骂一句:GPIO 模拟薄纱若至硬件 I2C!