ZYNQ7000-AXI GPIO详解

摘要

AXI GPIO是ZYNQ的一个IP核,它能够将PS侧的AXI4-Lite接口转成PL侧的IO口,可解决PS侧IO口不够用的问题。本文就AXI GPIO的概念、作用、配置与使用做了详细说明,展示了示例的Vivado工程和AXI GPIO输入、输出与中断配置的代码。

关键词:AXI GPIOZYNQAXI4-LiteGPIO中断

前言

本文参考:PG144 - AXI GPIO v2.0 Product Guide (v2.0)

一. AXI GPIO的概念与作用

AXI GPIO是ZYNQ PL部分的一个IP软核,此IP核提供AXI-Lite Master接口转GPIO的功能,且一个AXI-Lite Master通过AXI interconnect可以与多个AXI GPIO IP核相连,如下图所示。也就是说PS部分通过GP接口以及AXI GPIO IP核可实现多个GPIO,一个GP接口最多可以接几个AXI GPIO IP核我不知道,手册中没写,我这里接了4个没什么问题。.

我们知道ZYNQ的PS可通过EMIO来使用PL部分的引脚实现GPIO功能,但当使用的引脚很多时,PS程序中控制引脚方向、中断等将变得繁琐,这时如果使用PS的GP接口(AXI3 Master)接口通过AXI Interconnect连接AXI GPIO IP核,就可以在PS部分通过更简单的程序方便地控制众多PL引脚实现GPIO功能。

所以,从功能上来说,PS通过EMIO还是AXI GPIO来实现GPIO没有区别,都能输入/输出以及产生中断,但AXI GPIO在多引脚时在程序的复杂度方面有一定优势

二. AXI GPIO IP核设置与使用

2.1 AXI GPIO的最大工作时钟频率

需要注意,AXI GPIO的AXI-Lite接口的时钟频率,超频可能会导致此IP核无法正常工作

2.2 AXI GPIO设置

AXI GPIO IP核默认为单通道,可选GPIO宽度为1~32,可设置GPIO方向(注意如果在这里设置了All Input/Output,那么在PS程序中就无需再设置GPIO方向,设置了也无效,建议不要在这里设置,通过PS程序去设置,保持灵活性),可设置输出默认值与三态默认值。

可勾选Enable Dual Channel,打开双通道。

可勾选Enable Interrupt,打开GPIO中断功能,此中断属于PL对PS的中断,所以需要连接到ZYNQ7核的IRQ_F2P端口,如下图所示。

因为使用了AXI接口,我们知道AXI是读写数据的,它必须对应存储器(RAM,DDR等),所以在设置好IP核并连线完成后,需要对每个AXI GPIO的S_AXI进行存储器地址映射,规定S_AXI去读写哪个地址段。

打开Address Editor窗口,右击选择Assign All即可。

效果如下图。

这里需要说明,因为在PS的库函数中对多个AXI GPIO的情况是有排序的(在xparameters.h中每个AXI GPIO对应不同的ID,如下图),我们需要知道PL的Block Design中哪个AXI GPIO对应PS库中的AXI GPIO 0,哪个对应AXI GPIO 1。

这里的排序依据是ip核的名称,与同GP0接口相连还是GP1接口相连没有关系,PS并不区分axi gpio与哪个GP相连。axi_gpio_0会被设为ID 0,ID从0开始向后排,若不存在axi_gpio_0,则axi_gpio_1会被设为ID 0,以此类推

明白PL中的axi gpio与PS库函数中的ID的对应关系是重要的,它帮助我们对引脚命名,以及在PS中操作我们想操作的GPIO。

2.3 关于AXI GPIO中断的细节

注意:

1.AXI GPIO只能使能整个通道中断,而无法像EMIO一样单独使能通道中某个引脚的中断,当使能某个通道中断后,该通道所有输入引脚均能产生中断信号,效果完全相同。

一种可行的将中断固定到引脚的办法是设置通道中其它引脚为输出,输出引脚无法产生中断,中断就相当于固定到了唯一的输入引脚上,

2.因为AXI GPIO中断属于IRQ_F2P,而IRQ_F2P的中断类型只能设置为上升沿或者高电平,而不能是下降沿或者低电平。如下图(参考ug585 Table7-4)。

三. 在PS中控制AXI GPIO输入、输出与中断

3.1 AXI GPIO作为输入输出使用,不使用中断

步骤:初始化AXI GPIO -> 设置AXI GPIO方向 -> 读/写AXI GPIO

#include "xgpio.h"
#include "sleep.h"

#define AXIGPIO_CHANNEL_1    1U
#define AXIGPIO_CHANNEL_2    2U

XGpio axiGpio0;
XGpio axiGpio1;

int main(void)
{
	// 初始化AXI GPIO
	XGpio_Initialize(&axiGpio0, XPAR_GPIO_0_DEVICE_ID);
	XGpio_Initialize(&axiGpio1, XPAR_GPIO_1_DEVICE_ID);

	// 设置AXI GPIO的方向,对应位为0表示输出,为1表示输入
	XGpio_SetDataDirection(&axiGpio0, AXIGPIO_CHANNEL_1, 0x0); // 设置axiGpio0的通道1为全输出
	XGpio_SetDataDirection(&axiGpio1, AXIGPIO_CHANNEL_2, 0xFFFF0000); // 设置axiGpio1的通道2高16位输入,低16位输出

	u32 axiGpio1_ch2_data = 0;
	while(1)
	{
		sleep(1);
		XGpio_DiscreteWrite(&axiGpio0, AXIGPIO_CHANNEL_1, 0x3); // 向axiGpio0的通道1的第0位和第1位写1

		axiGpio1_ch2_data = XGpio_DiscreteRead(&axiGpio1, AXIGPIO_CHANNEL_2); // 读取axiGpio1的通道2的值,输出引脚也可读
		sleep(1);
	}

	return 0;
}

