CMD53读写数据,小于等于512字节时用stream模式,大于512字节时用block模式。
这在STM32F103和STM32F407的SDIO下测试过,都没问题。
然而同样的代码在STM32H743的SDMMC下运行,结果是:
(1)4线模式下,CMD53读写数据,不管是否使用IDMA, Stream/Block模式均正常。
(2)1线模式下,不管是否使用IDMA,情况如下:
方式 | 情况 |
---|---|
CMD53 Stream模式读数据 | 正常 |
CMD53 Stream模式写数据 | 卡死在while循环 |
CMD53 Block模式读数据 | 正常 |
CMD53 Block模式写数据 | 正常 |
为什么偏偏是STM32H7下的SDMMC无法用CMD53 Stream模式发数据呢?
研究了半天,发现是HAL库的问题。笔者用的HAL库版本是STM32Cube_FW_H7_V1.9.0。
仔细阅读STM32H743的Reference Manual,发现H7的SDMMC_DCTRL寄存器里面一共有四种传输模式:
然而,V1.9的HAL库里面,只给了我们两种选择:
也就是说SDMMC_DataInitTypeDef结构体的TransferMode成员要么选SDMMC_TRANSFER_MODE_BLOCK模式,要么选SDMMC_TRANSFER_MODE_STREAM模式,还剩下两种模式没法选。要是强行让TransferMode=SDMMC_DCTRL_DTMODE_0,那么IS_SDMMC_TRANSFER_MODE(MODE)返回0,SDMMC_ConfigData函数会报assert failed错误。
当TransferMode=SDMMC_TRANSFER_MODE_STREAM的时候,DTMODE=10,根据参考手册,此时恰好选择的是eMMC Stream data transfer模式,而且手册上明确说明了此模式仅在1线模式下有效。
要想解决这个问题,那就只有改HAL库的stm32h7xx_ll_sdmmc.h头文件了。增加SDMMC_TRANSFER_MODE_MULTIBYTE选项,当MODE等于这个新选项时IS_SDMMC_TRANSFER_MODE(MODE)要返回1:
#define SDMMC_TRANSFER_MODE_MULTIBYTE SDMMC_DCTRL_DTMODE_0
#define IS_SDMMC_TRANSFER_MODE(MODE) (((MODE) == SDMMC_TRANSFER_MODE_BLOCK) || \
((MODE) == SDMMC_TRANSFER_MODE_MULTIBYTE) || \
((MODE) == SDMMC_TRANSFER_MODE_STREAM))
然后TransferMode改成SDMMC_TRANSFER_MODE_MULTIBYTE就可以了,问题解决!