GPIO的结构体系
zynq的GPIO,分为两种,MIO(multiuse I/O)和EMIO(extendable multiuse I/O)。
ZYNQ的GPIO由4个BANK组成,其体系结构如图1所示。其中Bank0有32个GPIO引脚,Bank1有22个引脚,共54个GPIO引脚直接通过MIO连接到PS上,每个引脚可以通过寄存器的设置来确定该引脚为输入、输出或者中断,因为54个MIO引脚直接连接在PS上,像其他普通ARM一样,不需要通过XPS进行硬件配置,直接通过SDK编程即可。
Bank2和Bank3通过EMIO接口将CPU的GPIO连接到PL部分的引脚上,其中每个Bank各有32个引脚,通过EMIO扩展的GPIO连接到PL上,可以在PL部分进行逻辑设计,进行特定功能的IP核制定。然后在PS部分,像控制普通MIO一样进行编程。因此,使用EMIO引脚必须通过XPS进行硬件配置,然后在PS部分使用SDK进行编程控制。
图1 GPIO的组成
GPIO的内部结构和内部数据流及寄存器结构如图2所示。上半部分为GPIO中断相关的寄存器,下半部分为GPIO查询方式读写的寄存器。
图2 GPIO寄存器数据流组成
DATA_RO寄存器是读取GPIO引脚值寄存器,不论该GPIO引脚配置为输入还是输出,都能正确读取该GPIO引脚值。如果该引脚的功能没有配置成GPIO功能,读取的值为随机值,因为该寄存器只能读取GPIO引脚值。
DATA寄存器的值是要输出到GPIO引脚上的数值,当读取该寄存器的数值时,结果是前一次写入DATA寄存器里的数值,而不是当前GPIO引脚的数值。
MASK_DATA_LSW和MASK_DATA_MSW寄存器是传统的数据寄存器(DATA)和屏蔽寄存器(MASK)的结合,该寄存器32位,分成高16位和低16位,其中高16位作为传统的MASK使用,低16位作为传统的DATA使用。因此,MASK_DATA_LSW是对GPIO的16位引脚进行设置和屏蔽寄存器。当某位在MASK_DATA_LSW高16位屏蔽时,即使修改MASK_DATA_LSW低16位的数据,也不影响该位GPIO值。
DIRM寄存器是方向控制寄存器,控制GPIO的输入或者输出,该寄存器值不影响输入,即GPIO输入功能始终有效。
OEN寄存器是输出时能寄存器,当GPIO引脚被配置成输出引脚时,该寄存器控制该引脚是否输出;当GPIO引脚被配置成输出禁止时,该引脚为三态;当OEN[x] = 0时,输出无效。
GPIO使用实例
ZYNQ核的添加及配置
Step1:新建一个名为为Miz701_sys的工程
Step2:选择RTL Project 勾选Do not specify source at this time
Step3:选择芯片型号xc7z010clg400-1
Step4:单击Finish
使用IP Integrator创建硬件系统
Step1:单击Create Block Design
Step2:输入system
Step3:添加IP按钮
Step4:搜素单词z选择ZYNQ7 Processing System,然后双击
Step5:添加进来了ZYNQ CPU IP,双击ZYNQ CPU IP。
Step6: 修改时钟输入为50MHZ,可以看到ARM时钟为650MHZ DDR为525MHZ(1050MHZ),并且修改FCLK_CLK0 为100MHZ
step7:修改内存型号为MT41K256M16RE-125 M,单击OK。
Setp8:选择MIO Configuration选项卡,再看到I/O Peripherals 中的GPIO一栏,勾选上其中的EMIO一栏,并选择4位引脚输出(最多可以选择64位,但是这个使用只需要4位足够了)。
Setp9:按照上图设置好了之后,点击OK,仔细观察发现的zynq核心多出一组引脚名为GPIO_0,这个正是我们刚刚设置的一组EMIO,我们右击该引脚,选择make external把GPIO_0引脚引出(或者单击该引脚处,按快捷键Ctrl +t,也可以将引脚引出)。效果如下图所示:
step10::单击Run Block Automation 进行自动连线,VIVADO软件会根据信号的命名规则智能连线。
Step11:在你点击了OK后,你会发现DDR以及FICED_IO自动的延伸出来,然后把时钟FCLK_CLK0和M_AXI_GPI0_ACLK连接,其实就是给M_AXI_GP0_ACLK提供一个时钟。方法:当把鼠标靠近的时候会自动连接。
产生HDL和约束文件
Setp1:接下来依然是,右键单击Block文件,文件选择Generate the Output Products,是文件得到一定的约束。
Setp2:弹出如下对话框,直接点击Generate
Setp3:继续右键单击Block文件,选择Create a HDL wrapper,根据Block文件内容产生一个HDL 的顶层文件:
Setp4:并选择让vivado自动完成
Setp5:这里我们看到,Vivado给我创建了这样的顶层文件,其中的gpio_0_tri_io就是我们配置的EMIO
EMIO的管脚约束修改
我们发现,之前引出的EMIO叫做GPIO_0,到了顶层他的名字gpio_0_tri_io,而不是GPIO_0。所以分配引脚的时候就要注意了名字别错了,创建一个约束文件,分配引脚如下:
产生bit文件
此时可以,开始生成bit文件了:
导出bit文件
编译成功之后,依然是导出硬件:
加载到SDK
通过4个GPIO口输出高低电平到引出的引脚上。
配置GPIO的步骤如下:
通过GPIO的外设ID找到对应的外设信息;
填充GPIO外设寄存器基地址和一些相关信息;
配置GPIO口的方向为输出方向;
配置GPIO口的输出使能;
设置GPIO口输出高低电平;
打开SDK,然后新建一个工程,以及添加一个main.C文件。
添加程序如下:
文章转载自:FPGA技术联盟