OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4837|回复: 1

[XILINX] 《领航者ZYNQ之嵌入式Linux开发指南_V2.0》第四十一章 使用AXI GPIO

[复制链接]

1107

主题

1118

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4615
金钱
4615
注册时间
2019-5-8
在线时间
1218 小时
发表于 2022-3-29 16:53:00 | 显示全部楼层 |阅读模式
1)实验平台:正点原子领航者V2 ZYNQ开发板
2)  章节摘自【正点原子】《领航者ZYNQ之嵌入式Linux开发指南_V2.0》
3)购买链接:https://detail.tmall.com/item.htm?id=609032204975
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-329957-1-1.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子FPGA技术交流QQ群:90562473








第四十一章 使用AXI GPIO

       在前面所有驱动篇教程章节当中,我们只使用到了ZYNQ 7010/7020 PS端GPIO外设,包括驱动LED、蜂鸣器以及按键等,在《领航者ZYNQ之嵌入式开发指南》文档第五章教程“AXI GPIO按键控制LED实验”中给大家详细介绍过,PS端GPIO是一个硬核外设(Hard IIP),它是在SoC生产时在硅片中实现的功能逻辑电路,当然不仅仅只有GPIO,例如PS端的I2C、SPI、QSPI、SD等这些都是硬核外设。
       对于ZYNQ这种PL+PS(可以理解为ARM + FPGA)结构的SoC处理器来说,除了硬核外设,我们还可以使用软核外设。与硬核外设不同,软核即ZYNQ芯片在出厂时并不存在这样的一个硬件电路,而是由用户通过配置PL端的逻辑资源(硬件编程)来实现的一个功能逻辑电路模块。
       本章我们要介绍如何在vivado中调用AXI GPIO IP核,来实现一个软核GPIO外设,与《领航者ZYNQ之嵌入式开发指南》文档第五章教程“AXI GPIO按键控制LED实验”不一样的是,本章我们要在Linux环境下驱动并使用它。
       1.1AXI GPIO IP简介
       关于该IP的简介,在《领航者ZYNQ之嵌入式开发指南》文档第五章教程“AXI GPIO按键控制LED实验”中有给大家介绍过,所以这里就不再啰嗦了!如果想更加详细的了解,可以参考xilinx官方文档pg144-axi-gpio.pdf,在我们的资料光盘中也给大家了,路径为:领航者ZYNQ开发板资料盘(A盘)\8_ZYNQ&FPGA参考资料\Xilinx\Product Guide\pg144-axi-gpio.pdf
       大家都知道,对于一个硬核外设来说,寄存器是我们与外设进行交互的接口,我们可以通过寄存器对外设进行配置、获取它的数据、驱动它等;那么对于软核外设来说,同样也是如此,都是通过寄存器的方式与其进行交互;所以不管是硬核还是软核,大家要明白一个道理,它们在本质上都是相同的。
       AXI GPIO IP模块内部同样提供了寄存器,与硬核外设不同,软核IP模块内部寄存器的基地址不是固定的,而是可以配置的,当我们在vivado中实例化一个IP核(调用一个IP核)的时候,会自动给它分配基地址,当然也是可以自己修改了,打开vivado的Address Editor界面,就可以看到我们的vivado设计中所有的软核IP实例化之后对应的寄存器基地址,例如:
图 41.1.1 查看寄存器基地址

       当vivado工程编译完成之后,这些基地址就可以与这些软核IP实现的模块对应起来。对于硬核外设来说,它们的寄存器基地址都是固定的,而寄存器的基地址在ZYNQ的参考手册上都会有说明。
       接下来带大家简单地看看AXI GPIO IP的寄存器内容,大家也可以参考xilinx官方文档pg144-axi-gpio.pdf,总体寄存器描述信息如下所示:
图 41.1.2 AXI PWM寄存器总述

       从图 41.1.2可以知道,AXI GPIO模块的寄存器数量比较少,比较简单,整体上主要分为数据寄存器、控制寄存器、中断相关寄存器,每一个都是32位寄存器,包括各个寄存器的地址偏移量在图中都有记录,接下来我们简单地聊一聊各个寄存器所提供的配置功能。
       1、数据寄存器
        数据寄存器有两个,分别为GPIO_DATA和GPIO2_DATA,因为AXI GPIO模块可以提供2组GPIO通道,每一组可以提供32个GPIO;GPIO_DATA是第一组通道的数据寄存器,而GPIO2_DATA是第二组通道的数据寄存器,来看看寄存器介绍:
图 41.1.3 GPIO_DATA寄存器

        作为输入模式,读寄存器得到的是输入的值,而写寄存器没有什么效果;对于输出模式,读寄存器得到的总是0,而写寄存器对应的是GPIO的输出值,每一个bit位对应一个GPIO。
       2、控制寄存器
       同样的控制寄存器也有两个,分别为GPIO_TRI和GPIO2_TRI,其实就是GPIO输入、输出控制寄存器,如下所示:
