Xilinx XDMA驱动代码分析及用法

news2025/7/17 15:02:09

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.h

5 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工程,已经上传至网盘,有需要的朋友可以自行下载。
链接:https://pan.baidu.com/s/1wdPqUf8_2K6r8ZbVupizrw
提取码:i2sw

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/406185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA连接MySQL数据库并执行SQL语句使用数据

文章目录一、IDEA连接MySQL数据库&#xff08;一&#xff09;首先新建普通Java项目&#xff08;二&#xff09;连接数据库1、点击右侧DataBase2、点击加号&#xff0c;找到MySQL&#xff0c;添加数据库3、输入用户名和密码&#xff0c;点击**Test Connection**4、显示连接成功&…

深度分析| 数据防泄露技术再次“翻红”的思考与建议

此文章由天空卫士供稿 01、数据防泄露的定义 数据防泄露&#xff08;Data leakage prevention&#xff0c;DLP&#xff09;是指通过一定的技术和管理&#xff0c;防止组织内敏感数据或信息资产&#xff0c;违反安全约束而丧失组织控制、破坏数据机密性的策略和措施。数据防泄…

【云原生】裸金属架构之服务器安装VMWare ESXI虚拟化平台详细流程

??作者简介&#xff1a;大家好&#xff0c;我是&#xff0c;运维领域创作者&#xff0c;??阿里云ACE认证高级工程师?? 个人主页&#xff1a; ??支持我&#xff1a;点赞??收藏留言?? ??格言&#xff1a;你未必出类拔萃&#xff0c;但一定与众不同&#xff01;??…

[SSD4] 固态硬盘主控功能_SSD主控品牌

固态硬盘(Solid State Drives),简称SSD。它是一种电脑存储设备,由闪存(FLASH)、 闪存控制器、高速缓存(DRAM)组成。这是是固态硬盘的三个基本部件,对性能有关键影响。 了解一颗固态硬盘首先要从主控入手,主控对于固态硬盘的影响丝毫不亚于闪存。那么主控芯片对于固态硬盘…

来了!Python 官方发布了整套的中文PDF 文档(共27本)

1. 《Python中文指南》 学 Python 最好的学习资料永远是 Python 官方文档&#xff0c;可惜现在的官方文档大都是英文&#xff0c;虽然有中文的翻译版了&#xff0c;但是进度实在堪忧。 为了照顾英文不好的同学&#xff0c;我自己写了一份 面向零基础的朋友 的在线 Python 文档…

Stable diffusion安装踩坑(winMaciOS)

今天Apple官方支持了这个库&#xff0c;所以特意下载下来试试看&#xff0c;效果还不错&#xff0c;M芯片在深度学习领域第一次给人惊喜了。 https://machinelearning.apple.com/research/stable-diffusion-coreml-apple-silicon 1.win使用 安装 分享一下一个有意思的库的安…

算法的效率——时间复杂度和空间复杂度

文章目录1. 算法效率1.1 什么是算法1.2 算法的好坏2. 时间复杂度2.1 什么是时间复杂度2.2 时间复杂度的计算方法2.3 大O的渐进表示法2.4 常见时间复杂度计算举例3. 空间复杂度4. 常见复杂度对比1. 算法效率 1.1 什么是算法 目前普遍认可对算法的定义是&#xff1a;算法是解决…

通过CSS,H5,JavaScript实现表格表单的随机选择,和简单的随机点名。

目录 一、表格表单的随机选择 效果展示&#xff08;表单内容可以根据自己需要进行修改&#xff09; 1.H5的布局 第一步&#xff1a; 第二步&#xff1a; 2.CSS布局 3.JS的布局 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 二、简单的随机点名 效果展…

软件测试简历项目经验怎么写,没有项目经验?

怎么办&#xff1f;只能接受低薪工作吗&#xff1f;No No No。本文就教大家如何解决这个问题。 为了帮助大家彻底解决“没有项目”这个拦路虎&#xff0c;接下来文章将从以下几个方面进行展开&#xff1a; 1、应该去哪找项目&#xff1f; 2、在众多的项目中&#xff0c;该怎么…

【AI作画】使用stable-diffusion-webui搭建AI作画平台

