基于xilinx zynq7000平台(zynq7030),使用 github上的axi_dma驱动操作dma(PL与PS通信)

前言

最近公司项目中使用到了赛灵思Xilinx zynq7000系列(7030)平台,产品中需要在arm(PS)与fpga(PL)之间进行大批量数据传输,还要考虑效率问题,因此使用了axi_dma模块,我用的xilinx工具(xilinx-sdk)以及组件(u-boot、kernel)都是2018.2版本。


驱动选择

方式一:

采用proxy-dma驱动,官方wiki代码链接如下:

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/1027702787/Linux+DMA+From+User+Space+2.0#Receive-Only

不过没提供makefile来生成ko文件,我自己简单写了一个,供参考:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-

KERNEL_DIR=xxx/linux-xlnx(这里指定内核源码根目录路径)


all:
	make -C $(KERNEL_DIR) M=`pwd` modules

clean:
	rm -rf *.o *.cmd *.order Module.symvers *.ko *.mod* ./.* .tmp_versions

obj-m += dma-proxy.o

使用方法很简单,先修改设备树,注意,驱动代码中固定dma-names名称为dma_proxy_rx和dma_proxy_tx,因此不能随意修改,且驱动初始化中默认同时开启rx和tx通道,因为,你如果不是成对使用,需要注释掉驱动中多余通道的初始化代码:

dma_proxy {
	compatible ="xlnx,dma_proxy";
	dmas = <&S2MM_controller_axi_dma_0 0 &S2MM_controller_axi_dma_0 1>;
	dma-names = "dma_proxy_rx dma_proxy_tx";
};

dma设备树相关(S2MM_controller_axi_dma_0)我就没写了,这个可以通过xilinx-sdk工具生成。

系统起来后insmod ko文件,能在/dev目录下得到dma_proxy_rx和dma_proxy_tx驱动设备文件,后面直接参考dma-proxy-test.c文件中的用法进行使用就行了。

方法一我已经用过了,可以用,不过这种方式对于大批量数据的搬运效率如何我没有测试。


方式二:

采用 github上大神开发的axidma驱动,链接如下:

https://github.com/bperez77/xilinx_axidma

公司产品最终使用了就是这个驱动,使用步骤如下:

1、修改设备树

axidma_chrdev: axidma_chrdev@0 {
    compatible = "xlnx,axidma-chrdev";
    dmas = <&MM2S_controller_axi_dma_1 0 &MM2S_controller_axi_dma_1 1>;
    dma-names = "rx_channel", "tx_channel";
};

然后在axi_dma的设备树下面添加字段:

xlnx,device-id = <0x0>和xlnx,device-id = <0x1>,如果使用了多组dma,那么 其它device-id 依次为 0x2、0x3、0x4... ...

2、修改cma大小

由于该驱动在初始化时会malloc大量连续内存(大小依据业务需要确定),我在业务中dma_malloc了256MB,所以启动参数bootargs中添加的是cma=300M

3、驱动编译

注意,编译驱动前,需要先编译linux内核,此步骤省略。

然后进入axi_dma驱动源码目录编译ko:

make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm KBUILD_DIR=../ driver

 注意,我将axi_dma目录放在了kernel源码的根目录下,所以KBUILD_DIR指定的是 ../,KBUILD_DIR的意思就指定编译后的内核源码根目录在什么地方。

编译axi_dma动态库,该库在用户空间使用:

make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm  library

4、驱动使用

系统上电后,如果dts配置正确,内核启动会有如下类似打印:

dma-pl330 f8003000.dmac:        DBUFF-128x8bytes Num_Chans-8 Num_Peri-4 Num_Events-16
xilinx-vdma 40400000.dma: Xilinx AXI DMA Engine Driver Probed!!
xilinx-vdma 40410000.dma: Xilinx AXI DMA Engine Driver Probed!!

insmod axidma驱动后,正常情况下能在/dev目录下看到axidma设备,且打印:

