zynq操作系统:Linux驱动开发AXIDMA补充篇 多路DMA

简介: Linux驱动开发AXIDMA补充篇 多路DMA

上一篇的一路双通道DMA的正常收发已经成功实现了,但是实际使用的时候大概率会挂载多路dma,那么我们调用的这个模块能不能支持多路的dma便是第一个要解决的问题

 首先阅读初始化部分的代码,自然有了第一个猜测,增加多路设备时,在dev目录是否可以生成多个axidma设备?即使不可以,可不可以通过修改解析设备树的部分代码,编写四个模块加载四次呢?(最后没有选择,找到了更简单合适的办法,这个理论上应该也可以吧)

 dmesg模块加载的信息,发现一行打印,说加载成功了一个收通道一个发送通道,如果只有一个设备的话,而且1明显是个变量打印,会不会增加不同设备后会多出通道,然后通过不同的通道ID来进行选择呢?!,第二个猜测感觉更为简单方便,而且从模块开发者的角度考虑,更加符合实际习惯

 开始对设备树通过引用覆盖的方式进行修改,首先就是在原来的基础上要增加节点,新增至四路,并确保每个通道id唯一

&axi_dma_0 {
  dma-channel@40400000 {
  xlnx,device-id = <0x0>;
  };
  dma-channel@40400030 {
  xlnx,device-id = <0x1>;
  };
};
&axi_dma_1 {
  dma-channel@40410000 {
  xlnx,device-id = <0x2>;
  };
  dma-channel@40410030 {
  xlnx,device-id = <0x3>;
  };
};
&axi_dma_2 {
  dma-channel@40420000 {
  xlnx,device-id = <0x4>;
  };
  dma-channel@40420030 {
  xlnx,device-id = <0x5>;
  };
};
&axi_dma_3 {
  dma-channel@40430000 {
  xlnx,device-id = <0x6>;
  };
  dma-channel@40400030 {
  xlnx,device-id = <0x7>;
  };
};

 剩下的dmas和dma-names部分一头雾水,仅仅这样很明显是不可能的,但是目前国内博客里找见的资料来看没有对多路axidma的说明,我们只能找到github源工程,找到readme阅读下对于设备树部分的描述,大致翻译如下:

Device Tree

 驱动程序需要设备树中的一个节点。此节点描述驱动程序具有独占访问权的DMA通道。它还用于探测驱动程序,因此仅在存在该节点时才激活驱动程序。该节点具有以下属性:

 compatible-这必须是字符串“ xlnx,axidma-chrdev”。这用于使驱动程序与设备树节点匹配。

 dmas -Xilinx AXI DMA或VDMA设备树节点的句柄列表(对其他设备树节点的引用),后跟0或1。这是指Xilinx AXI DMA / VDMA设备树节点内部的子节点,0表示当然是第一个子节点。

 dma-names-DMA通道的名称列表。名称可以完全任意,但必须唯一。DMA接口功能需要此功能dma_request_slave_channel(),否则驱动程序将不使用此功能。将来,驱动程序将在打印的消息中使用这些名称。

 对于Xilinx AXI DMA / VDMA设备树节点,唯一的要求是该device-id属性是唯一的,但它们可以完全是任意的。这是在驱动程序中以及从用户空间中引用通道的方式。有关创建AXI DMA / VDMA设备树节点的更多信息,请查阅内核文档。

 这是一个具有发送和接收通道的具有单个AXI DMA IP的系统的设备树节点的简单示例。注意,您将需要针对您的内核树和设置进行调整:

axidma_chrdev: axidma_chrdev@0 {
    compatible = "xlnx,axidma-chrdev";
    dmas = <&axi_dma_0 0 &axi_dma_0 1>;
    dma-names = "tx_channel", "rx_channel";
};
axi_dma_0: axidma0@40400000 {
    #dma-cells = <1>;
    compatible = "xlnx,axi-dma", "xlnx,axi-dma-6.03.a", "xlnx,axi-dma-1.00.a";
    reg = <0x40400000 0x10000>;
    clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
    clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";    
    xlnx,include-sg;    
    xlnx,addrwidth = <32>;
    dma-mm2s-channel@40400000 {
        compatible = "xlnx,axi-dma-mm2s-channel";
        dma-channels = <1>;
        xlnx,datawidth = <64>;
        xlnx,device-id = <0>;
        interrupt-parent = <&intc>;
        interrupts = <0 29 4>;
    };
    dma-s2mm-channel@40400000 {
        compatible = "xlnx,axi-dma-s2mm-channel";
        dma-channels = <1>;
        xlnx,datawidth = <64>;
        xlnx,device-id = <1>;
        interrupt-parent = <&intc>;
        interrupts = <0 30 4>;
    };
};

 好像还是有点云里雾里,偶然间,在关闭的问题里找见了Problem with two dma in design!,

 源地址如下:https://github.com/bperez77/xilinx_axidma/issues/98

 楼主提出了挂载2个设备找不到通道的问题,不过很可惜,是因为平台不同导致的,ultrascale是64位的平台,而我所用的7045是32位的,楼主仅仅对datawidth做了更改后就解决了问题,不过收获还是很明显的,在楼主和遇见类似问题(我就不信没人用多个dma)的讨论中,我看到了这样的一张图:

