Xilinx XDMA 数据传输sgdma 驱动代码分析
我的之前两篇文章有介绍到上位机软件的逻辑该如何控制,驱动代码的框架是怎样的,驱动的整体逻辑在linux系统中是如何实现的,感兴趣的小伙伴可以去考古。
Xilinx XDMA 上位机应用程序控制逻辑
Xilinx XDMA驱动代码分析及用法
XDMA 传输的核心部分代码是cdev_sgdma.c ,利用DMA进行数据传输,传输方式为sgdma的传输方式,
1、SG-DMA介绍
Scatter-Gather DMA ,分散/集中映射是流式 DMA 映射的一个特例。它将几个缓冲区集中到一起进行一次映射,并在一个 DMA 操作中传送所有数据。这些分散的缓冲区由分散表结构scatterlist来描述,多个分散的缓冲区的分散表结构组成缓冲区的struct scatterlist数组。
[DMA技术和及其SG模式](https://blog.csdn.net/chinamaoge/article/details/104606865)
2、sgdma IO文件操作接口
cdev_sgdma.c 是xdma 驱动传输的主要接口,驱动正确安装后会生成xdma0_c2h_0 xdma0_h2c_0 的读写设备。
上位机程序。通过文件io.read\write 调用驱动的read\write,以触发sgdma进行数据传输,传输完成会有中断,之余中断时如何使用的,感兴趣的朋友看一下一起的文章。
char_sgdma_read 、char_sgdma_write 两个接口调用同一个接口进行数据输出, 接口以一个bool变量驱动,数据是读还是写。
函数原型:
static ssize_t char_sgdma_read_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos, bool write);
函数的调用关系如图
static ssize_t char_sgdma_read_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos, bool write)
{
int rv;
ssize_t res = 0;
struct xdma_cdev *xcdev = (struct xdma_cdev *)file->private_data;
struct xdma_dev *xdev;
struct xdma_engine *engine;
struct xdma_io_cb cb;
rv = xcdev_check(__func__, xcdev, 1);
if (rv < 0)
return rv;
xdev = xcdev->xdev;
engine = xcdev->engine;
dbg_tfr("file 0x%p, priv 0x%p, buf 0x%p,%llu, pos %llu, W %d, %s.\n",
file, file->private_data, buf, (u64)count, (u64)*pos, write,
engine->name);
if ((write && engine->dir != DMA_TO_DEVICE) ||
(!write && engine->dir != DMA_FROM_DEVICE)) {
pr_err("r/w mismatch. W %d, dir %d.\n",
write, engine->dir);
return -EINVAL;
}
rv = check_transfer_align(engine, buf, count, *pos, 1);
if (rv) {
pr_info("Invalid transfer alignment detected\n");
return rv;
}
memset(&cb, 0, sizeof(struct xdma_io_cb));
cb.buf = (char __user *)buf;
cb.len = count;
cb.ep_addr = (u64)*pos;
cb.write = write;
rv