linux 在system-user.dtsi文件中定义了两个中断,但为什么在/proc/interrupts中只定义了一个中断?

x6yk4ghg  于 5个月前  发布在  Linux
关注(0)|答案(1)|浏览(64)

VIVADO中有一个DMA传输的设计。我想使用uio设备,我有一个/dev/uio0目录沿着/sys/class/uio/uio0/maps/map0目录中的信息。在我的 pl.dtsi 中,我有两个中断,我已经将它们添加到 system-user.dtsi 文件中:

/include/ "system-conf.dtsi"
/ {
    chosen {
            bootargs = "earlycon clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio rootwait quiet loglevel=0";
            stdout-path = "serial0:115200n8";
        };
};

&axi_dma_0 {
    clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
    clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
    interrupt-names = "mm2s_introut", "s2mm_introut";
    compatible = "generic-uio";
    reg = <0x40400000 0x10000>;
    interrupt-parent = <&intc>;
    interrupts = <0 29 4 0 30 4>;

    
};

字符串
然而,在引导后(我使用petalinux构建booing映像和其他文件),我在/proc/interrupts中看到了一个条目

32:          0          0 GIC-0  61 Level     dma


我假设61对应的是mm 2s,因为它对应的是61 - 32 = 29。我不应该在/proc/interupts中看到另一个30的条目吗?

EDIT:当dmesg | grep -C3 dma在我的电脑petalinux项目目录中时,我得到以下内容。

dmesg | grep -C3 dma
[    0.179479] APIC: Switch to symmetric I/O mode setup
[    0.179481] DMAR: Host address width 36
[    0.179483] DMAR: DRHD base: 0x000000fed90000 flags: 0x1
[    0.179488] DMAR: dmar0: reg_base_addr fed90000 ver 1:0 cap c9008020660262 ecap f0105a
[    0.179490] DMAR: RMRR base: 0x000000ded2e000 end: 0x000000ded3cfff
[    0.179492] DMAR-IR: IOAPIC id 2 under DRHD base  0xfed90000 IOMMU 0
[    0.179493] DMAR-IR: HPET id 0 under DRHD base 0xfed90000
--
[    0.529581] system 00:03: [io  0x0a30-0x0a4f] has been reserved
[    0.529584] system 00:03: [io  0x0a00-0x0a0f] has been reserved
[    0.529773] system 00:04: [io  0x04d0-0x04d1] has been reserved
[    0.530002] pnp 00:05: [dma 0 disabled]
[    0.530295] system 00:07: [mem 0xfed1c000-0xfed1ffff] has been reserved
[    0.530298] system 00:07: [mem 0xfed10000-0xfed17fff] has been reserved
[    0.530299] system 00:07: [mem 0xfed18000-0xfed18fff] has been reserved


但是,如果我在我的董事会petalinux目录dmesg | grep -C3 dma我什么也没有得到:另一方面,而引导董事会qspi我得到以下消息。

SF: Detected s25fl256s1 with page size 256 Bytes, erase size 64 KiB, total 32 MiB
device 0 offset 0x9c0000, size 0x40000
SF: 262144 bytes @ 0x9c0000 Read: OK
QSPI: Trying to boot script at 3000000
## Executing script at 03000000
Wrong image format for "source" command
QSPI: SCRIPT FAILED: continuing...
JTAG: Trying to boot script at 3000000
## Executing script at 03000000
Wrong image format for "source" command
JTAG: SCRIPT FAILED: continuing...
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot.scr
3016 bytes read in 16 ms (183.6 KiB/s)
## Executing script at 03000000
Trying to load boot images from qspi
SF: Detected s25fl256s1 with page size 256 Bytes, erase size 64 KiB, total 32 MiB
device 0 offset 0xa80000, size 0x1500000
SF: 22020096 bytes @ 0xa80000 Read: OK
Wrong Image Format for bootm command
ERROR: can't get kernel image!
Booting using Fit image failed
device 0 offset 0xa00000, size 0x600000
SF: 6291456 bytes @ 0xa00000 Read: OK
device 0 offset 0x1000000, size 0xf80000
SF: 16252928 bytes @ 0x1000000 Read: OK
Wrong Image Format for bootm command
ERROR: can't get kernel image!
Booting using Separate images failed
Trying to load boot images from jtag
Wrong Image Format for bootm command
ERROR: can't get kernel image!
Trying to load boot images from mmc0
17834024 bytes read in 1655 ms (10.3 MiB/s)
## Loading kernel from FIT Image at 10000000 ...
   Using 'conf-system-top.dtb' configuration
   Verifying Hash Integrity ... OK
   Trying 'kernel-1' kernel subimage
     Description:  Linux kernel
     Type:         Kernel Image
     Compression:  uncompressed
     Data Start:   0x1000010c
     Data Size:    4654376 Bytes = 4.4 MiB
     Architecture: ARM
     OS:           Linux
     Load Address: 0x00200000
     Entry Point:  0x00200000
     Hash algo:    sha256
     Hash value:   1cf7ebde3d2e20e4297f3bb94fd5b62628d7a00343786bd751f76bab9335fbf9
   Verifying Hash Integrity ... sha256+ OK
