0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

AXI_GPIO简介与使用指南

FPGA之家 来源:CSDN技术社区 作者:Vuko-wxh 2022-07-19 17:36 次阅读

学习内容

前面简单学习了关于GPIO的操作,本次将使用PL 端调用 AXI GPIO IP 核, 并通过 AXI4-Lite 接口实现 PS 与 PL 中 AXI GPIO 模块的通信

开发环境

vivado 18.3SDKPYNQ-Z2

AXI_GPIO简介


AXI GPIO IP 核为 AXI 接口提供了一个通用的输入/输出接口。与 PS 端的 GPIO 不同, AXI GPIO 是一个软核( Soft IP),即 ZYNQ 芯片在出厂时并不存在这样的一个硬件电路, 而是由用户通过配置 PL 端的逻辑资源来实现的一个功能模块。而 PS 端的 GPIO 是一个硬核( Hard IP) ,它是一个生产时在硅片中实现的功能电路。我们之前驱动的MIO接口,他属于PS端口的一个搭载好的硬件资源,而对于AXI_GPIO这样一个IP核来说他就相当于与在PL的逻辑端口实现了一个软核IP的GPIO接口。AXI 接口作为 ZYNQ PS 和 PL 之间的桥梁, 能够使两者协同工作,进而形成一个完整的、 高度集成的系统。AXI GPIO 可以配置成单通道或者双通道, 每个通道的位宽可以单独设置。另外通过打开或者关闭三态缓冲器, AXI GPIO 的端口还可以被动态地配置成输入或者输出接口。其顶层模块的框图如下所示:


a0e999e8-06f8-11ed-ba43-dac502259ad0.png


模块的左侧实现了一个 32 位的 AXI4-Lite 从接口, 用于主机访问 AXI GPIO 内部各通道的寄存器。当右侧接口输入的信号发生变化时,模块还能向主机产生中断信号。不过只有在配置 IP核时选择“ 使能中断” , 才会启用模块的中断控制功能。

我们可以在xilinx的一个说明书(UG144)中详细的看到关于AXI_GPIO IP的具体的寄存器,对于不同功能的配置我们只需要像在ARM开发中进行寄存器的配置即可,但寄存器的操作过于繁琐,在一般的开发过程中我们通常进行的都是库函数的使用调用。

在文档中我们可以看到IP的以下特点,基本包含了硬件GPIO的所有功能。设置输入输出模式,设置中断等。

a0f801b8-06f8-11ed-ba43-dac502259ad0.png

引脚说明表如下,在这个表中,大致分为了两类,第一类s_axi接口的相关引脚,用于配置挂载到AXI总线,s_axi_*这是一组信号接口,用于进行数据的交互和配置;第二类是和GPIO有关的信号接口,这里的IP中有两组gpio,每组输出三个信号经过一个三态缓存器实现三态输出。为了实现中断功能,这里的ip2intc_irpt是中断的敏感信号。


a108f2e8-06f8-11ed-ba43-dac502259ad0.png


编程指南

同样在UG144中我们可以找到对于AXI_GPIO IP在应用开发的时候的一个编程指南

设置带中断的INPUT

  1. 将端口配置为输入,将相应的位写入GPIOx_TRI寄存器,值为1。
  2. 通过设置IP中断使能中相应的位使能通道中断注册;也可以通过设置全局中断的第31位来启用全局中断注册为1。
  3. 当接收到中断时,读取GPIOx_DATA寄存器中相应的位。通过写入值为1的对应位来清除IP中断状态寄存器中的状态。

这里的编程指南描述的是寄存器的配置流程,在我们的实际应用中简单来说就是调用库函数配置端口为输入,然后进行中断功能的注册(类似前文的GPIO的按键中断)。

配置为普通的INPUT

  1. 将端口配置为输入,将相应的位写入GPIOx_TRI寄存器,值为1。
  2. 读取GPIOx_DATA寄存器中相应的位。

配置为普通的OUTPUT

  1. 通过在GPIOx_TRI寄存器中写入值为0的对应位,将端口配置为输出。
  2. 将相应的位写入GPIOx_DATA寄存器。

工程系统框图

实现功能为使用EMIO的引脚驱动LED,使用AXI_GPIO的IP进行按键控制,当我们按键按下时,我们的LED进行一次反转。
a114b36c-06f8-11ed-ba43-dac502259ad0.png

硬件平台搭建

同样重复前面的步骤,打开vivado工具的block design 添加ZYNQ的IP核,完成基础配置。

a11dd014-06f8-11ed-ba43-dac502259ad0.png


然后打开MIO configuration,对EMIO引脚的LED进行配置

