开启Cache后UART无法发送新数据

描述

有人使用STM32H743做产品开发,  DMA 传输待发送的数据到 UART 发送寄存器做后续UART通信。在开启D-Cache的情况下,发现UART没法发送更新过的数据。

具体应用场景是这样的,源数据放在STM32H743片内D1域的AXI-SRAM区,数据会不定期地被CPU修改,然后让DMA将数据传输到USART3的发送寄存器进行后续UART通信。结合手册可以查得USART3位于D2域。[下面截图来自STM32H7芯片参考手册]

dma

目前开启了D-Cache/I-Cache。我基于现有场景写了一段简单的如下测试代码【编译环境使用STM32CubeIDE】:

__attribute__((section(".Source"))) uint8_t Source[5];

uint32_t  TimeOut;

uint8_t  Variable=0;

dma

dma

基于上面测试代码,也重现了相同现象。即尽管CPU在不停修改源端数据,可目的端UART3的TDR寄存器的数据总保持0不变。【注:我这里的DMA使用的Memory to Memory方式,并非要一定这样操作。你完全可以基于UART事件使用Memory to Peripheral的方式。】

dma

这里排除了其它方面的原因,该现象是因为开启了D-Cache并使用write back策略而导致的不同主设备访问同一内存而产生的数据不一致的问题。

现在CPU不时修改AXI-SRAM1指定区域的数据,DMA到同一位置读取数据送到UART发送寄存器。画个图示意下:

dma

对于STM32H743片内AXI-SRAM1区域,其默认的存储属性为write back及writeallocate。【下图来自STM32H7参考手册】

dma

此时CPU对该区域进行写操作发生Cache分配,数据会先写到Cache里。要等到Cache重分配或手动刷新Cache时才会将Cache里的新数据写到RAM内存。

这里有三种方案可选用来解决这个问题:

第一种方案就是,CPU做数据更新操作后,对相应存储区执行Cache清除操作,让Cache的新数据及时写到RAM内存,即添加下面打红勾的代码。

dma

第二种方案就是针对CPU修改的数据存储区进行MPU设置,配置为write through或关闭该区域Cacheable特性。下面将其配置为Writethrough属性。【下面截图来自ARM相关技术手册。C:Cacheable,B:Bufferable,S:Shareable】

dma

使用STM32图形化配置工具CubeMx进行MPU相关配置【参见下图】:

dma

第三种方案,简单粗暴且有效,那就是关闭芯片D-Cache的使用。如果对开启D-Cache不在乎或者只是前期功能调试先关掉无妨,后面再去调整也可以。

上面简单介绍了在开启D-Cache情况下,CPU不定期修改Cacheable内存数据,DMA读取相应内存而发生的数据不一致问题的解决方案,以供参考。

dma

最后提醒下,当我们使用SCB_CleanDCache_by_Addr()函数清除Cache时,需注意给定地址要遵循32字节对齐的原则。【注:上面截图来自STM32H7Cube库。】

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分