一、安装配置Anaconda 进入官网下载安装包https://www.anaconda.com/并安装&#xff0c;然后将Anaconda配置到环境变量中。 打开命令行&#xff0c;依次通过如下命令创建Python运行虚拟环境。 conda env create novelai python3.10.6E:\workspace\02_Python\novalai>conda…

基于FPGA 的TDC设计更好的选择——易灵思Quantum架构FPGA

时间数据转换器(TDC)常被用于测量时间间隔&#xff0c;被广泛应用于飞行时间测量领域。分辨率是一个重要的参数&#xff0c;但TDC线性度将直接影响整个系统的精度。尤其是近年来迅猛增长的汽车自动驾驶&#xff08;ADAS&#xff09;领域&#xff0c;利用光测距的激光雷达&#…

GCN-图卷积神经网络算法简单实现(含python代码)

本文是就实现GCN算法模型进行的代码介绍&#xff0c;上一篇文章是GCN算法的原理和模型介绍。 代码中用到的Cora数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1SbqIOtysKqHKZ7C50DM_eA 提取码&#xff1a;pfny 文章目录 目的 一、数据集介绍 二、实现过程讲…

[闪存 2.1] 闪存芯片物理结构与_SLC/MLC/TLC/QLC

固态硬盘(Solid State Drives),简称SSD。它是一种电脑存储设备,由闪存(FLASH)、 闪存控制器、高速缓存(DRAM)组成。这是是固态硬盘的三个基本部件,对性能有关键影响。 闪存芯片简介闪存颗粒是固态

MySQL数据库的基础语法总结(1)

MySql一.数据库,数据表的基本操作1.数据库的基本操作2. 数据表的基本操作2.1 数据库的数据类型2.1.1 整数类型2.1.2 浮点数类型和定点数类型2.1.3 字符串类型2.1.4 日期与时间类型2.2 数据表的基本操作2.2.1 创建一个数据表2.2.2 查看数据表2.2.3 查看表的基本信息的MySQL指令2…

设计模式(上)

目录 1.设计模式概述 1.什么是设计模式 2.学习设计模式的意义 3.23种设计模式 4.七大设计原则 2.创建者模式 1.单例模式 2.工厂模式 3.抽象工厂模式 4.建造者模式 5.原型模式 3.结构型模式 1.适配器模式 2.桥接模式 3.代理模式 4.组合模式 5.装饰模式 6.享元…

[架构之路-24]:目标系统 - 系统软件 - C语言的结构与程序的工作原理 - 程序控制、函数调用栈、函数调用性能优化

目录 前言&#xff1a; 第1章 结构化程序与分层编程系统 1.1 计算机软硬件模型 1.2 程序的经典框架&#xff1a;算法数据结构 1.3 程序的结构化框架 1.4 程序的层次模型 1.5 程序设计的层次模型 第2章 C语言概述 2.1 C语言本质 2.2 C语言关键字 2.3 C语言在编程语言的…

js算法 字母大小写转换

题目&#xff1a;输入字符串将大写转换成小写&#xff0c;小写转换成大写&#xff1f; js字母大小写转换方法&#xff1a; 1、转换成大写&#xff1a;toUpperCase() 2、转换成小写&#xff1a;toLowerCase()方法一&#xff1a;把输入的字符串转成数组用split&#xff08;&…

chatgpt 无法登录报错Access denied、OpenAl‘s services are not available in yourcountry. (error=unsupported )

一、主要解决有账号无法登录问题&#xff0c;共包含两种情况。 1、Oops! OpenAls services are not available in yourcountry.(errorunsupported country) 2、Access denied You do not have access to chat.openai.com. The site owner may have set restrictions that p…

Linux命令之nano命令

一、nano命令简介 nano是一个小型、免费、友好的编辑器&#xff0c;旨在取代非免费Pine包中的默认编辑器Pico。nano不仅复制了Pico的外观&#xff0c;还实现了Pico中一些缺失&#xff08;或默认禁用&#xff09;的功能&#xff0c;例如“搜索和替换”和“转到行号和列号”。nan…

Element Plus的el-tree-select组件,懒加载 + 数据回显

目录一、背景说明二、使用1. dom2.methods三、回显一、背景说明 技术&#xff1a;Vue3 Element Plus需求&#xff1a;在选择组织机构时以树结构下拉展示。用到组件&#xff1a;TreeSelect 树形选择组件&#xff08;el-tree-select&#xff09; 官网文档地址&#xff1a; ht…