ZYNQ:MIO、EMIO、IO的区别和灵活使用
ZYNQ:MIO、EMIO、IO的区别和灵活使用
在使用ZYNQ上ARM -A9平台时首先面临的就是对IO进行操作,总的来说对IO操作无怪乎两种方式,一种是直接对GPIO寄存器进行操作,这样程序效率高,但编写代码困难;另一种是调用SDK工具提供的API接口函数。
在实际使用时ZYNQ又把GPIO分成MIO、EMIO和PL端的IO这三种类型,在刚刚接触时会因为这三种IO的不同配置和使用方式而影响后续的学习,这里针对三种IO进行详细的说明使用方法。
首先要明白这三种IO的物理属性,简单的说1、MIO只属于PS端,PL端无法进行操作。
2、EMIO从物理属性来说属于PL端IO,但PS端可以通过软件映射连线来对EMIO进行操作,且使用效果与MIO一致。3、PL端所有IO都属于常规的FPGA的IO口,可进行输入输出操作,但是如果PS端不对EMIO控制时,LP端可以随意的使用EMIO。
1、PS配置MIO进行输出
系列芯片由54个MIO,隶属于PS部分,使用时不需要添加引脚约束,对PL部分是不可见的。在使用PS端MIO时需要对GPIO进行配置,这个配置过程与普通的ARM芯片过程一致。首先需要对MIO的基本特性进行配置,在对GPIO配置时需要调用API函数,这里需要了解下面几个函数
1、 *(u16 );
这个函数是根据唯一的设备ID号来查找设备配置。这个函数返回一个配置表入口。实际上就是根据设备ID返回结构体的配置。
2、s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, XGpioPs_Config *ConfigPtr, u32 EffectiveAddr);
这个函数用于初始化GPIO,主要完成对结构体的配置。函数总是返回配置成功。
3、 void XGpioPs_SetDirectionPin(XGpioPs *InstancePtr, u32 Pin, u32 Direction);
这个函数为指定的引脚配置输入输出方向。实际上是对方向寄存器(寄存器)进行使能。设置为0时禁止输出驱动使能,也就是输入有效,设置为1时使能输出驱动。
4、void XGpioPs_SetOutputEnablePin(XGpioPs *InstancePtr, u32 Pin, u32 OpEnable);
这个函数设置指定引脚输出使能。这个是对寄存器进行配置。与属于逻辑与的关系,只有两个都配置成功才能实现MIO的输入或者输出的配置。
5、u32 XGpioPs_ReadPin(XGpioPs *InstancePtr, u32 Pin);
这个函数是从指定引脚读出数据。返回值是从寄存去内取出读到的数据。
6、void XGpioPs_WritePin(XGpioPs *InstancePtr, u32 Pin, u32 Data);
这个函数是对指定引脚写入数据。这个函数是对DATA寄存器、寄存器、寄存器进行配置,共同完成输出数据的写入。
在了解了上述函数后,对PS端的GPIO操作就相对简单了。配置流程就是
1、根据设备ID找到基地址和设备编号,也就是完成的配置。
2、对找到的设备进行配置,这个可直接调用函数进行完成。
3、设置IO的输入输出方向。
4、使能对应IO的输入输出。
5、对IO进行读或者写操作。
根据上面是配置流程代码如下:
# “.h”
# “sleep.h”
int main()
{
;
* ;
int = 7; //LD9连接的是MIO7
u32 = 0x1; //1表示输出,0表示输入
int ;
//--MIO的初始化
GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
if(GpioConfigPtr == NULL)return XST_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);//配置MIO输出方向XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);//配置MIO的第7位输出while(1){XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 1);//点亮MIO的第7位输出1sleep(1); //延时XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 0);//熄灭MIO的第7位输出0sleep(1); //延时}
return 0;
}
2、 PS配置EMIO进行输出
在使用EMIO时需要在Z7的IP核配置时选择EMIO。如下图,这里选择了2个EMIO端口。
其次又要EMIO硬件上属于PL端,需要在PL端对GPIO进行约束,通俗的讲就是把这个GPIO硬件端口链接到PS上。管脚约束文件如下图
在完成了上述配置后,在SDK上对这些EMIO进行配置时就和MIO一样。
3、PS配置PL端普通IO进行输出
这个方式对PL端普通IO进行操作是比较麻烦的,并且也消耗AXI总线资源。
AXI接口如下表描述:
在使用PS对PL端IO操作时,相当于GPIO的IP核,是通过AXI总线挂在PS上的GPIO上。因此系统整体连线图如下图所示:(这个图包含了MIO、EMIO和)
这部分由于使用了AXI总线,设备的ID和地址都是确定的,因此不需要对GPIO的设备ID和基地址进行配置,只需要对PL端GPIO进行初始化即可。
= (&, CE_ID);
if (NULL!=)
print (“ ok \n\r”) ;
on(&,1,1);
on(&,2,0);
然后对这个IO进行读写操作,这里需要主要的是输入数据为32位,需要把输入的数据和GPIO数量要进行对应。
(&,2,);
(&,2,);
总结
这三种GPIO的配置有相同的地方和不同的地方,不同的地方主要是由GPIO所归属的物理位置不同导致,由于物理位置不同进行额外配置在PL端。而在PS端其实需要修改的很少。因此在SDK上进行IO操作是相对灵活且简单的。