图 41.1.4 GPIO_TRI寄存器

       寄存器相应bit位配置为0表示作为输出模式,配置为1表示作为输入模式。
       3、全局中断使能寄存器
       GIER为全局中断使能寄存器,只有最高位有效,控制AXI GPIO模块的中断使能与禁止,如下所示:
图 41.1.5 GIER寄存器

       写入0禁止全局中断、写入1使能全局中断。
       4、中断使能寄存器
       IPIER为中断使能寄存器,只有最低两个bit位有效,如下所示:

图 41.1.6 IPISR寄存器

       该寄存器可以单独配置两组通道的中断使能、禁止。
       bit[0]:配置通道1中断使能、禁止,设置为0表示禁止通道1中断功能,设置为1表示使能通道1中断功能。
       bit[1]:配置通道2中断使能、禁止,设置为0表示禁止通道1中断功能,设置为1表示使能通道1中断功能。
       5、中断状态寄存器
       IPISR为中断状态寄存器,只有最低两个bit位有效,如下所示:

       它的中断状态非常的简单,只能做到通道级别的状态检查,并不能查询具体是某一个GPIO发生了中断事件,也不能配置GPIO中断触发方式,只能是边沿触发(上升沿和下降沿都可以),所以笔者认为这个IP模块对中断支持的支持不是很好。
        bit[0]:读取的数据为0表示通道1没有发生中断事件,读取的数据为1则表示发生了中断事件。
        bit[1]:读取的数据为0表示通道2没有发生中断事件,读取的数据为2则表示发生了中断事件。
        1.2vivado硬件设计
        在vivado设计中,我们可以画出AXI GPIO IP模块和ZYNQ PS部分之间的连接框图,如下:
图 41.2.1 系统框图

       在《领航者ZYNQ之嵌入式开发指南》文档第五章教程“AXI GPIO按键控制LED实验”中大家就已经见过了;在图中,PS端的M_AXI_GP0作为主端口,与PL端的AXI GPIO IP核以AXI4-Lite总线相连接,其中,AXI互联IP(AXI Interconnect)用于连接AXI存储器映射(memory-mapped)的主器件和从器件;通用中断控制器(GIC)用于管理来自PS或者PL的中断,并把这些中断发送到CPU。
       AXI GPIO与PS端连接示例如下所示:
