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.

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



相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
相关文章
|
6天前
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
27 9
|
6天前
|
缓存 运维 网络协议
深入Linux内核架构:操作系统的核心奥秘
深入Linux内核架构:操作系统的核心奥秘
22 2
|
10天前
|
缓存 网络协议 Linux
Linux操作系统内核
Linux操作系统内核 1、进程管理: 进程调度 进程创建与销毁 进程间通信 2、内存管理: 内存分配与回收 虚拟内存管理 缓存管理 3、驱动管理: 设备驱动程序接口 硬件抽象层 中断处理 4、文件和网络管理: 文件系统管理 网络协议栈 网络安全及防火墙管理
31 4
|
8天前
|
安全 网络协议 Linux
Linux操作系统的内核升级与优化策略####
【10月更文挑战第29天】 本文深入探讨了Linux操作系统内核升级的重要性,并详细阐述了一系列优化策略,旨在帮助系统管理员和高级用户提升系统的稳定性、安全性和性能。通过实际案例分析,我们展示了如何安全有效地进行内核升级,以及如何利用调优技术充分发挥Linux系统的潜力。 ####
28 1
|
11天前
|
物联网 Linux 云计算
Linux操作系统的演变与未来趋势####
【10月更文挑战第29天】 本文深入探讨了Linux操作系统从诞生至今的发展历程,分析了其在服务器、桌面及嵌入式系统领域的应用现状,并展望了云计算、物联网时代下Linux的未来趋势。通过回顾历史、剖析现状、预测未来,本文旨在为读者提供一个全面而深入的视角,以理解Linux在当今技术生态中的重要地位及其发展潜力。 ####
|
13天前
|
安全 Linux 数据安全/隐私保护
Vanilla OS:下一代安全 Linux 发行版
【10月更文挑战第30天】
34 0
Vanilla OS:下一代安全 Linux 发行版
|
16天前
|
人工智能 安全 Linux
|
4月前
|
安全 Linux 网络安全
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
|
1月前
|
Unix 物联网 大数据
操作系统的演化与比较:从Unix到Linux
本文将探讨操作系统的历史发展,重点关注Unix和Linux两个主要的操作系统分支。通过分析它们的起源、设计哲学、技术特点以及在现代计算中的影响,我们可以更好地理解操作系统在计算机科学中的核心地位及其未来发展趋势。
|
3月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
109 3

热门文章

最新文章