欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-15 15:44:34
Zynq Cache问题的解决方法 - Kevin_HeYongyuan - 博客园https://www.cnblogs.com/kevin-heyongyuan/articles/7738552.html 在进行PS-PL之间的DMA传输时,不可避免会遇到Cache问题。今天在这里讲一下Cach ......

zynq cache问题的解决方法 - kevin_heyongyuan - 博客园
https://www.cnblogs.com/kevin-heyongyuan/articles/7738552.html

在进行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 )。