首页 > 解决方案 > 为什么 DSB 不刷新缓存?

问题描述

我正在使用 LWIP 和 HAL 驱动程序在 STM32H725VG 上调试 HTTP 服务器,所有这些驱动程序最初都是由 STM32CubeMX 生成的。问题是在某些情况下HAL_ETH_Transmit,通过 0x00 发送的数据有一些八位字节替换,而这些损坏的内容成功地到达了客户端。

我已经检查过作为参数传入的缓冲区中的数据在HAL_ETH_Transmit调用此函数之前和之后都是完整的。因此,显然,从 RAM 传输到 MAC 时会发生损坏,因为校验和是根据损坏的数据计算的。所以我认为问题可能是由于缓存和DMA之间的交互。我试过禁用 D-cache,然后没有发生损坏。

然后我认为我应该只使用__DSB()将缓存数据写入 RAM 的指令。重新启用 D-cache 后,我__DSB()在调用之前添加了HAL_ETH_Transmit(这是low_level_output由 STM32CubeMX 生成的内部函数),然后……什么也没发生:数据仍然损坏。

然后,经过一些实验,我发现SCB_CleanDCache()调用之后(或代替)__DSB()可以解决问题。

这让我很奇怪。DSB指令说明如下

数据同步屏障充当一种特殊的内存屏障。该指令执行后,程序顺序中没有指令,直到该指令完成。该指令在以下情况下完成:

  • 此指令完成之前的所有显式内存访问。
  • 此指令完成之前的所有缓存、分支预测器和 TLB 维护操作。

并且描述SCB_DisableDCache有以下说明SCB_CleanDCache

禁用数据缓存时,您必须清理 ( SCB_CleanDCache) 整个缓存以确保将任何脏数据刷新到外部内存。

DSB如果在“所有显式内存访问”完成时应该完成缓存,为什么不刷新缓存,这似乎包括刷新缓存?

标签: cachingarmcpu-cachedmamemory-barriers

解决方案


dsb ish用作线程间内存顺序的内存屏障;它只是命令当前 CPU 访问相干缓存。您不会期望dsb ish刷新任何缓存,因为在同一内部可共享缓存一致性域中的可见性不需要这样做。就像您引用的手册中所说的那样,它完成了内存操作。

回写式缓存上的可缓存内存操作只更新缓存;等待它们完成并不意味着刷新缓存。

我认为您的 ARM 系统对于微控制器与 DSP 有多个相干域?你的__DSB内在编译成dsb sy指令吗?假设不刷新缓存,他们的意思大概是它命令内存/缓存操作,包括显式刷新,这仍然是必要的。


推荐阅读