## Loading ramdisk from FIT Image at 10000000 ...
   Using 'conf-system-top.dtb' configuration
   Verifying Hash Integrity ... OK
   Trying 'ramdisk-1' ramdisk subimage
     Description:  petalinux-image-minimal
     Type:         RAMDisk Image
     Compression:  uncompressed
     Data Start:   0x10475524
     Data Size:    13157774 Bytes = 12.5 MiB
     Architecture: ARM
     OS:           Linux
     Load Address: unavailable
     Entry Point:  unavailable
     Hash algo:    sha256
     Hash value:   6acad62316441a792f0dc018eb8fdfa293b6358057f648e5a5484309e7d100b5
   Verifying Hash Integrity ... sha256+ OK
## Loading fdt from FIT Image at 10000000 ...
   Using 'conf-system-top.dtb' configuration
   Verifying Hash Integrity ... OK
   Trying 'fdt-system-top.dtb' fdt subimage
     Description:  Flattened Device Tree blob
     Type:         Flat Device Tree
     Compression:  uncompressed
     Data Start:   0x10470740
     Data Size:    19734 Bytes = 19.3 KiB
     Architecture: ARM
     Hash algo:    sha256
     Hash value:   da2cb926234ba4ea5339484c96b5f02f265fa00d2f6e8b50f1bf21d7c9113506
   Verifying Hash Integrity ... sha256+ OK
   Booting using the fdt blob at 0x10470740
Working FDT set to 10470740
   Loading Kernel Image
   Loading Ramdisk to 2f373000, end 2ffff58e ... OK
   Loading Device Tree to 2f36b000, end 2f372d15 ... OK
Working FDT set to 2f36b000

Starting kernel ...

Booting Linux on physical CPU 0x0
Linux version 6.1.5-xilinx-v2023.1 (oe-user@oe-host) (arm-xilinx-linux-gnueabi-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.39.0.20220819) #1 SMP PREEMPT Fri Apr 21 07:47:58 UTC 2023
CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
OF: fdt: Machine model: xlnx,zynq-7000
earlycon: cdns0 at MMIO 0xe0001000 (options '115200n8')
printk: bootconsole [cdns0] enabled
INIT: version 3.04 booting
Starting udev
Starting version 251.8+
hwclock: can't open '/dev/misc/rtc': No such file or directory
Fri Mar  9 12:34:56 UTC 2018
hwclock: can't open '/dev/misc/rtc': No such file or directory
Configuring packages on first boot....
 (This may take several minutes. Please do not power off the machine.)
Running postinst /etc/rpm-postinsts/100-sysvinit-inittab...
update-rc.d: /etc/init.d/run-postinsts exists during rc.d purge (continuing)
 Removing any system startup links for run-postinsts ...
  /etc/rcS.d/S99run-postinsts
INIT: Entering runlevel: 5
Configuring network interfaces... udhcpc: started, v1.35.0
udhcpc: broadcasting discover
udhcpc: broadcasting discover
udhcpc: broadcasting discover
udhcpc: no lease, forking to background
done.
Starting OpenBSD Secure Shell server: sshd
  generating ssh RSA host key...
  generating ssh ECDSA host key...
  generating ssh ED25519 host key...
done.
Starting rpcbind daemon...done.
starting statd: done
hwclock: can't open '/dev/misc/rtc': No such file or directory
Starting internet superserver: inetd.
NFS daemon support not enabled in kernel
Starting syslogd/klogd: done
Starting tcf-agent: OK

ijxebb2r

ijxebb2r1#

简介

使用Userspace IO (UIO)时,每个设备不可能有多个中断。这是因为:

  • 内核代码不支持这种情况。如果我们看一下__uio_register_device()中调用request_irq()的代码,它只提供了一个注册单个中断的功能。
  • 用户空间的API没有区分多个中断的机制。

但是,没有理由不能创建第二个UIO设备,它只具有一个中断属性。一般来说,这看起来像这样:

/ {
    dma0 {
        compatible = "generic-uio";
        reg = <0x40400000 0x10000>;
        clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
        clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
        interrupt-parent = <&intc>;
        interrupts = <0 29 4>;
    };

    dma1 {
        compatible = "generic-uio";
        interrupt-parent = <&intc>;
        interrupts = <0 30 4>;
    };
};

字符串
时钟、寄存器空间和第一个中断将通过一个UIO设备管理,第二个中断将通过另一个UIO设备提供。

PetaLinux

(我不是PetaLinux用户,所以这只是我读到的,可能需要纠正。
在这个特定的示例中,它看起来有点不同。PetaLinux工具将生成一个 pl.dtsi 文件,其中包含一个DMA设备节点。这个节点将在假设内核中的Xilinx DMA Engine驱动程序正在使用的情况下构建。要为这个设备使用UIO,我们有两个选项:用一个新的节点替换生成的节点或更新现有的生成节点。

替换生成的节点

我们可以简单地将 pl.dtsi 文件中的节点标记为要删除,这样它就不会出现在生成的DTB中。这很简单,但意味着某些信息必须从 pl.dtsi 复制到 system-user.dtsi。这很简单,但确实造成了维护问题(例如,如果对设计的改变移动了寄存器的地址,则有必要更新 system-user.dtsi 中的地址,而对 pl.dtsi 的更新将自动发生)。

/include/ "system-conf.dtsi"
/ {
    chosen {
        bootargs = "earlycon clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio rootwait quiet loglevel=0";
        stdout-path = "serial0:115200n8";
    };
};

&amba_pl {
    /delete-node/ &axi_dma_0;

    dma0 {
        compatible = "generic-uio";
        reg = <0x40400000 0x10000>;
        clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
        clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
        interrupt-parent = <&intc>;
        interrupts = <0 29 4>;
    };

    dma1 {
        compatible = "generic-uio";
        interrupt-parent = <&intc>;
        interrupts = <0 30 4>;
    };
};

更新生成的节点

我们可以使用的另一种技术是更新由PetaLinux工具在 pl.dtsi 中生成的节点。这减少了必须复制到 system-user.dtsi 中的信息量(尽管不幸的是我看不到避免复制第二个中断号的方法)。

/include/ "system-conf.dtsi"
/ {
    chosen {
        bootargs = "earlycon clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio rootwait quiet loglevel=0";
        stdout-path = "serial0:115200n8";
    };
};

&amba_pl {   
    dma1 {
        compatible = "generic-uio";
        interrupt-parent = <&intc>;
        interrupts = <0 30 4>;
    };
};

&axi_dma_0 {
    compatible = "generic-uio";
    linux,uio-name = "dma0";
};


请注意,在这种情况下,我们不需要复制clocksreginterrupts属性(尽管只使用interrupts属性中的第一个中断)。
我们还为UIO设备添加了一个名称,这样它就不会使用默认名称(默认名称为dma)。
&axi_dma_0节点中会有很多属性,这些属性只有在使用Xilinx DMA Engine驱动程序时才相关。这些属性可以被删除(使用/delete-property/),但它们应该是无害的,因为UIO驱动程序不会识别它们。

用户空间驱动

然后,您需要计算出哪个/dev/uio设备文件对应于哪个设备。理想情况下,您的驱动程序将打开所有/sys/class/uio/uio<n>/name文件,以计算出哪个UIO设备对应于设备dma0dma1。这样,如果您稍后向设备树添加额外的UIO设备,并且设备编号发生更改,您的代码仍然可以工作。
然后打开/dev/uio<x>/dev/uio<y>,并使用select(2)poll(2)等待其中一个中断发生。

相关问题