Xilinx XDMA驱动代码分析及用法

2023-10-23 11:30

本文主要是介绍Xilinx XDMA驱动代码分析及用法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Xilinx XDMA驱动代码分析及用法

先简单的介绍一下,赛灵思的XDMA的驱动是用于做什么的、他的主要功能就类似与网卡pcie接口的网卡驱动、用于控制主机与fpga设备进行pcie的通讯。通讯的主要方式是设备文件的读写,这里不清楚的同学可以看一下我上一篇文章。通过控制设备文件的读写,操作驱动与fpga设备进行数据传输。

1、目录结构

zacha@Superman:~/nfs/xdma-debug/dma_ip_drivers-master/XDMA/linux-kernel$ tree -C
.
├── COPYING
├── include
│   └── libxdma_api.h
├── LICENSE
├── readme.txt
├── RELEASE
├── tests
│   ├── data
│   │   ├── datafile0_4K.bin
│   │   ├── datafile1_4K.bin
│   │   ├── datafile2_4K.bin
│   │   ├── datafile_256K.bin
│   │   ├── datafile_32M.bin
│   │   ├── datafile3_4K.bin
│   │   └── datafile_8K.bin
│   ├── dma_memory_mapped_test.sh
│   ├── dma_streaming_test.sh
│   ├── load_driver.sh
│   ├── perform_hwcount.sh
│   └── run_test.sh
├── tools
│   ├── \001
│   ├── dma_from_device.c
│   ├── dma_to_device.c
│   ├── dma_utils.c
│   ├── Makefile
│   ├── performance.c
│   ├── perform_hwcount.sh
│   └── reg_rw.c
└── xdma├── cdev_bypass.c├── cdev_ctrl.c├── cdev_ctrl.h├── cdev_events.c├── cdev_sgdma.c├── cdev_sgdma.h├── cdev_xvc.c├── cdev_xvc.h├── libxdma.c├── libxdma.h├── Makefile├── version.h├── xdma_cdev.c├── xdma_cdev.h├── xdma_mod.c├── xdma_mod.h├── xdma_thread.c└── xdma_thread.h5 directories, 43 files
zacha@Superman:~/nfs/xdma-debug/dma_ip_drivers-master/XDMA/linux-kernel$ 

Xilinx 官方的XDMA驱动的目录结构大致如上图所示,大致就是:xdma(驱动代码)、tools(测试工具)、tests(自动化测试脚本)、include(对外头文件)。

今天重点分析驱动的代码部分,也会简单的介绍一些测试文件代码的基本用法。

1.1 tests/tools

tools中的文件就是用于测试驱动mem读写、寄存器读写、等的工具。 tests中的文件 就是自动化运行脚本,分为两种测试方法,第一种是mem mapped 方式,第二种事streamming的方式,两种模式的区别在于DMA以及FPGA的传输方式不同。

1.2 xdma

xdma就是驱动部分的代码,我们先看一下驱动安装成功后,所生成的设备文件,然后对应设备文件去看驱动代码每部分的功能和控制逻辑。

2、驱动的文件与生成的设备

2.1

我们先看xdma_mod.c这个文件, 这个文件主要的功能,这部分代码的主要功能是驱动代码的整体控制入口,我们知道,整个驱动的通讯都是基于PCI协议进行通讯的,所有的总线协议在Linux下都是需要进行总线上设备注册的,所以这个代码主要的功能,就是进行pci总线初始化和注册、然后再 在总线上注册各个字符设备。

static struct pci_driver pci_driver = {.name = DRV_MODULE_NAME,.id_table = pci_ids,.probe = probe_one,							/*设备总线上的字符设备注册入口*/.remove = remove_one,.err_handler = &xdma_err_handler,
};static int xdma_mod_init(void)
{int rv;pr_info("%s", version);if (desc_blen_max > XDMA_DESC_BLEN_MAX)desc_blen_max = XDMA_DESC_BLEN_MAX;pr_info("desc_blen_max: 0x%x/%u, timeout: h2c %u c2h %u sec.\n",desc_blen_max, desc_blen_max, h2c_timeout, c2h_timeout);rv = xdma_cdev_init();if (rv < 0)return rv;return pci_register_driver(&pci_driver);	/*总线设备驱动的注册*/
}
2.2

