caching - 为什么 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
如果在“所有显式内存访问”完成时应该完成缓存,为什么不刷新缓存,这似乎包括刷新缓存?
解决方案
dsb ish
用作线程间内存顺序的内存屏障;它只是命令当前 CPU 访问相干缓存。您不会期望dsb ish
刷新任何缓存,因为在同一内部可共享缓存一致性域中的可见性不需要这样做。就像您引用的手册中所说的那样,它完成了内存操作。
回写式缓存上的可缓存内存操作只更新缓存;等待它们完成并不意味着刷新缓存。
我认为您的 ARM 系统对于微控制器与 DSP 有多个相干域?你的__DSB
内在编译成dsb sy
指令吗?假设不刷新缓存,他们的意思大概是它命令内存/缓存操作,包括显式刷新,这仍然是必要的。
推荐阅读
- sql - 从 SQL Server 中的字符串转换日期和/或时间
- mysql - 在 WHERE 语句列名中使用变量
- html - 即使在静音和遵守不同的浏览器规则后,自动播放也不适用于 html 视频
- perl - perl中拆分语法中缺少表达式
- python - 如何将实例绑定描述符作为引用参数传递给函数?
- xcode - 如何在不使用 Xcode 的情况下导出 Apple Developer Id 证书
- java - Java cucumber IllegalArgumentException 路径不一致
- php - 表查询,从table1中选择数据,但前提是table2中的用户设置设置为特定值
- javascript - 从胡须模板 Moodle 3.7 中获取数据
- internationalization - 全球分数的 PageSpeed Insights