图 41.2.2 AXI GPIO设计示例

       关于AXI GPIO IP核的配置信息在《领航者ZYNQ之嵌入式开发指南》文档第五章教程“AXI GPIO按键控制LED实验”中也给大家介绍过,所以这里不再重述!
       驱动篇教程当中我们使用了开发板出厂时对应的vivado工程,在这个vivado设计中,也使用到了AXI GPIO IP,用于读取检查LCD id信息。本章想向大家介绍的重点知识一共有三个内容:
       1、明白软核(Soft IP)和硬核(Hard IP)之间的差异和共同点,以及FPGA可编程硬件的本质。
       2、vivado工程设计当中如何使用AXI GPIO IP模块(如何调用),PS与PL之间的连接方式。
       3、在裸机或者是Linux系统中如何使用。
       以上三点当中,前面两个点都已经给大家详细介绍过,接下来就向大家介绍如何在Linux环境下使用AXI GPIO。经常会有很多人问,怎么在Linux系统下驱动、使用软核IP,如果你把笔者前面说到的内容理解了,这是不难的,不管是硬核IP还是软核IP,它们最终的效果都是对应一个电路逻辑功能模块,例如AXI GPIO,它们都提供了可编程的寄存器对其进行配置,实现相应的功能,对驱动开发工程师而言,它们都是一样的。
       例如你要读取AXI GPIO的输入值,首先你需要编程GPIO_TRI寄存器将GPIO配置为输入模式,然后你再去读取GPIO_DATA即可!不管你是在操作硬核外设还是软核外设,对于驱动开发工程师来说,寄存器始终是我们与外设进行交互的接口。
       1.3AXI GPIO设备树节点
       如果想通过软核(Soft IP)的方式来实现GPIO接口,那么可以通过调用AXI GPIO IP它来实现,例如图 41.2.2所示;编译工程导出hdf文件,按照第二十章所示步骤可以自动生成内核或u-boot所需的设备树文件,例如包括pcw.dtsi、pl.dtsi以及system-top.dts等。
       其中pl.dtsi设备树文件中就会自动产生AXI GPIO IP这个软核外设所对应的设备节点信息,例如:
  • 示例代码 41.3.1 AXI GPIO设备树节点示例
    1. gpio1: gpio@41200000 {
    2.     #gpio-cells = <3>;
    3.     clock-names = "s_axi_aclk";
    4.     clocks = <&clkc 15>;
    5.     compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
    6.     gpio-controller ;
    7.     reg = <0x41200000 0x10000>;
    8.     xlnx,all-inputs = <0x0>;
    9.     xlnx,all-inputs-2 = <0x0>;
    10.     xlnx,all-outputs = <0x0>;
    11.     xlnx,all-outputs-2 = <0x0>;
    12.     xlnx,dout-default = <0x00000000>;
    13.     xlnx,dout-default-2 = <0x00000000>;
    14.     xlnx,gpio-width = <0x3>;
    15.     xlnx,gpio2-width = <0x20>;
    16.     xlnx,interrupt-present = <0x0>;
    17.     xlnx,is-dual = <0x0>;
    18.     xlnx,tri-default = <0xFFFFFFFF>;
    19.     xlnx,tri-default-2 = <0xFFFFFFFF>;
    20. };
    21. 复制代码
    22.        关于AXI GPIO IP对应的设备树节点属性描述信息大家可以查看内核源码Documentation/devicetree/bindings/gpio/gpio-xilinx.txt这篇文档,该文档中详细了记录了每一个属性所表达的含义。
    23.        可以看到“#gpio-cells”这个属性等于3,表示如果我们要使用AXI GPIO需要提供3个参数,例如“led-gpio = <&gpio1 0 0 GPIO_ACTIVE_LOW>”,&gpio1表示引用gpio1节点,也就是AXI GPIO对应的设备节点,第一个0表示管脚编号,第二个0表示对应的通道(0表示第一个通道、8表示第二个通道),这两个连起来的意思就是:AXI GPIO模块的第一个通道的0号管脚;而最后一个GPIO_ACTIVE_LOW表示低电平有效。
    24.       “gpio-controller”属性描述了该节点是一个GPIO控制器节点,reg属性描述了AXI GPIO模块所对应的地址空间,包括基地址和长度;compatible属性值有两个,“xlnx,axi-gpio-2.0”和“xlnx,xps-gpio-1.00.a”,在我们的Linux驱动源码中搜索这两个字符串,就可以找到对应的驱动源码文件,这里笔者直接给出它对应的驱动源文件,路径为内核源码目录drivers/gpio/gpio-xilinx.c,驱动代码是由xilinx官方提供的,因为这个IP由xilinx官方提供。
    25.        当打开gpio-xilinx.c文件,找到如下内容:
    26. 示例代码 41.3.2 gpio-xilinx.c部分代码
    27. 767 static const struct of_device_id xgpio_of_match[] = {
    28. 768     { .compatible = "xlnx,xps-gpio-1.00.a", },
    29. 769     { /* end of list */ },
    30. 770 };
    31. 771 MODULE_DEVICE_TABLE(of, xgpio_of_match);
    32. 772
    33. 773 static struct platform_driver xilinx_gpio_driver = {
    34. 774     .probe = xgpio_of_probe,
    35. 775     .remove = xgpio_remove,
    36. 776     .driver = {
    37. 777         .name = "xilinx-gpio",
    38. 778         .of_match_table = xgpio_of_match,
    39. 779         .pm = &xgpio_dev_pm_ops,
    40. 780     },
    41. 781 };
    复制代码



       在第768行中,可以看到该驱动源码的compatible对应的匹配字符串就是“xlnx,xps-gpio-1.00.a”,所以示例代码 41.3.1中的设备节点就能够和该驱动源码匹配成功!
       关于gpio-xilinx.c驱动源码这里笔者就不给大家分析了,寄存器相关的硬件操作都在这个驱动文件,除此之外还涉及到GPIO驱动框架相关的代码,这是后面的章节的内容,以后再给大家讲。内核默认配置使能了AXI GPIO的驱动,所以不需要我们menuconfig再去配置,可以直接使用,关于AXI GPIO的使用我们讲到这里了,在使用上跟PS端GPIO是一样的,比如在驱动代码中,of_get_named_gpio得到GPIO的编号、gpio_request或devm_gpio_request申请使用GPIO、gpio_direction_output设置GPIO为输出模式等等。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

8

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
91
金钱
91
注册时间
2019-10-29
在线时间
31 小时
发表于 2022-6-12 11:43:18 | 显示全部楼层
原子哥,请问使用通过AXI-gpio 如何实现中断.我在注册中断
    ret = of_irq_to_resource(misc_axi_gpio.nd ,0, &res);

            if (!ret) {

                printk("GPIO IRQ not connected %d\r\n", ret);

                return 0;

        }

    printk("ret %d\r\n",ret);

    xgpio_set_irp_type(misc_axi_gpio.axi_gpio)

加载模块提示如下错误:
misc_axi_gpio.irq: 45
genirq: Setting trigger mode 2 for irq 45 failed (xgpio_set_irq_type+0x0/0x10)

请问如何操作中断?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-10-4 02:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表