接下来我们就可以看xdma_cdev.c这个文件,就是用于生成下面图片所需的设备文件,看一下他的创建设备的代码,我们主要关注一下每个设备创建时进行的初始化函数,基本上就能大体的了解他的用法了。我们就按设备的顺序,一一讲解每个设备的功能和具体的用法。

enum cdev_type {CHAR_USER,		/* /dev/xdma_user */CHAR_CTRL,		/* /dev/xdma_control */CHAR_XVC,		/* /dev/xdma_xvc */CHAR_EVENTS,	/* /dev/xdma_events */CHAR_XDMA_H2C,	/* /dev/xdma_h2c */CHAR_XDMA_C2H,	/* /dev/xdma_c2h */CHAR_BYPASS_H2C,	/*fpga ip core bypass 功能 ,未配置未生成*/CHAR_BYPASS_C2H,	/*fpga ip core bypass 功能 ,未配置未生成*/CHAR_BYPASS,		/*fpga ip core bypass 功能 ,未配置未生成*/
};

在这里插入图片描述

int xpdev_create_interfaces(struct xdma_pci_dev *xpdev)

可以看到这个函数,位于xdma_cdev.c ,他的功能就是用于生成各个字符设备的入口,他的调用关系如下:
在这里插入图片描述
函数的调用关系可以与生成的dev/xdma_ 设备进行对应:
xdma_userxdma_control 调用了同一个设备初始化接口,但是是两个不同的设备, 上层接口传递的参数有差异。可以从代码里查看到。他们映射的bar空间是不一样的。
control,映射的是配置寄存器的bar空间, user 映射的给用户预留的bar空间。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里感谢@立夏的小满的指正。

2.3

接下来就是 xdma_xvc.cxdma_xvc设备了, 说实话,目前我没怎么用过这个设备,不过大体看代码逻辑,可能跟fpga的xvc协议有关。Xilinx 虚拟线缆 (XVC) 是一种基于 TCP/IP 的协议,其不仅可发挥类似于 JTAG 线缆的作用,而且还可提供一种无需使用物理线缆便可访问和调试 FPGA 或 SoC 设计的方法。 Xilinx 虚拟线缆 (XVC)。

2.4

xdma_enents.cxdma_events_x 设备 : 这个文件具体的含义就是处于处理事件函数:也就是中断处理。这个设备的读操作是阻塞的, 当读到有fpga有中断过来,那么就会返回应用层,用纸用户层代码就行下一步中断来了处理的逻辑。
在这里插入图片描述

2.5

接下来就是驱动代码的重点文件及设备:xdma_sgdma.cxdma_c2h 、xdma_h2c两个设备, 这两个设备分配对应用户端读和写操作,对应fpga端的读写两个通道。 这个文件是相对其他比较复杂的,它的传输方式是sgdma的传输方式, 就是所谓的scalter-gather (分散-聚集)的dma传输方式。他会生成一个scalterlist表,表的每一项是dma mem 的描述符,描述符大致的内容: src_addr、dst_addr、length、buf、next*、大致是这样。接下来我们看代码。
在这里插入图片描述
设备文件的读写io 调用了同一个接口,即用于读,也用于写。函数原型如下:

static ssize_t char_sgdma_read_write(struct file *file, const char __user *buf,size_t count, loff_t *pos, bool write)

就是说,在用户空间里,我们通过调用文件io的read,和write函数就可以完成设备数据的读和写。
该函数的主要点在:
分配-传输-释放
在这里插入图片描述
在这里插入图片描述
具体函数深入就不细讲了,之后可能会更新一篇文章来阐述,驱动在传输过程中,如何控制dma的内存传输的。下面将一下,几个设备如何使用。

3、用户层代码实现与设备使用

在这里插入图片描述

3.1 xdma_user

看一下官方的解释:

/* maps the PCIe BAR into user space for memory-like access using mmap() */

该设备就是用于映射PCIe设备的bar 空间