a12c8f8c-06f8-11ed-ba43-dac502259ad0.png


因为这里我们要使用AXI_GPIO的中断功能,所以我们打开中断界面进行配置,开启中断后,勾选PL到PS的中断功能。这里的中断标号有16个,对应原则是[15:0]对应的是[91:84]:[68:61],这里我们只使用了一个中断,所以我们的中断标号是61。

a13b3b68-06f8-11ed-ba43-dac502259ad0.png

配置完成后添加AXI_GPIO的IP核。配置使能中断,GPIO的位宽选择为1即可。

a14bb9b6-06f8-11ed-ba43-dac502259ad0.png

完成配置后得到下图点击运行自动连接,可以进行帮助我们进行对应端口的自动连接:

a157c8c8-06f8-11ed-ba43-dac502259ad0.png自动连接完成后如图所示:a16447b0-06f8-11ed-ba43-dac502259ad0.png



这里工具帮助我们完成了大部分的连接,但是没有帮助我们进行中断功能的连线,我们需要手动进行连接。

a16f7ae0-06f8-11ed-ba43-dac502259ad0.png

手动连接完成:

a17a4c40-06f8-11ed-ba43-dac502259ad0.png


完成设计后,我们进行generate output product 然后生成HDL封装。接着就对应引脚进行引脚约束即可(PYNQ的粉色开发板可以直接引用这个约束):

set_property -dict { PACKAGE_PIN R14   IOSTANDARD LVCMOS33 } [get_ports { GPIO_0_tri_io[0] }]; #IO_L6N_T0_VREF_34 Sch=led[0]
set_property -dict { PACKAGE_PIN D19   IOSTANDARD LVCMOS33 } [get_ports { axi_gpio0_tri_io[0] }]; #IO_L4P_T0_35 Sch=btn[0]

完成约束后进行综合布局布线,等待生成bit流文件。bit文件生成后在FILE处,点击导出硬件资源(包含bit流文件),接着launch SDK。

软件部分编写

这里引用的AXI GPIO的资源对应的是gpio的部分,配置相应的功能函数可以参考相应的文件和对应的例程。

a186df82-06f8-11ed-ba43-dac502259ad0.png


首先给出我本次的工程代码,在后面进行简要的说明:

#include 
#include "platform.h"
#include "xil_printf.h"
#include "xgpiops.h"
#include "xgpio.h"
#include "xparameters.h"
#include "xparameters_ps.h"
#include "xscugic.h"
#include "sleep.h"
//设置设备id和io编号
#define GPIO_ID XPAR_XGPIOPS_0_DEVICE_ID //PS GPIO的器件ID
#define AXI_GPIO_ID XPAR_GPIO_0_DEVICE_ID//AXIGPIO的器件ID
#define SCUGIC_ID XPAR_PS7_SCUGIC_0_DEVICE_ID//中断的ID
//axi gpio的中断号
#define AXI_GPIO_INTR_ID XPAR_FABRIC_GPIO_0_VEC_ID
#define LED0 54
//axi gpio通道1
#define AXI_GPIO_CHANNEL 1
//定义调用GpioPs的结构体
XGpioPs gpiops;
XGpioPs_Config *gpio_cfg;
//定义调用中断的结构体
XScuGic gpio_gic;
XScuGic_Config *gpio_gic_cfg;
//定义调用Gpio的结构体
XGpio axi_Gpio;
//变量声明
u32 key_value=0;
//函数声明
void Init_gpio();
void IntrHandler();
int main()
{
u32 led_status=0;
    init_platform();
    Init_gpio();
    Init_interrupt();
    print("axi_gpio TEST

");
    while(1)
    {
    if(key_value==1){
    //清除中断状态
    if(XGpio_DiscreteRead(&axi_Gpio, AXI_GPIO_CHANNEL)==1){
    led_status=~led_status;
    }
    XGpio_InterruptClear(&axi_Gpio, 0x0000001);
    key_value=0;

    XGpioPs_WritePin(&gpiops,LED0,led_status);
    usleep(200000);
    //打开中断使能
    XGpio_InterruptEnable(&axi_Gpio, 0x0000001);//使能中断
    }
    }
    cleanup_platform();
    return 0;
}
//初始化gpio
void Init_gpio(){
//查找设备ID,gpio初始化操作
gpio_cfg=XGpioPs_LookupConfig(GPIO_ID);
XGpioPs_CfgInitialize(&gpiops,gpio_cfg,gpio_cfg->BaseAddr);
//设置gpio为输出,开启使能
XGpioPs_SetDirectionPin(&gpiops,LED0,1);
XGpioPs_SetOutputEnablePin(&gpiops,LED0,1);
//对PL端的gpio进行初始化
XGpio_Initialize(&axi_Gpio,AXI_GPIO_ID);
//对AXI设置方向
XGpio_SetDataDirection(&axi_Gpio,AXI_GPIO_CHANNEL,0x0000001);//设置为输入

}
void Init_interrupt(){
//初始化gic
gpio_gic_cfg = XScuGic_LookupConfig(SCUGIC_ID);
XScuGic_CfgInitialize(&gpio_gic,gpio_gic_cfg,gpio_gic_cfg->CpuBaseAddress);

//初始化异常处理
Xil_ExceptionInit();
//CPU中断异常注册
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&gpio_gic);
//使能处理器中断
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

//链接中断信号
XScuGic_Connect(&gpio_gic,AXI_GPIO_INTR_ID,(Xil_InterruptHandler)IntrHandler,&axi_Gpio);
//使能中断
XScuGic_Enable(&gpio_gic,AXI_GPIO_INTR_ID);
//0xa0中断优先级
XScuGic_SetPriorityTriggerType(&gpio_gic,AXI_GPIO_INTR_ID,0xA0, 0x3);
//axi gpio使能中断
XGpio_InterruptGlobalEnable(&axi_Gpio);//打开全局中断
XGpio_InterruptEnable(&axi_Gpio, 0x0000001);//使能中断
}
void IntrHandler(){
printf("interrupt~~

");
key_value=1;
//关闭中断使能
XGpio_InterruptDisable(&axi_Gpio, 0x0000000);

}

部分代码讲解

代码很类似上次的GPIO的中断功能的代码,这里只是更改了部分函数对axi gpio的ip进行ip的配置,实现带中断的输入功能的KEY。axi的初始化只需要一行代码即可完成,然后根据编程指南设置下方向即可完成输入的配置XGpio_Initialize(&axi_Gpio,AXI_GPIO_ID);//对PL端的gpio进行初始化XGpio_SetDataDirection(&axi_Gpio,AXI_GPIO_CHANNEL,0x0000001);//对AXI设置方向设置为输入对于这里的AXI_GPIO中断的标号就是我们前面提到的61,在这里我们可以进行define一下,方便我们进行引用。#define AXI_GPIO_INTR_ID XPAR_FABRIC_GPIO_0_VEC_ID//axi gpio的中断号在SDK中寻一下这个参数的数据也可以验证我们的标号数值:

a19152b4-06f8-11ed-ba43-dac502259ad0.png

对于axi _gpio,我们配置的时候可以看到,每个IP核有两路GPIO,这里我们只用了通道1,所以我们的通道编号定义为1 #define AXI_GPIO_CHANNEL 1//axi gpio通道1在配置axi gpio的中断功能时,用的了XScuGic_SetPriorityTriggerType(&gpio_gic,AXI_GPIO_INTR_ID,0xA0, 0x3);在寻到该函数定义时候,可以简要了解下参数的配置功能。

a19dd516-06f8-11ed-ba43-dac502259ad0.png

0xa0配置了中断优先级,这里我们不进行中断优先级的配置,所以引用的是示例里面的默认值,中断编号就是我们AXI GPIO的编号,0x03这个值用于配置中断的方式。这里我们的中断有高电平触发和边沿触发模式。我们设置边沿触发后,在我们按下按键会满足两次边沿触发的条件(这里我感觉注释和实际操作不相符),然后回看我们的编程指南,在中断配置时候是也是要求我们:当接收到中断时,读取GPIOx_DATA寄存器中相应的位。通过写入值为1的对应位来清除IP中断状态寄存器中的状态。所以我们就引用了XGpio_DiscreteRead(&axi_Gpio, AXI_GPIO_CHANNEL) 对中断的状态进行读取。对应编程指南代码编写如下:

//清除中断状态
    if(XGpio_DiscreteRead(&axi_Gpio, AXI_GPIO_CHANNEL)==1){
   led_status=~led_status;
    }
    XGpio_InterruptClear(&axi_Gpio, 0x0000001);

完成代码编写后下载到我们的PYNQ的开发板即可完成本次实验。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • GPIO
    +关注

    关注

    16

    文章

    1191

    浏览量

    51876
  • Zynq
    +关注

    关注

    9

    文章

    607

    浏览量

    47112
  • AXI
    AXI
    +关注

    关注

    1

    文章

    127

    浏览量

    16585

原文标题:软件部分编写

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    ARM+FPGA开发:基于AXI总线的GPIO IP创建

    FPGA+ARM是ZYNQ的特点,那么PL部分怎么和ARM通信呢,依靠的就是AXI总线。这个实验是创建一个基于AXI总线的GPIO IP,利用PL的资源来扩充GPIO资源。通过这个实验
    的头像 发表于 12-25 14:07 5556次阅读
    ARM+FPGA开发:基于<b class='flag-5'>AXI</b>总线的<b class='flag-5'>GPIO</b> IP创建

    Xilinx ZYNQ开发GPIO的三种方式:MIO、EMIO、AXI_GPIO

    前言: ZYNQ 7000有三种GPIO:MIO,EMIO,AXI_GPIO MIO是固定管脚的,属于PS,使用时不消耗PL资源;EMIO通过PL扩展,使用时需要分配管脚,使用时消耗PL管脚资源
    的头像 发表于 12-26 10:12 3842次阅读
    Xilinx ZYNQ开发<b class='flag-5'>GPIO</b>的三种方式:MIO、EMIO、<b class='flag-5'>AXI_GPIO</b>

    GPIO2接口上添加三态GPIO端口时会导致错误

    AXI_GPIO中存在一个小错误,可以防止使用电路板文件。在Vivado / 2016.2 / data / ip / xilinx / axi_gpio_v2_0 / xgui
    发表于 04-19 10:32

    MIO/EMIO/AXI_GPIO接口详解

    ZYNQ-7000系列MIO/EMIO/AXI_GPIO接口
    发表于 02-02 07:30

    PWM使用指南

    日期作者版本说明2020.09.26TaoV0.0撰写中目录简要介绍常用配置设置更新中断输出PWM脉冲捕获输出带死区控制的互补PWM使用指南简要介绍常用配置设置更新中断输出PWM脉冲捕获输出带死区控制的互补PWM使用指南...
    发表于 08-09 08:54

    HPM6700/6400系列微控制器GPIO模块使用指南

    HPM6700_6400_GPIO使用指南
    发表于 06-02 06:30

    学习架构-AMBA AXI简介

    指南介绍了高级微控制器总线体系结构(AMBA)AXI的主要功能。 该指南解释了帮助您实现AXI协议的关键概念和细节。 在本指南中,我们介绍
    发表于 08-09 07:37

    AT32F421 GPIO使用指南

    AT32F421 GPIO 使用指南AT32F421系列的GPIO还提供了丰富I/O复用功能,能够使得多个外设可以同时工作,并且保证每个引脚在某一时刻只会连接到一个外设,从而避免了外设冲突的产生。
    发表于 10-24 07:53

    AT32F413/415 GPIO使用指南

    AT32F413/415 GPIO使用指南介绍AT32F413/415 的GPIO 功能及固件驱动程序API 的配置和使用,并对BSP 例程的软件设计加以说明,同时演示使用方法并展示实验效果,供用户参考。
    发表于 10-25 08:24

    ZYNQ 的三种GPIO :MIO、EMIO、AXI

    GPIO的博客说的有一些不一样呢。 我们先看有哪三种GPIO:MIO、EMIO、AXI_GPIO。其中MIO和EMIO是直接挂在PS上的GPIO。而
    发表于 02-08 10:23 3245次阅读
    ZYNQ 的三种<b class='flag-5'>GPIO</b> :MIO、EMIO、<b class='flag-5'>AXI</b>

    FreeRTOS 使用指南

    FreeRTOS 使用指南
    发表于 10-24 13:37 25次下载
    FreeRTOS <b class='flag-5'>使用指南</b>

    被zynq的GPIO唬住,告诉你zynq的3种GPIO

    我们先看有哪三种GPIO:MIO、EMIO、AXI_GPIO。其中MIO和EMIO是直接挂在PS上的GPIO。而AXI_GPIO是通过AXI
    发表于 07-07 08:23 5180次阅读

    电子票使用指南免费下载

    电子票使用指南电子票使用指南电子票使用指南电子票使用指南电子票使用指南电子票使用指南
    发表于 11-24 14:02 3次下载

    ZYNQ-7000系列MIO、EMIO、AXI_GPIO接口

    ZYNQ-7000系列MIO/EMIO/AXI_GPIO接口
    发表于 07-25 17:41 2634次阅读
    ZYNQ-7000系列MIO、EMIO、<b class='flag-5'>AXI_GPIO</b>接口

    ZYNQ-7000系列MIO/EMIO/AXI_GPIO接口

    ZYNQ-7000系列MIO/EMIO/AXI_GPIO接口
    发表于 01-31 06:50 12次下载
    ZYNQ-7000系列MIO/EMIO/<b class='flag-5'>AXI_GPIO</b>接口