3.2 使用AXI GPIO中断

步骤:初始化AXI GPIO -> 打开系统的中断处理功能 -> 初始化中断控制器 -> 设置中断优先级与类型,关联中断处理函数 -> 使能中断

#include "xgpio.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "sleep.h"


#define AXIGPIO_CHANNEL_1    1U
#define AXIGPIO_CHANNEL_2    2U

#define AXIGPIO_IRQ_TYPE_HIGH   1U
#define AXIGPIO_IRQ_TYPE_PEDGE  3U

#define AXIGPIO_IRQ_PRIORITY  128U


XGpio axiGpio0;
XScuGic scuGic;

void axiGpio0_Handler(void *CallbackRef);

int axiGpio0_intrFlag = 0;


int main(void)
{
	// 初始化AXI GPIO
	XGpio_Initialize(&axiGpio0, XPAR_GPIO_0_DEVICE_ID);

	// 打开系统的中断处理功能
	Xil_ExceptionInit(); // 初始化异常句柄,只在很早版本的bsp中需要,此处为了兼容性保留
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, &scuGic);
	Xil_ExceptionEnable(); // 使能系统中断

	// 初始化中断控制器
	XScuGic_Config *scuGicConfig;
	scuGicConfig = XScuGic_LookupConfig(XPAR_XSCUTIMER_0_DEVICE_ID); // 根据器件ID查找配置
	XScuGic_CfgInitialize(&scuGic, scuGicConfig, scuGicConfig->CpuBaseAddress);

	// 设置对应ID中断的的优先级与触发类型
	XScuGic_SetPriorityTriggerType(&scuGic, XPAR_FABRIC_GPIO_0_VEC_ID, AXIGPIO_IRQ_PRIORITY, AXIGPIO_IRQ_TYPE_HIGH);
	// 连接中断ID与中断服务函数
	XScuGic_Connect(&scuGic, XPAR_FABRIC_GPIO_0_VEC_ID, (Xil_InterruptHandler)axiGpio0_Handler, &axiGpio0);
	// 启用对应中断ID的中断源
	XScuGic_Enable(&scuGic, XPAR_FABRIC_GPIO_0_VEC_ID);

	// 启动AXI GPIO中断
	XGpio_InterruptGlobalEnable(&axiGpio0);
	// 使能对应通道的中断
	XGpio_InterruptEnable(&axiGpio0, AXIGPIO_CHANNEL_1);

	while(1)
	{
		sleep(1);

		if (axiGpio0_intrFlag)
		{
			xil_printf("This is axiGpio0 interrupt!");

			axiGpio0_intrFlag = 0; // 复原中断标志
			XGpio_InterruptEnable(&axiGpio0, AXIGPIO_CHANNEL_1); // 重新使能中断
		}

		sleep(1);
	}

	return 0;
}


void axiGpio0_Handler(void *CallbackRef)
{
	XGpio *axiGpioPtr = (XGpio *)CallbackRef;

	axiGpio0_intrFlag = 1;

	// 关闭中断
	XGpio_InterruptDisable(axiGpioPtr, AXIGPIO_CHANNEL_1);

	// 清除中断寄存器,不清除无法再次进入中断
	XGpio_InterruptClear(axiGpioPtr, AXIGPIO_CHANNEL_1);
}


徐晓康的博客持续分享高质量硬件、FPGA与嵌入式知识,软件,工具等内容,欢迎大家关注。

  • 29
    点赞
  • 173
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
hibernate-jpa-2.1-api 1.0.2是一个Java持久化规范的实现库。它是基于JPA(Java Persistence API)2.1规范的Hibernate实现。Hibernate是一个流行的ORM(对象关系映射)框架,用于在Java应用程序和关系数据库之间进行数据持久化。 该版本的hibernate-jpa-2.1-api是对JPA 2.1规范的实现,并且是Hibernate团队为了确保应用程序与Java EE 7兼容性而发布的一个版本。 JPA是一种使用对象模型操作数据库的标准规范,它提供了一组API,使开发人员可以使用面向对象的方式访问和操作数据库。Hibernate作为一个JPA的实现,提供了许多附加的功能和特性,使得开发人员可以更加简化和灵活地进行数据库操作。 通过使用hibernate-jpa-2.1-api,开发人员可以使用JPA的标准API,以及Hibernate提供的独有特性,来实现应用程序的数据持久化需求。它提供了实体管理器,用于管理实体对象的生命周期,以及CRUD操作。此外,它还提供了用于查询和各种持久化注解的支持。 通常情况下,使用hibernate-jpa-2.1-api需要将其添加到项目的依赖中,并与其他必需的Hibernate库一起使用。开发人员需要熟悉JPA的基本概念和API,并且理解Hibernate特有的扩展和配置选项。 总的来说,hibernate-jpa-2.1-api 1.0.2提供了开发人员在使用JPA进行数据持久化时的基本工具和功能。它是Hibernate团队为了支持JPA 2.1规范而发布的一个版本,开发人员可以使用它来简化和灵活地操作数据库。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值