zynq开发,什么情况下需要关闭arm侧 CPU的cache_zynq7 cache coherency
在 Zynq 平台开发中(如 Zynq-7000 或 Zynq UltraScale+ MPSoC),ARM 侧 CPU 的 Cache(L1 / L2)默认是开启的,用于提升 AXI 总线访问的效率。但在某些特定应用中,必须关闭或绕开 CPU Cache,否则可能会导致数据错误或系统行为不可预期。
✅ 一句话总结:
当 ARM 和 PL(FPGA)之间共享内存、或 ARM 直接操作外设寄存器、或进行 DMA 操作时,为确保数据一致性,需要关闭 Cache 或使用 non-cacheable 内存。
📌 常见需要关闭或避免使用 Cache 的场景:
🔍 更详细举例:
✅ 示例 1:ARM 写内存 → FPGA 读取
// ARM 写数据my_buffer[0] = 0x12345678;// FPGA 读取的是老数据? → 原因:Cache 未写回内存
解决方法:
Xil_DCacheFlushRange(&my_buffer[0], 4);
- 或将
my_buffer
放在 non-cacheable 区域
✅ 示例 2:DMA 写入 buffer → ARM 读取
// DMA 写入完成后 ARM 马上读取val = my_dma_buffer[0]; // 读到的是 Cache 旧数据
解决方法:
Xil_DCacheInvalidateRange(&my_dma_buffer[0], 4);
- 或使用 uncached buffer
🧠 如何实现 non-cacheable 区域?
方法 1:裸机下通过 linker script 指定 uncached 区域
MEMORY { ps7_ddr_0 : ORIGIN = 0x00100000, LENGTH = 512M /* cacheable */ uncached : ORIGIN = 0x3F000000, LENGTH = 16M /* non-cacheable */}
方法 2:Linux 下使用 dma_alloc_coherent()
分配 uncached buffer
void *buf = dma_alloc_coherent(NULL, size, &phys_addr, GFP_KERNEL);
方法 3:MMU 页表配置为 Strongly Ordered 或 Device 类型(non-cacheable)
⚠️ 注意:不要关闭全局 Cache,除非你非常确定
ARM 的 L1/L2 Cache 对 Linux/裸机系统性能至关重要,一般不要直接全局关闭,而是:
- 控制某一段内存是否 Cacheable(通过 MMU 或 Memory Attribute)
- 或用 API 手动 flush/invalidate Cache
✅ 推荐 API(裸机 BSP)
Xil_DCacheFlush()
Xil_DCacheFlushRange(addr, len)
Xil_DCacheInvalidateRange(addr, len)
Xil_ICacheDisable()
/ Xil_DCacheDisable()