保留DDR内存作为外设访问

来源:互联网 发布:时时彩开奖视频源码 编辑:程序博客网 时间:2024/05/07 00:28

最近使用xilinx的zynq,需要完成FPGA和ARM的AXI协议通讯,通过增加linux内核启动参数mem=1008M保留了顶部的16M内存空间用来读写数据,FPGA以DMA方式来访问这个内存空间,接下来要完成的就是给这16M的内存空间编写platform_device的驱动程序。

现在讲期间碰到的问题总结一下:

1)DMA:

什么是DMA:就是没有CPU的情况下,由DMA控制器完成内存RAM和其他部分的数据交互,可以写RAM,也可以读RAM。具体方式就是设定DMAC的源地址和目标地址,以及DMA方式,然后写入传输的字节数就可以启动DMA数据传输了。CPU设置完后就不用管数据的传输了。

DMA牵涉到cache,因为CPU为了提高和RAM的交互性能,会把RAM中的部分数据放到cache,这样CPU从cache读要比从RAM读快多了,CPU会根据需要更新cache或则flush。

但是DMA方式因为没有CPU的参与,会导致cache中的新数据还没有flush到RAM,RAM中的旧数据就被读走了;或者RAM中的数据已经被DMAC更新了,但是CPU还是从cache读取了旧数据。因此,当使用DMA方式时,DMA读写RAM的同时要通知CPU,具体方式如下:

1.DMA把RAM数据拷贝出去之前,先把cache数据flush;

2.DMA把数据拷贝到RAM后,使无效RAM中的这段地址。

在linux中,操作RAM都是对内核虚拟地址而言。

可以参考http://blog.csdn.net/linweig/article/details/5327002以及http://www.linuxidc.com/Linux/2011-09/42076.htm

invalidate_dcache_range flush_dcache_range 在mm/cache.c文件下。

/***********下段的结论依赖于具体的硬件,可以参看*****************

*************ioremap和ioremap_nocache函数的实现是否一致***********

但是,DDR作为外设时不需要cache操作,因为DDR物理地址是通过ioremap到内核虚拟地址的,相当于读写外设的寄存器,即便FPGA以DMA方式读写DDR外设,但是ioremap后得到的地址指针也能够读取到正确的数据。

也就是说,ioremap后,对指针的操作直接影响DDR外设,不会经过cache。

***********************************************************************************/


2)read和write使用copy_to_user、copy_from_user还是ioread8、iowrite8

为什么会有ioread8、iowrite8等函数?

主要目的是防止编译器优化,导致读写指令重新排序。

在驱动里面,提供ioread8等函数的目的是不让直接使用ioremap返回的指针,因为对于外设寄存器ioremap得到的指针操作时,必须要避免由于CPU或编译器不恰当的优化而改变预期的I/O动作(引自LDD3)。

RAM的访问可以通过多个方法进行优化:高速缓存保存数值、重新排序读写指令。

而外设的驱动程序要确保不适用告诉缓存,访问寄存器时不发生读或写指令的重新排序。

显然,DDR外设不受读写指令重新排序的干扰,因为它并不是真正意义的硬件外设。

但是高速缓存呢?如何解决,ioremap是否自身已经把这个问题解决了呢?

查看<asm/io.h>发现:ioremap和ioremap_nocache的实现方式是一样的,也就是说,arm把所有的I/O内存都进行了非缓存处理,所以,对于所有的外设,包括DDR外设和其他真实的硬件外设,IO内存都不会经过cache优化。


3)是否使用mmap替代read和write,是否可以提高性能

      其实最后的解决方案就是使用了mmap,保留了部分RAM用作数据存储区。











0 0