[STM32L4] STM32L4A6ZGT6U SDMMC 配合 DMA 挂载 FatFS 无法工作

[复制链接]
40|15
内核558 发表于 2026-7-18 22:49 | 显示全部楼层 |阅读模式
STM32L4A6ZGT6,固件包 STM32Cube_FW_L4_V1.17.1,硬件 NUCLEO-L4A6ZG。
我正在调试 SDMMC 外设配合 DMA 驱动 FatFS 文件系统,遇到卡死故障。
有没有办法手动升级 FatFS 源码,且每次重新生成 CubeMX 工程时不会被覆盖删除?
在 CubeMX 的 FATFS 高级设置中勾选使用 DMA 模板后读写卡死;取消该选项、采用轮询模式时 SD 卡读写完全正常。
开启 DMA 后程序卡死栈:
SD_write() sd_diskio.c 351行
disk_write() diskio.c 104行
f_mkfs() ff.c 5661行
test() test.c 23行
main() main.c 103行
卡死代码片段:

if(BSP_SD_WriteBlocks_DMA((uint32_t*)buff, (uint32_t)(sector), count) == MSD_OK)
{
  /* 等待写完成或超时 */
  timeout = HAL_GetTick();
  while((WriteStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT))
  {
  }
  /* 超时则返回错误 */
  if (WriteStatus == 0)
  {
    res = RES_ERROR;
  }
}
逻辑是等待全局标记WriteStatus被BSP_SD_WriteCpltCallback置 1,但该回调函数始终不会被触发:
void BSP_SD_WriteCpltCallback(void)
{
  WriteStatus = 1;
}
卡死时读取 SDMMC 句柄hsd1寄存器关键值:
MASK二进制 11010,仅开启:DCRCFAILIE、DTIMEOUTIE、TXUNDERRIE;未开启 DATAENDIE
STA 状态寄存器:TXACT、TXFIFOE、TXFIFOHE、TXDAVL 置位,说明发送流程卡住,FIFO 空但传输未结束
DLEN/DCOUNT = 0x200,DCOUNT 未减少,无任何数据真正完成 DMA 传输
请问是什么导致该故障?

elephant00 发表于 2026-7-20 16:54 | 显示全部楼层
DMA传输前没检查SDMMC的FIFO是否就绪,FIFO空但DMA还没从内存搬数据,卡在TXFIFOE状态。
classroom 发表于 2026-7-20 17:25 | 显示全部楼层
BSP_SD_WriteCpltCallback只清写状态,但没清SDMMC的DCRCFAIL或DTIMEOUT中断标志,失败时不进回调。
cr315 发表于 2026-7-20 17:55 | 显示全部楼层
CubeMX生成的sd_diskio.c里,DMA配置用的是普通模式,而SDMMC传输需要循环模式或双缓冲,否则DMA传输完成后不重载。
duo点 发表于 2026-7-20 18:26 | 显示全部楼层
HAL_SD_WriteBlocks_DMA内部会调用HAL_DMA_Start_IT,但DMA中断使能没开,传输完成中断收不到。
flycamelaaa 发表于 2026-7-20 18:58 | 显示全部楼层
卡死时STA寄存器TXACT置位,说明SDMMC认为正在发送,但DLEN=0x200一直没减,因为DMA没真正写数据到FIFO。
jcky001 发表于 2026-7-20 19:29 | 显示全部楼层
检查DMA的源地址是栈上局部变量还是全局数组,栈地址在Cache范围内,DMA访问Cache不一致导致读不到数据。
onlycook 发表于 2026-7-20 20:00 | 显示全部楼层
NUCLEO板SD卡供电来自MCU的3.3V,DMA启动时大电流拉低电压,SD卡进入异常状态,数据传输失败。
powerantone 发表于 2026-7-20 20:30 | 显示全部楼层
SDMMC的IDMA使能后,必须把描述符放在D1域内存,你放在D2域或外部SRAM,DMA无法访问。
probedog 发表于 2026-7-20 21:02 | 显示全部楼层
轮询模式正常说明SD卡硬件和时钟没问题,问题在DMA请求映射,SDMMC的DMA请求号在L4系列是DMA2_Channel5,你配错通道了。
solty 发表于 2026-7-20 21:33 | 显示全部楼层
HAL库的BSP_SD_WriteCpltCallback函数里只置变量,但函数本身在回调表里可能被覆盖为空函数,需要检查BSP_SD_RegisterCallback注册。
stormwind123 发表于 2026-7-20 22:10 | 显示全部楼层
手动升级FatFS时,把ff.c和diskio.c放到Application/User目录,CubeMX重生成时不会覆盖用户文件夹。
在海边聆听 发表于 2026-7-20 22:46 | 显示全部楼层
卡死循环里用HAL_GetTick做超时,但HAL_GetTick依赖SysTick中断,如果你关中断或优先级高于SysTick,时间永不更新。
故里说长安 发表于 2026-7-21 10:59 | 显示全部楼层
SDMMC的时钟分频系数在初始化时设得太高,DMA跟不上SD卡响应时序,数据根本没发出去。
甜心puppy 发表于 2026-7-21 16:59 | 显示全部楼层
在写回调里加断点或串口打印,确认回调是否根本没注册进SDMMC的中断向量表,IRQHandler被空指针覆盖。
海滨消消 发表于 2026-7-20 17:00 | 显示全部楼层
临时绕过DMA问题:用轮询读写但用DMA做双缓冲暂存,即CPU通过DMA把数据搬入内部缓冲再调用轮询写入,分两步走。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

201

主题

202

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部
0