@honorpeter it seems like you have succeeded someway but i have no idea how this kind message showed up
45.547129] axidma:axidma dma.c:axidma dma init:719:DMA:Found2 transmit channels and 2 receive channels.45.557138] axidma:axidmadma.c:axidma dma_init:721:VDMA:Found 0 transmit channels and o receive channels. root@pynq:~/DMA_Loop_cache/memory#

 一下确定了我的第二个猜想,继续阅读评论,在楼主没解决问题的时候,有软件工程师提出了这样的修改建议

What if you try to set in pl.dtsi something like this:
amba_pl:amba_pl@@ {
....
axidma chrdev:axidma chrdev@0 {
compatible = "xlnx,axidma-chrdev";
dmas=<&ps2p1a&pl2ps1>; // note to the 1 after pl2ps, it is the xlnx,device-id
};  dma-names = "tx channel", "rx channel"; Hx--1024

 楼主虽然两个dma,但是很明显应该只用一个方向的通道,一个用来PL发向PS,一个PS发给PL,观察这里对dmas的注释,提到了0和1是设备号,难道是我们新加的通道唯一的编号吗,(在之前只有一个是刚好发通道编号0收通道编号1),不论是模块编写者还是问题建议者在这块的描述都会导致我理解上有歧义,挨个试呗,所幸在我将0和1改成2和3后及时的报了加载失败的错误,终于明白该怎么办了(只能是0和1!!!)如果只用一个通道的话就是下面这种情况了

@suikammd And there is something wrong with your axidma chrdev dmas =<&pl2ps 0 &ps2pl 1>;
ifyou use two dma with only one channel both value should be 0
dmas=<&pl2ps 0 &ps2pl e>;
Andt seems like you set the dma-names in opposite if your desiqn is to send data from ps ddr to pl ddr
A list of phandles (references to other device tree nodes) of Xilinx AXI DMA or VDMA device tree nodes, followed by either 0 or 1. This refers to the child node inside of the Xilinx AXI DMA/VDMA device tree node, 0 of course being the first child node.

 而dma-names就很好理解了,因为每个通道都应该是独一无二的,那么起名字也应该对其区分,那么完整的修改就出来了

/include/ "system-conf.dtsi"
/ {
};
&amba_pl {
  axidma_chrdev: axidma_chrdev@0 {
  compatible = "xlnx,axidma-chrdev";
  dmas = <&axi_dma_0 0 &axi_dma_0 1 &axi_dma_1 0 &axi_dma_1 1 &axi_dma_2 0 &axi_dma_2 1 &axi_dma_3 0 &axi_dma_3 1 >;
  dma-names = "tx_channel", "rx_channel", "tx_channel1", "rx_channel1", "tx_channel2", "rx_channel2", "tx_channel3", "rx_channel3";
  };
};
&axi_dma_0 {
  dma-channel@40400000 {
  xlnx,device-id = <0x0>;
  };
  dma-channel@40400030 {
  xlnx,device-id = <0x1>;
  };
};
&axi_dma_1 {
  dma-channel@40410000 {
  xlnx,device-id = <0x2>;
  };
  dma-channel@40410030 {
  xlnx,device-id = <0x3>;
  };
};
&axi_dma_2 {
  dma-channel@40420000 {
  xlnx,device-id = <0x4>;
  };
  dma-channel@40420030 {
  xlnx,device-id = <0x5>;
  };
};
&axi_dma_3 {
  dma-channel@40430000 {
  xlnx,device-id = <0x6>;
  };
  dma-channel@40400030 {
  xlnx,device-id = <0x7>;
  };
};

 这总没有问题了吧!

 但是很明显没有这么顺利

xidma:axidma of.c:axidma of parse channel: 92: Device tree node dma: DMA has more than two channel nodes. xidma:probe of amba pl:axidma chrdev00 failed with error -38

 DMA超过两个节点了!难道模块仅仅支持两个dma设备吗

 先减少至两个试试

 果然我也出现了识别到两个发通道和两个收通道的好消息

axidma:axidma_dma.c:axidma_dma_init:718:DMA:Found 2 transmit channels and 2 receive channels. axidma:axidma_dma.c:axidma_dma_init:720:VDMA:Found 0 transmit channels and 0 receive channels.

 难道还要回到第一种猜想?

 所幸,模块开发者对于错误打印的编写做的太棒了,都不用复制错误信息grep,直接找到提示的c文件,函数,92行就找到了错误打印的源头,

80  static int axidma_of_parse_channel(struct device node *dma_node, int channel, 
81  struct axidma chan *chan, struct axidma device *dev)  
82  { 
83  int rc; 
84  struct device node *dma chan_node;  
85  u32 channel id; 
86
87  // Verify that the DMA node has two channel (child) nodes, one for Tx and rx  
88  if (of get child count(dma node) < 1) { 
89  axidma node_err(dma node, "DMA does not have any channel nodes.\n");  
90  return -EINVAL; 
91  } else if (of get child count(dma node) > 2) {  
92  axidma node err(dma node, "DMA has more than two channel nodes.\n");  
93  return -EINVAL; 
94  95  Hx--1024

 既然限制了不超过两个,我先强行改成4个试试,或许是参数的保护呢?(我不相信有开发者会在支持多设备时仅仅局限于 多=2)

axidma: axidma_dma.c:axidma_dma_init:718:DMA:Found 4transmit channels and 4 receive channels.
dm  dm  750.  VDMA.

剩下的就顺理成章接着调试了!



相关文章
|
9天前
|
监控 Unix Linux
Linux操作系统调优相关工具(四)查看Network运行状态 和系统整体运行状态
Linux操作系统调优相关工具(四)查看Network运行状态 和系统整体运行状态
26 0
|
10天前
|
Linux 编译器 开发者
Linux设备树解析:桥接硬件与操作系统的关键架构
在探索Linux的庞大和复杂世界时🌌,我们经常会遇到许多关键概念和工具🛠️,它们使得Linux成为了一个强大和灵活的操作系统💪。其中,"设备树"(Device Tree)是一个不可或缺的部分🌲,尤其是在嵌入式系统🖥️和多平台硬件支持方面🔌。让我们深入了解Linux设备树是什么,它的起源,以及为什么Linux需要它🌳。
Linux设备树解析:桥接硬件与操作系统的关键架构
|
26天前
|
Linux 数据安全/隐私保护 虚拟化
Linux技术基础(1)——操作系统的安装
本文是龙蜥操作系统(Anolis OS) 8.4 的安装指南,用户可以从[龙蜥社区下载页面](https://openanolis.cn/download)获取ISO镜像。安装方法包括物理机的光驱和USB闪存方式,以及虚拟机中的VMware Workstation Pro设置。安装过程涉及选择语言、配置安装目标、选择软件集合和内核,设置Root密码及创建新用户。安装完成后,可通过文本模式或图形化界面验证系统版本,如Anolis OS 8.4,标志着安装成功。
|
9天前
|
Linux
Linux操作系统调优相关工具(三)查看IO运行状态相关工具 查看哪个磁盘或分区最繁忙?
Linux操作系统调优相关工具(三)查看IO运行状态相关工具 查看哪个磁盘或分区最繁忙?
19 0
|
3天前
|
Linux 内存技术 Perl
【ZYNQ】制作从 QSPI Flash 启动 Linux 的启动文件
【ZYNQ】制作从 QSPI Flash 启动 Linux 的启动文件
|
13天前
|
Linux API C语言
FFmpeg开发笔记(一)搭建Linux系统的开发环境
本文指导初学者如何在Linux上搭建FFmpeg开发环境。首先,由于FFmpeg依赖第三方库,可以免去编译源码的复杂过程,直接安装预编译的FFmpeg动态库。推荐网站<https://github.com/BtbN/FFmpeg-Builds/releases>提供适用于不同系统的FFmpeg包。但在安装前,需确保系统有不低于2.22版本的glibc库。详细步骤包括下载glibc-2.23源码,配置、编译和安装。接着,下载Linux版FFmpeg安装包,解压至/usr/local/ffmpeg,并设置环境变量。最后编写和编译简单的C或C++测试程序验证FFmpeg环境是否正确配置。
35 8
FFmpeg开发笔记(一)搭建Linux系统的开发环境
|
27天前
|
存储 Shell Linux
【Shell 命令集合 网络通讯 】⭐Linux 显示当前系统的主机名和操作系统类型 uuname命令 使用教程
【Shell 命令集合 网络通讯 】⭐Linux 显示当前系统的主机名和操作系统类型 uuname命令 使用教程
28 0
|
10天前
|
Web App开发 Linux 网络安全
工作中常用到的Linux命令
工作中常用到的Linux命令
|
10天前
|
Web App开发 Java Linux
Linux之Shell基本命令篇
Linux之Shell基本命令篇
Linux之Shell基本命令篇