static const struct file_operations ctrl_fops = {.owner = THIS_MODULE,.open = char_open,.release = char_close,.read = char_ctrl_read,.write = char_ctrl_write,.mmap = bridge_mmap,.unlocked_ioctl = char_ctrl_ioctl,
};

用户层代码通过mmap io 进行mem映射, 然后通过read 和write 对bar空间的内存寄存器进行读写操作,以完成用户与设备的数据交互。

用户空间代码逻辑实现如下:

static int open_control(char *filename)
{int fd;fd = open(filename, O_RDWR | O_SYNC);if(fd == -1){printf("open control error\n");return -1;}return fd;
}
static void *mmap_control(int fd,long mapsize)
{void *vir_addr;vir_addr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);return vir_addr;
}
static void write_control(void *base_addr,int offset,uint32_t val)
{uint32_t writeval = htoll(val);*((uint32_t *)(base_addr+offset)) = writeval;
}
static uint32_t read_control(void *base_addr,int offset)
{uint32_t read_result = *((uint32_t *)(base_addr+offset));read_result = ltohl(read_result);return read_result;
}
	int control_fd = open_control("/dev/xdma0_user");	control_base = mmap_control(control_fd,MAP_SIZE);frame_bytes = read_control(control_base,0x0a4);write_control(control_base, 0x0004, 0);

打开设备, mem映射至用户空间,寄存器读和写的操作

3.2 xdma_events

事件中断设备, 用于处理设备端发送中断事件的设备,read接口是以阻塞的方式实现的。
用法其实很简单,就是去读这个设备,能读完就说明有中断来了, 卡在读这里说明没有中断过来。
看用户层代码:这里读事件中断是用一个线程一直去读的,通过信号量去通知其他线程是否有中断过来。

void *c2h_event_process(void *param)
{static int flag = 0;int fd = open_event("/dev/xdma0_events_0");printf("c2h event thread running, c2h_event_fd = %d\n", fd);while(1){if (read_event(fd)) {sem_post(&c2h_sem);printf("c2h get %d frame event\n",flag);}else{/*timeout*/}
3.3 xdma_c2h

数据传输读设备,方向是从fpga设备中读取数据过来。对应fpga的写通道。
用户端代码的逻辑是:调用设备的读接口,将读出的数据保存在预先分配的内存中,然后写进文件。 这种方式不建议在嵌入式设备中使用, 因为写数据到文件是比较耗时的, 这样就会影响读的速度,如果fpga读的速度过慢,那么就会导致fpga端的的数据传输fifo 满,数据就会丢失或者异常。

void *c2h_data_process(void *param)
{int fd = open("/dev/xdma0_c2h_0",O_RDWR | O_NONBLOCK);printf("c2h data thread running, c2h_data_fd = %d\n", fd);/*读取的数据写文件*/FILE *record_fp = fopen("/mnt/nfs/c2h_record.bin", "wb");unsigned char *buf = new unsigned char[frame_bytes];while(1){sem_wait(&c2h_sem);read(fd, c2h_align_mem, trans_bytes);fwrite(c2h_align_mem, frame_bytes, 1, record_fp);}
}
3.4 xdma_h2c

数据传输写设备,方向是将数据写进fpga设备中,对应fpga的读通道。
用户端写代码的逻辑就不阐述了,无非就是将预先写好的内容写到fpga的mem, 一般是DDR或者RAM看具体的逻辑设计。
直接上用户层代码。

void *h2c_data_process()
{int fd;fd = open("/dev/xdma0_h2c_0",O_RDWR);while(1){write(fd,h2c_align_mem,frame_bytes);sem_wait(&h2c_sem);}
}

4.总结

最后整体的驱动文件与设备的功能,大致就将这么多。

相关的的驱动及测试代码,以及FPGA工程,已经上传至网盘,有需要的朋友可以自行下载。

网盘连接私信,看到就回,最晚第二个工作早上。
网盘内容请勿传播,有技术问题可私信加微信沟通。

最后,声明一下: 本人的博客很多基本上都是原创, 也有参考其他博文,也基本会在本人博文中有声明地址。 如果本文对您有帮助或者你想转载,请标明文章出处。文章作者:CSDN@蕉尼基

这篇关于Xilinx XDMA驱动代码分析及用法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/267544

相关文章

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud