MPSOC上PS和PL基于UIO的中断(linux)

                                                                       MPSOC上PS和PL基于UIO的中断(linux)

                                                                                                                                             alvin.lu@avnet.com

                                                                                                                                             2020.09.12

软件平台:
Vivado 2018.3
PetaLinux 2018.3
Ubuntu16.04.6真机

硬件平台:
ZCU102 (ZynqMP)

 

Vivado框图如下

 

管脚约束如下,对照原理图选择sw13的低4位

 

然后编译vivado生成bit并且导出hdf文件,

petalinux创建以及编译的流程参考上一篇

MPSOC上PS和PL基于bram进行数据交互(linux)

这里需要注意的一点,由于uio部分petalinux不会自动生成节点,所以需要手动在system-user.dtsi添加对应的dts描述

首先修改project-spec/meta-user/recipes-bsp/device-tree/device-tree.bbappend如下

FILESEXTRAPATHS_prepend := "${THISDIR}/files:"

SRC_URI_append ="\
    file://system-user.dtsi \
    file://pl.dtsi \
"
然后修改system-user.dtsi如下

/include/ "system-conf.dtsi"
#include "pl.dtsi"
/ {
    chosen {
        bootargs = "earlycon clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio";
        stdout-path = "serial0:115200n8";
    };
};
接下来就是创建一个pl.dtsi文件

如下

/*
 * CAUTION: This file is automatically generated by Xilinx.
 * Version:  
 * Today is: Sat Sep 12 04:53:17 2020
 */


/ {
        amba_pl: amba_pl@0 {
                #address-cells = <2>;
                #size-cells = <2>;
                compatible = "simple-bus";
                ranges ;
                axi_bram_ctrl_0: axi_bram_ctrl@b0000000 {
                        clock-names = "s_axi_aclk";
                        clocks = <&clk 71>;
                        compatible = "xlnx,axi-bram-ctrl-4.1";
                        reg = <0x0 0xb0000000 0x0 0x1000>;
                        xlnx,bram-addr-width = <0xa>;
                        xlnx,bram-inst-mode = "EXTERNAL";
                        xlnx,ecc = <0x0>;
                        xlnx,ecc-onoff-reset-value = <0x0>;
                        xlnx,ecc-type = <0x0>;
                        xlnx,fault-inject = <0x0>;
                        xlnx,memory-depth = <0x400>;
                        xlnx,rd-cmd-optimization = <0x0>;
                        xlnx,read-latency = <0x1>;
                        xlnx,s-axi-ctrl-addr-width = <0x20>;
                        xlnx,s-axi-ctrl-data-width = <0x20>;
                        xlnx,s-axi-id-width = <0x1>;
                        xlnx,s-axi-supports-narrow-burst = <0x1>;
                        xlnx,select-xpm = <0x1>;
                        xlnx,single-port-bram = <0x1>;
                };
                axi_gpio_0: gpio@a0000000 {
                        //#gpio-cells = <3>;
                        #gpio-cells = <2>;
                        #interrupt-cells = <2>;
                        clock-names = "s_axi_aclk";
                        clocks = <&clk 71>;
                        //compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
                        compatible = "generic-uio";
                        gpio-controller ;
                        interrupt-controller ;
                        interrupt-names = "ip2intc_irpt";
                        interrupt-parent = <&gic>;
                        interrupts = <0 93 4>;
                        reg = <0x0 0xa0000000 0x0 0x1000>;
                        xlnx,all-inputs = <0x0>;
                        xlnx,all-inputs-2 = <0x0>;
                        xlnx,all-outputs = <0x1>;
                        xlnx,all-outputs-2 = <0x0>;
                        xlnx,dout-default = <0x00000000>;
                        xlnx,dout-default-2 = <0x00000000>;
                        xlnx,gpio-width = <0x8>;
                        xlnx,gpio2-width = <0x20>;
                        xlnx,interrupt-present = <0x1>;
                        xlnx,is-dual = <0x0>;
                        xlnx,tri-default = <0xFFFFFFFF>;
                        xlnx,tri-default-2 = <0xFFFFFFFF>;
                };
                uio@0 {
                    compatible = "generic-uio";
                    status = "okay";
                    interrupt-controller;
                    interrupt-parent = <&gic>;
                    interrupts = <0 89 1>;
                };
                uio@1 {
                    compatible = "generic-uio";
                    status = "okay";
                    interrupt-controller;
                    interrupt-parent = <&gic>;
                    interrupts = <0 90 1>;
                };

                uio@2 {
                    compatible = "generic-uio";
                    status = "okay";
                    interrupt-controller;
                    interrupt-parent = <&gic>;
                    interrupts = <0 91 4>;
                };

                uio@3 {
                    compatible = "generic-uio";
                    status = "okay";
                    interrupt-controller;
                    interrupt-parent = <&gic>;
                    interrupts = <0 92 4>;
                };

                psu_ctrl_ipi: PERIPHERAL@ff380000 {
                        compatible = "xlnx,PERIPHERAL-1.0";
                        reg = <0x0 0xff380000 0x0 0x80000>;
                };
                psu_message_buffers: PERIPHERAL@ff990000 {
                        compatible = "xlnx,PERIPHERAL-1.0";
                        reg = <0x0 0xff990000 0x0 0x10000>;
                };
        };
};
~                            

由于mpsoc的uio中断只支持上升沿和高电平,所以interrupts最后一个参数只能是1或者4,1代表上升沿,4代表高电平.

接下来编译petalinux并且打包BOOT.BIN,拷贝BOOT.BIN和image.ub到sd卡,上电启动开发板

启动linux之后,我们首先看一下uio的对应关系

我现在要测试sw13的GPIO_DIP_SW0,也就是/dev/uio2设备节点,如下图

我来回拨动了9次开关,产生了9次上升沿中断.

 

测试代码如下

/*
 * This application reads/writes GPIO devices with UIO.
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

void usage(void)
{
    printf("*argv[0] -d <UIO_DEV_FILE>\n");
    printf("    -d               UIO device file. e.g. /dev/uio0");
    return;
}

int main(int argc, char *argv[])
{
    int c;
    int fd;
    char *uiod;
    unsigned i = 0;
    unsigned icount;
    int irq_on = 1;
    int err;

    printf("pin UIO test.\n");
    while((c = getopt(argc, argv, "d:io:h")) != -1) {
        switch(c) {
        case 'd':
            uiod=optarg;
            break;
        case 'h':
            usage();
            return 0;
        default:
            printf("invalid option: %c\n", (char)c);
            usage();
            return -1;
        }

    }

    /* Open the UIO device file */
    fd = open(uiod, O_RDWR);
    if (fd < 1) {
        perror(argv[0]);
        printf("Invalid UIO device file:%s.\n", uiod);
        usage();
        return -1;
    }

    for(i = 0; ; ++i) {
        /* Print out a message, for debugging. */
            if (i == 0)
                    fprintf(stderr, "Started uio test driver.\n");
            else
                    fprintf(stderr, "Interrupts: %d\n", icount);

        /* enable IRQ, trigger the irqcontrol of driver */
        write(fd, &irq_on, sizeof(irq_on));
            /* Here we got an interrupt from the
            device. Do something to it. */
        err = read(fd, &icount, 4);
        if (err != 4) {
            perror("uio read:");
            break;
        }
    }

    return 0;
}
~   

关于UIO的详细文档链接 https://01.org/linuxgraphics/gfx-docs/drm/driver-api/uio-howto.html

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值