【转载】ZYNQ Cache问题的解决方法
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 )。
推荐阅读
-
Win7打开文件提示快捷方式存在问题的解决方法
-
sqlserver自动增长列引起的问题解决方法
-
在数据库‘master’中拒绝CREATE DATABASE权限问题的解决方法
-
html5 canvas fillRect坐标和大小的问题解决方法
-
Android编程向服务器发送请求时出现中文乱码问题的解决方法
-
mysql启动时出现ERROR 2003 (HY000)问题的解决方法
-
Win10突然跳出提示网络发现已关闭问题的解决方法
-
Win8应用闪退怎么办?Win8应用商店闪退问题的解决方法
-
SQL中WHERE变量IS NULL条件导致全表扫描问题的解决方法
-
SQLServer 数据库变成单个用户后无法访问问题的解决方法