【转载】ZYNQ Cache问题的解决方法

Zynq Cache问题的解决方法 - Kevin_HeYongyuan - 博客园
https://www.cnblogs.com/kevin-heyongyuan/articles/7738552.htmlhtml

在进行PS-PL之间的DMA传输时,不可避免会遇到Cache问题。今天在这里讲一下Cache的解决方法。其中参考了forums.xilinx.com的处理方法。
首先解释为何DMA会引入Cache问题(专业名称为Cache一致性问题)。
PS和PL都在独立运行,PS经过DDR控制器来对DDR存储器进行访问,为了加速,经常将一些数据缓存(Cache),并且不是针对一个数据缓存,而是针对一批(Xilinx称为一行,即Line,一行长度为32)。这样好处很明显,下一次访问速度会加快;但坏处也很明显,就是Cache里的数据若是发生了改变,不能迅速反映到DDR2实际数据中,反之亦然。所以,当PL经过DMA修改了DDR2数据时,CPU可能还不知道发生了些什么,拿到的数据仍然是Cache中的没有改过的数据。
在裸机开发时,规避Cache最简单的方法就是禁用Cache。
#include "xil_cache.h"
void Xil_DCacheDisable(void);
这样操做后,CPU将直接访问DDR内存,读写都是直接的。这样显然会下降CPU性能,但简化了数据传输操做,属于极端的方法。
 
另一种操做要多加一道手续,在个人文章【参赛手记】详细介绍AXI-HP接口+DMA+GIC编程中,给出的例程里有Cache Flush和Cache Invalidate操做。从字面理解,Flush就是把Cache里的数据流放出去,清空Cache,也就是将Cache的内容推到DDR中去;而Cache Invalidate表示当场宣布Cache里的内容无效,须要从DDR中从新加载,即把数据从DDR中拉到Cache中来。
理解了这个原理,在编程的时候内心就很是有底气了!
#include "xil_cache.h"
//写点什么到发送缓冲区sendram 
Xil_DCacheFlushRange((u32)sendram,sizeofbuffer);//将内容刷新至DDR
//启动发送DMA过程。。。。
 
//启动接收DMA过程。。。。。
Xil_DCacheInvalidateRange((u32)recvram,sizeofbuffer);//将DDR内容拉进Cache
//从recvram中读取数据吧!
 
好了,裸机工程下面开发是很是简单的,出错了也容易定位,调试起来方便。在Linux下开发时,因为编写的接口模块处于驱动层面,调试可能不如SDK中那么直观,只能关键部位打印printk,而后慢慢去寻找错误,定位比较麻烦。
在Linux下,Cache的Flush和Invalidate操做须要调用内核函数 dma_sync_single_for_device和 dma_sync_single_for_cpu。
这两个函数包含时能够这样:
#include 
其代码能够在内核源码的/arch/arm/include/asm中看到。
一样,在驱动程序中,涉及到DMA操做时,也须要在DMA写以前先Flush,DMA读以后Invalidate操做。
其参数为:第一个参数是device结构体,第二个参数为DMA的实际地址,须要经过虚拟地址到实际地址的映射才能实现(这是Linux的自己特色),第三个参数为方向,能够选择DMA_TO_DEVICE或 DMA_FROM_DEVICE(须要包含头文件#include )。编程

相关文章
相关标签/搜索