ZYNQ 在Linux系统层上通过DMA传输数据(安装控制DMA驱动的设备驱动)

2 篇文章 4 订阅
2 篇文章 0 订阅

编译Linux 驱动有两种方法,一种是使用petalinux直接编译进入内核中,第二种是在外部通过arm内核编译之后,insmod加载进入内核。

我使用的是ZYNQ芯片,在芯片中跑Linux系统,我想解决的目标是通过DMA驱动从PS端传输数据到PL端。因为DMA驱动位于设备驱动的下一层,用户模式在设备驱动的上一层;而且DMA驱动对硬件的地址有要求,必须分配连续的物理内存,而在用户层只能分配非连续的内存页,所以需要一个驱动转换映射到物理地址才能给DMA驱动使用。我的工作目的就是安装上管理DMA驱动的设备驱动!在这里介绍两种管理DMA驱动的管理驱动的安装使用!

先介绍第一种:使用dma-proxy 驱动

先要build出一个基于arm的Linux内核,可以参考这篇博客:zynq linux驱动之传统开发

我在编译内核时候出现问题,找不到arm-linux-guneabihf-gcc模块。arm-linux-guneabihf-gcc是基于arm架构的gcc编译器,没有的话直接安装就行,因为我是Ubuntu系统所以使用命令:apt-get install gcc-arm-linux-gnueabihf 进行安装。

接下来使用arm的内核编译我们的驱动文件,我使用的xilinx官方提供的dma-proxy驱动文件,它可以控制DMA驱动的使用,并且提供了用户态的test example给我们熟悉怎么使用DMA driver。

通过Makefile编译dma proxy的内核.C源文件,得到dma-proxy.ko文件,去加载到Linux系统中。

这是dma proxy的Makefile,KERN_DIR设置为已经编译成功的arm Linux kernel location 。

因为dma-proxy驱动为platform device,所以必须加入设备树节点,驱动才能通过bus与对应的设备相匹配!

这个知识点可以参考这几篇博文:

Linux 设备驱动开发 —— platform设备驱动应用实例解析

Linux 设备驱动开发 —— platform 设备驱动

Device Tree中的.dts和dtsi文件介绍

先用petalinux定制Linux系统,导出 design_1_wrapper.hdf 文件,放到 linux_base 文件夹中,source petalinux 和 vivado 环境。

petalinux-create --type project --template zynq --name ax_peta
cd ax_peta
petalinux-config --get-hw-description ../linux_base.sdk
petalinux-config -c kernel
(配置Linux内核一定要把xilinx DMA engine都选中,可以参考GitHub上的Linux Kernel配置)
petalinux-build

配置设备树:

在meta-user的目录下来配置axidma_chrdev: axidma_chrdev@0 和 dma_proxy 节点,

不建议在:

.../plnx_workspace/device-tree/device-tree-generation

的目录下来配置其中的pl.dtsi和system-conf.dtsi设备树文件,因为这是一个临时设备树文件的文件夹,每次petalinux-build都会进行更新恢复到初始状态(虽然很多人这么干...我修改之后build,发现设备树并没有改变,很可能是还原了)。

petalinux-build
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf
--fpga ./images/linux/design_1_wrapper.bit --u-boot --force
生成的文件BOOT.bin、image.ub位于<path/to/PetaLinux/project>/images/linux/下

启动Linux系统,进入到NFS共享文件夹中,加载ko驱动文件。
insmod dma-proxy.ko
启动测试文件,对dma驱动进行数据传输测试。
./dma-proxy-test 1000 1000 (后面两个命令行可以看源码之后填写)

如果成功如下图所示:

 

第二种方法为:使用AXI DMA 驱动

使用 GitHub 中作者提供的 AXI DMA的驱动模块,来传输数据,我使用的FPGA的block design为dma loop的工程。

先用petalinux定制Linux系统,导出 design_1_wrapper.hdf 文件,放到 linux_base 文件夹中,source petalinux 和 vivado 环境。

petalinux-create --type project --template zynq --name ax_peta
cd ax_peta
petalinux-config --get-hw-description ../linux_base.sdk
petalinux-config -c kernel
(配置Linux内核一定要把xilinx DMA engine都选中,可以参考GitHub上的Linux Kernel配置)
petalinux-build

下载GitHub的axi dma资源,解压,然后把所有的文件移动到petalinux的工程下,输入命令Creating and Adding Custom Modules(ug1144-petalinux-tools-reference-guide )

petalinux-create -t modules -n xilinx-axidma --enable

然后把资源文件拷贝到module的文件夹下,并且删除xilinx-axidma.c文件。以下是shell命令作为参考:

