> 技术文档 > zynq开发,什么情况下需要关闭arm侧 CPU的cache_zynq7 cache coherency

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 的场景:

场景 说明 处理方式 ✅ 共享内存(ARM 与 PL / DMA 共享) 比如 ARM 把数据写到内存,PL 读取,或反过来 该区域必须 non-cacheable,或每次都 flush & invalidate ✅ DMA 传输(ARM 控制 DMA,或 DMA 写回 ARM) Cache 会导致 CPU 看到的数据和实际内存不一致 推荐 DMA buffer 分配在 uncached 内存区域AXI-MM 接口控制 PL IP 的寄存器 PL 侧寄存器数据随时可能变化,cache 会导致访问老数据 访问寄存器应使用 强制 non-cacheable 的地址映射实时性场景,如外设轮询、bit-bang IO 缓存访问不确定,可能增加延迟 建议将相关区域映射为 non-cacheable ❌ 裸机程序中未配置 MMU/Cache 默认就是 uncached,无需额外处理 不使用 MMU 的 bare-metal 程序默认无 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)

API 作用 Xil_DCacheFlush() Flush 全部 D-cache Xil_DCacheFlushRange(addr, len) Flush 指定范围(写回) Xil_DCacheInvalidateRange(addr, len) Invalidate 指定范围(使之失效) Xil_ICacheDisable() / Xil_DCacheDisable() 关闭 Cache(不推荐全局用)

🧭 总结表:Zynq ARM Cache使用建议

场景 建议 Cache 策略 普通代码/数据 Cacheable(默认即可) DMA buffer 使用 Non-cacheable 区或手动 flush/invalidate PL 寄存器映射 强制 Non-cacheable 多核间通信共享内存 使用 Non-cacheable 区或加 barrier 实时/确定性要求高 避免使用 Cache,或精控 Cache 行为