Zynq的IO包括对外连接的GPIO和内部PS与PL通信的AXIO。其中对外的GPIO又分为两种:MIO和EMIO。MIO直连到PS;EMIO则是PS扩展到PL,从PL接出的IO。所以MIO不需要管脚约束,而EMIO需要管脚约束。
1.MIO寄存器
上图为MIO内部构造,对MIO操作即是对以下寄存器进行配置:
DATA_RO: 此寄存器使软件能观察 PIN 脚情况,当 GPIO 被配置成输出的时候,这个寄存器的值会反应输出的 PIN 脚情况。
DATA:此寄存器控制输出到GPIO 的值,读这个寄存器的值可以读到最后一次写入该寄
存器的值。
MASK_DATA_LSW:位操作寄存器,写入 GPIO 低 16bit 其他没有改变的位置保存原先的状态
MASK_DATA_MSW:位操作寄存器,写入 GPIO 高 16bit 其他没有改变的位置保存原先的状态(按笔者的理解应该是偏移量操作,通过bank的基地址+偏移量操作,寻找到相应的MIO,最后向DATA寄存器赋值,程序编写中暂时也用不上,可以先不管)。
DIRM:方向控制,此寄存器控制输入输出的开关,当 DIRM[x]==0 时候,禁止输出
OEN: 输出使能,当 OEN[x]==0 的时候输出关闭,PIN 脚处于三态
因此,如果要读 IO 状态就得读 DATA_RO 的值,如果是对某一位进行操作就是写
MASK_DATA_LSW/MASK_DATA_MSW。
2.EMIO寄存器
与 MIO 大部分类似但是需要注意以下几点:
• EMIO 在 PL 部分,输入与 OEN 寄存器无关,当 DIRM 设置为 0 的时候设置为输入,可以读 DATA_RO寄存器获取数据。
•输出不能设置成三态,当 DIRM 设置为 1 的时候为输出,写入 DATA 寄存器或者
MASK_DATA_LSW/MASK_DATA_MSW寄存器
• EMIOGPIOTN[x]=DIRM[x] & OEN[x],实现输出的控制。
3.硬件搭建:
基于vivado搭建下图所示IP。
此次通过PS控制zturn 7z020的开发板上的两个用户灯的亮灭,因此只需用到DDR和MIO,所以只需要配置好DDR以及相应的MIO(MIO0和MIO9使能)。
4.PS程序解读
实例程序导读:
#include "xgpiops.h"//控制GPIO的头文件
#include "sleep.h"
int main()
{
staticXGpioPs psGpioInstancePtr;
XGpioPs_Config*GpioConfigPtr;
intiPinNumber= 0; //第一个user_Led连接的是MIO0
intiPinNumber1 = 9;//第二个user_Led连接的是MIO9
u32uPinDirection = 0x1; //1表示输出,0表示输入
intxStatus;
//--MIO的初始化
GpioConfigPtr= XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
if(GpioConfigPtr== NULL)
returnXST_FAILURE;
xStatus= XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr,GpioConfigPtr->BaseAddr);
if(XST_SUCCESS!= xStatus)
print("PS GPIO INIT FAILED \n\r");
//--MIO的输入输出操作
XGpioPs_SetDirectionPin(&psGpioInstancePtr,iPinNumber,uPinDirection);//配置MIO0输出方向
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr,iPinNumber,1);//配置MIO0的第1位输出
XGpioPs_SetDirectionPin(&psGpioInstancePtr,iPinNumber1,uPinDirection);//配置MIO9输出方向
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr,iPinNumber1,1);//配置MIO9的第1位输出
while(1)
{
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber, 1);//点亮MIO的第1位输出1
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber1, 1);//点亮MIO的第1位输出1
usleep(500000);//延时
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber, 0);//熄灭MIO的第9位输出0
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber1, 0);//点亮MIO的第9位输出0
usleep(500000);//延时
}
return 0;
}
从以上程序看出,整个过程如下:MIO初始化(基本上不用修改程序),MIO输入输出配置(包括配置哪个mio的方向寄存器和输出使能寄存器),最后就是向该MIO写入数据了。