【发布时间】:2021-12-09 01:58:59
【问题描述】:
我正在使用 LWIP 和 HAL 驱动程序在 STM32H725VG 上调试 HTTP 服务器,这些驱动程序最初都是由 STM32CubeMX 生成的。问题在于,在某些情况下,通过HAL_ETH_Transmit 发送的数据有一些八位字节被 0x00 替换,而这些损坏的内容成功地到达了客户端。
我检查了缓冲区中作为参数传递给HAL_ETH_Transmit 的数据在调用此函数之前和之后都完好无损。因此,显然,从 RAM 传输到 MAC 时会发生损坏,因为校验和是根据损坏的数据计算的。所以我认为问题可能是由于缓存和DMA之间的交互。我试过禁用 D-cache,然后没有发生损坏。
然后我想我应该只使用 __DSB() 指令将缓存的数据写入 RAM。启用 D-cache 后,我在调用 HAL_ETH_Transmit 之前添加了 __DSB()(在 STM32CubeMX 生成的 low_level_output 函数中),然后……什么也没发生:数据仍然损坏。
然后,经过一些实验,我发现SCB_CleanDCache() 在__DSB() 之后(或代替)调用可以解决问题。
这让我很奇怪。 DSB指令的描述为as follows:
数据同步屏障作为一种特殊的内存屏障。该指令执行后,程序顺序中没有指令,直到该指令完成。该指令在以下情况下完成:
- 此指令完成之前的所有显式内存访问。
- 此指令完成之前的所有缓存、分支预测器和 TLB 维护操作。
而description of SCB_DisableDCache 有以下关于SCB_CleanDCache 的注释:
禁用数据缓存时,您必须清理 (
SCB_CleanDCache) 整个缓存,以确保将所有脏数据刷新到外部内存。
为什么DSB 在“所有显式内存访问”完成时不刷新缓存,这似乎包括刷新缓存?
【问题讨论】:
标签: caching arm cpu-cache dma memory-barriers