axidma: axidma_dma.c: axidma_dma_init: 721: DMA: Found 1 transmit channels and 1 receive channels.
axidma: axidma_dma.c: axidma_dma_init: 723: VDMA: Found 0 transmit channels and 0 receive channels.

没这个打印或者dev下没有设备,基本就是设备树配置问题了,设备树稍微配置错了一点就会导致这个问题,如果你出现了这个问题,请好好检查设备树文件。

驱动加载成功后就是使用库文件了,参考源码目录下的examples目录下的文件进行使用就好了,有阻塞方式和回调方式可选择,阻塞时给定超时时间,非阻塞时先调用axidma_set_callback设置回调并且超时时间给0,回调中可再次调用transfer接口,这样就能重复达到回调目的了(例如循环处理命令的模式,我最终用的就是这种方式)。

其它说明

1、transfer接口中给定的地址必须是先根据axidma_malloc或者axidma_register_buffer得到的,不能是其它形式;

2、transfer 接口中的channel值,是根据设备树配置来的,比如id依次是0(rx1) 1(tx1) 2(rx2) 3(tx2),那么,axidma_get_dma_tx和axidma_get_dma_rx返回的数组依次就是tx1、tx2和rx1、rx2。

3、如果正常使用axi_dma的用户库接口且数据收/发正常时,内核会有类似打印:

xilinx-vdma 40400000.dma: Channel ef18ae10 has errors 10, cdr 0 tdr 0

这个问题官方在某个issue中回复过了,可以忽略,暂未定位原因。

4、每次完成传输,linux系统上其实能查到中断次数:

root-~# cat /proc/interrupts 
           CPU0       CPU1       
 16:          1          0     GIC-0  27 Edge      gt
 17:          0          0     GIC-0  43 Level     ttc_clockevent
 18:   10542244    9262181     GIC-0  29 Edge      twd
 19:          0          0     GIC-0  37 Level     arm-pmu
 20:          0          0     GIC-0  38 Level     arm-pmu
 21:         43          0     GIC-0  39 Level     f8007100.adc
 23:          0          0     GIC-0  57 Level     cdns-i2c
 24:         84          0     GIC-0  80 Level     cdns-i2c
 26:          0          0     GIC-0  35 Level     f800c000.ocmc
 27:         42          0     GIC-0  82 Level     xuartps
 28:          9          0     GIC-0  51 Level     e000d000.spi
 29:  153829207          0     GIC-0  54 Level     eth0
 30:          0          0     GIC-0  45 Level     f8003000.dmac
 31:          0          0     GIC-0  46 Level     f8003000.dmac
 32:          0          0     GIC-0  47 Level     f8003000.dmac
 33:          0          0     GIC-0  48 Level     f8003000.dmac
 34:          0          0     GIC-0  49 Level     f8003000.dmac
 35:          0          0     GIC-0  72 Level     f8003000.dmac
 36:          0          0     GIC-0  73 Level     f8003000.dmac
 37:          0          0     GIC-0  74 Level     f8003000.dmac
 38:          0          0     GIC-0  75 Level     f8003000.dmac
 39:          0          0     GIC-0  40 Level     f8007000.devcfg
 45:          0          0     GIC-0  41 Edge      f8005000.watchdog
 47:          1          0     GIC-0  64 Edge      uio0
 48:          0          0     GIC-0  65 Edge      uio1
 49:   27267328          0     GIC-0  61 Level     xilinx-dma-controller
 50:     129024          0     GIC-0  66 Level     xilinx-dma-controller

如上面的中断号为61和66的就是dma控制器收、发的中断次数,分别是 27267328次和 129024次。

5、也可以不成对使用dma通道,比如只是用1个rx或tx通道或者共使用2个tx和1个rx通道,总之,按需配置dts就行(已亲测可用)。

 


 

后续有想到的我再添加吧!

 

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值