STM32H7 CPU Cache 与MDMA冲突问题

关于最近使用STM32H743+SDMMC+QSPI+MDMA+FATFS读写SD卡与SPI FLASH时的问题:

注:以下修改适用于你使用了STM32H743+SDMMC+QSPI+MDMA+FATFS+Cache缓存的情况。

  • 在读写SD卡时,发现f_write函数返回FR_INT_ERR,然后打断点调试发现底层函数返回值没有问题:
    - ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a1a6d9fede0849b18788f643673b9164.png)

    使用读卡器发现数据实际已经写入;这让我百思不得其解,怀疑是什么原因导致数据没有同步;于是想到了会不会是STM32H7的Cache缓存的问题,然后上网找资料,看到了一篇文章:文章链接在这里插入图片描述
    经过这篇文章提示,于是看了代码,确实开启了Cache;尝试关闭后:
    在这里插入图片描述
    果然写入返回错误的问题解决了:
    在这里插入图片描述
    关闭Cacheh后,SDRAM的内存映射读写也变慢了,影响了其他模块性能,问题还未完全解决。
    于是想办法在不关闭缓存机制的情况下,能够保证数据的一致性了,然后根据SCB_EnableDCache这个函数跳转,发现了一个SCB_CleanDCache函数,该函数是清除数据Cache的,然后尝试使用了一下,在DMA读写之前调用,重写了下面函数:在这里插入图片描述
    测试发现也是可以的,其他模块也没有受到影响,到此,问题全部解决。

  • QSPI FALSH读写也是一样,也是MDMA与Cache数据不一致导致的,解决方法可以参考上面SD卡。
    修改读写部分函数(底层驱动基于野火开发板例程修改):
    在这里插入图片描述
    在这里插入图片描述
    参照SDMMC的磁盘读写(sd_diskio.c文件),完成以下修改:
    在这里插入图片描述
    在这里插入图片描述

  • 最后注意时钟树的选择:
    DTCM内存池,DTCM共128KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!

    ITCM内存池,DTCM共64 KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!
    在这里插入图片描述
    之前我QSPI 时钟选择是HCLK3,所以 QSPI按照SD卡改了也不行,更改时钟选择就行了。

### STM32 MDMA配置方法及示例 #### 配置初始化结构体 为了实现STM32 MDMA通道的操作,需先实例化`MDMA_InitTypeDef`类型的变量用于设置传输参数。这一步骤对于后续寄存器操作至关重要[^1]。 ```c MDMA_HandleTypeDef hmdma_x; void MX_MDMA_Init(void) { /* Initialize the global state of the handle */ hmdma_x.Instance = MDMA_Channel0; /** Configure number of data to transfer, source and destination addresses */ hmdma_x.Init.Mode = MDMA_MODE_NORMAL; // Normal mode or buffer circular mode hmdma_x.Init.Priority = MDMA_PRIORITY_HIGH; // Priority level hmdma_x.Init.Request = MDMA_REQUEST_GENERATOR_0;// Request selection hmdma_x.Init.TransferTriggerMode= MDMA_TRANSFER_NO_TRIGGER;// Trigger mode if (HAL_OK != HAL_MDMA_Init(&hmdma_x)) { Error_Handler(); } } ``` #### 设置循环模式 当需要重复执行相同的数据传输任务时,可以启用DMA的循环模式。通过将DMNGT位置为特定值可激活这一功能,在某些应用场景下尤为有用[^2]。 ```c // Enable loop mode for continuous transfers hmdma_x.Init.Mode = MDMA_MODE_CIRCULAR; if (HAL_OK != HAL_MDMA_ConfigChannel(&hmdma_x, &Init)) { Error_Handler(); } ``` #### 定义并验证内存区域 确保所使用的内存扇区已在`.sct`文件中正确定义非常重要;否则即使编译无误也可能因访问非法地址而导致运行期错误或异常行为。因此建议开发者仔细核对自己项目的链接脚本以确认所有自定义内存分区的存在性和可达性[^3]。 ```c __attribute__((section(".RAM_D3"))) uint8_t myBuffer[SIZE]; /* Ensure .sct file contains a definition like this: RAM_D3 0x20000000 0x1000 { ; Read-write } */ ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值