Vivado中的IP核——GPIO详解

  • Post author:
  • Post category:其他



资料ID:PG144

文档查找软件:DocNav,在安装vivado时可以选择一并安装


Vivado中的GPIO模块框图如下。

在这里插入图片描述

下表展示了AXI GPIO的寄存器和相对于基地址的地址偏移值。

在这里插入图片描述

这些寄存器是否可用取决于一些配置参数的值。若某个寄存器是不可用的,一个写信号对该寄存器没有效果;当尝试读取该寄存器的值时,将会得到全零值。决定寄存器是否可用的参数如下表。

在这里插入图片描述

如上表所示,当Enable Interrupt参数为0时,与中断相关的三个寄存器GIER、IP IER、IP ISR是不可使用的,而对其余寄存器是没有影响的。同理,当使能双通道(Enable Dual Channel)这个参数为0时,通道2的数据寄存器和三态寄存器是不可用的。



Register Space

由于通道1和通道2的数据寄存器与三态寄存器是相同的,所以这里仅介绍五个寄存器。GPIOx_DATA表示通道x的数据寄存器。



GPIOx_DATA

GPIO数据寄存器的作用有两个,当GPIO被配置为输入端口时,用于读取输入值;当GPIO被配置为输出端口时,将要输出的值写入该寄存器。此外,当GPIO被配置为输入端口时,向该寄存器写数据是无效的。

GPIO数据寄存器的描述如下表。

在这里插入图片描述



GPIOx_TRI

GPIO 3态控制寄存器可以动态地配置端口为输入或者输出。当某一个比特位被配置为1,则相应的端口就会被配置为输入端口;当某一比特位被配置为0,则相应的端口被设置为输出端口。

GPIO 3态控制寄存器的描述如下。

在这里插入图片描述



Interrupts

在介绍与中断相关的寄存器之前,先介绍一下GPIO的中断。

在中断使能的情况下,任何输入通道的转换都会产生一个电平中断。GPIO接口模块中包含了中断检测逻辑,该逻辑可以识别任何输入通道的转换。当一个转换被检测到,它将被告知给中断控制模块。

为了支持通道的中断能力,中断控制模块中实现了以下的寄存器。

全局中断使能寄存器(GIER)-使能或不使能中断输出,这些中断输出到processor或者interrupt controller。

IP中断使能寄存器(IPIER)-为每一个通道配置独立的中断使能位。

IP中断状态寄存器(IPISR)-为每一个通道配置独立的中断状态位。为了测试,IP ISR也可以手动设置产生一个中断。



GIER

该寄存器有效位只有一位,即第31位。具体的寄存器描述如下。

在这里插入图片描述

如果想要产生中断,必须要设置两个使能,第一个就是上述寄存器,即Master enable;第二个就是IPIER。



IPIER

IPIER中有效位也只有两位,具体的寄存器描述如下。

在这里插入图片描述



IPISR

与IPIER类似,该寄存器中的有效位也是两个,具体描述如下。

在这里插入图片描述



示例程序:GPIO做为输出控制LED,GPIO2做为输入产生中断

在利用Vivado搭建硬件平台的时候已经对GPIO进行了相关设置,程序里首先验证这些设置是否会对相关寄存器进行初始化,如是否会将GPIO2所对应的4个端口全部设置为输入。实验结果表明,寄存器必须由软件初始化。

#include "xil_printf.h"
#include "sleep.h"

#define GPIOBaADDr 0x40000000
#define DATA1OffSet 0x0
#define TRI1OffSet 0x4
#define DATA2OffSet 0x8
#define TRI2OffSet 0xC
#define GIEROffSet 0x11C
#define IPIEROffSet 0x128
#define IPISROffSet 0x120
#define GETX(x) (*(volatile int *)(GPIOBaADDr + x))

int main()
{
	/***************initialize GPIO*******************/
	if((GETX(TRI1OffSet) & 0xf) == 0x0)
	{
		print("GPIO1 already set to output by hardware platform\r\n");
	}
	else
	{
		print("GPIO1 will set to output by software\r\n");
		GETX(TRI1OffSet) &= 0x0;
	}

	if((GETX(TRI2OffSet) & 0xf) == 0xf)
	{
		print("GPIO2 already set to input by hardware platform\r\n");
	}
	else
	{
		print("GPIO2 will set to input by software\r\n");
		GETX(TRI2OffSet) |= 0xf;
	}

	if((GETX(GIEROffSet) & 0x80000000) == 0x80000000)
	{
		print("Global Interrupt Enable by hardware platform\r\n");
	}
	else
	{
		print("Global Interrupt Enable by software\r\n");
		GETX(GIEROffSet) |= 0x80000000;
	}

	if((GETX(IPIEROffSet) & 0x2) == 0x2)
	{
		print("channel2 interrupt enable by hardware platform\r\n");
	}
	else
	{
		print("channel2 interrupt enable by software\r\n");
		GETX(IPIEROffSet) |= 0x2;
	}
	/*************************************************/

	/******************GPIO control led***************/
	//The four LEDs are lit in turn every one second
	for(int i = 0; i < 100; i++)
	{
		GETX(DATA1OffSet) |= (0x1 << (i % 4));
		sleep(1);
		GETX(DATA1OffSet) &= 0x0;
	}
	/*************************************************/

	/**************GPIO2 generate interrupt***********/
	while(1)
	{
		if((GETX(IPISROffSet) & 0x2) == 0x2)
		{
			print("GPIO2 Generate interrupt\r\n");
			GETX(IPISROffSet) |= 0x2;//clear interrupt by TOW
		}
	}
	/************** **********************************/
}



版权声明:本文为qq_37816919原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。