path/to/PetaLinux/project>/project-spec/meta-user/recipes-modules/xilinx-axidma/files
cp -a driver/*.c driver/*.h include/axidma_ioctl.h <path/to/PetaLinux/project>/project-spec/meta-user/recipes-modules/xilinx-axidma/files
拷贝文件到module目录

rm <path/to/PetaLinux/project>/project-spec/meta-user/recipes-modules/xilinx-axidma/files/xilinx-axidma.c
删除xilinx-axidma.c文件

<path/to/PetaLinux/project>/project-spec/meta-user/recipes-modules/xilinx-axidma/files/Makefile
修改Makefile文件,删除Makefile第一行,取代为下面三行代码:
DRIVER_NAME = xilinx-axidma
$(DRIVER_NAME)-objs = axi_dma.o axidma_chrdev.o axidma_dma.o axidma_of.o
obj-m := $(DRIVER_NAME).o

<path/to/PetaLinux/project>/project-spec/meta-user/recipes-modules/xilinx-axidma/xilinx-axidma.bb
修改xilinx-axidma.bb文件:
SRC_URI = "file://Makefile \ 
           file://axi_dma.c \
           file://axidma_chrdev.c \
           file://axidma_dma.c \
           file://axidma_of.c \
           file://axidma.h \
           file://axidma_ioctl.h \
           file://COPYING \
          "

1.根据之前petalinux-build生成的pl.dtsi,需要修改device id,不管几个dma一定保证device id的唯一性(修改如下图)。将其中的内容全部复制到system-conf.dtsi,这两个文件的地址均在<path/to/PetaLinux/project>/components/plnx_workspace/device-tree/device-tree,这部分复制进system-user.dtsi也可以,<path/to/PetaLinux/project>/components/plnx_workspace/device-tree/device-tree这个目录下的文件一般是自动生成的。

2.同时删除system-top.dtsi最后一行#include system-user.dtsi

3.修改system-user.dtsi(位置/project-spec/meta-user/recipes-bsp/device-tree/files/”),加入以下内容:

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

 

petalinux-build
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf
--fpga ./images/linux/design_1_wrapper.bit --u-boot --force
生成的文件BOOT.bin、image.ub位于<path/to/PetaLinux/project>/images/linux/下

(我当时petalinux-build的时候没有成功,发现我修改plnx-workspace目录下的设备树文件被还原了,也不知道什么情况,再修改一次就好了) 

我最后成功的配置设备树文件的方式是放到user文件中,方法同上面一种方法一样。

启动Linux系统,加载axidma.ko驱动,然后运行axidma_transfer例子,我在1.txt中写入文字,通过DMA传输到2.txt中。

出现问题:

我当把BOOT.bin、image.ub文件放入SD卡,启动FPGA的时候出现 Bad FIT kernel image format! 问题。

原因是因为FIT文件损坏。

所以在把SD卡进行格式化的时候要格式化为FAT32格式,而且一定要安全弹出,不要直接热插拔,文件很容损坏!

 

我觉得这篇博客写得非常棒:ZYNQ跑系统 系列(四) AXI-DMA的linux下运行

不好意思 ,写得比较乱。现在工作内容是camera 软件工程师,已经不做FPGA了,没办法回答你们关于DMA的问题了,抱歉!

  • 6
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Zynq是一款由赛灵思公司开发的可编程SoC(System-on-a-Chip),它集成了双核ARM Cortex-A9处理器和可编程逻辑部分。在Zynq上运行Linux操作系统需要使用适配的驱动程序来管理硬件资源。 DMA(Direct Memory Access)是一种数据传输技术,可以实现在设备之间直接进行内存间的数据传输,而无需CPU的干预。Zynq上的Linux DMA驱动可以通过DMA控制器来管理数据的传输。DMA驱动中最常用的函数是dmaengine_prep_slave_XXX(),它用于准备DMA传输的配置参数,并将其保存到DMA请求对象中。然后,可以通过dmaengine_submit()函数将请求添加到DMA队列中,并使用dma_async_issue_pending()函数将请求提交给DMA引擎。 在单向读写中,通过DMA设备读取数据或将数据写入设备。读取数据时,我们可以通过dmaengine_prep_slave_rx()函数来准备DMA传输的配置参数,然后调用dmaengine_submit()函数将请求添加到DMA队列中,并使用dma_async_issue_pending()函数来开始传输。类似地,写入数据时,我们可以使用dmaengine_prep_slave_tx()函数来准备DMA传输的配置参数。 使用DMA进行单向读写的好处是可以提高数据传输的效率和性能。因为DMA的传输是在设备和内存之间直接进行的,可以实现高速数据传输而无需CPU的干预,从而减少了CPU的负载,提高了系统的响应速度。同时,由于DMA传输是异步进行的,可以在数据传输的同时进行其他任务,提高了系统的并行处理能力。 总结起来,Zynq上的Linux DMA驱动可以通过DMA控制器来管理数据的传输。在单向读写中,通过准备配置参数并将请求添加到DMA队列中,可以实现从设备读取数据或将数据写入设备。使用DMA进行数据传输可以提高系统的性能和响应速度,同时提高了系统的并行处理能力。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值