MiZ702学习笔记5——EMIO 使用详解
0赞
上次讲到MIO的使用,初步熟悉了EDK的使用,这次就来说说EMIO的使用。如你所见zynq的GPIO,分为两种,MIO(multiuse I/O)和EMIO(extendable multiuse I/O)
MIO分配在bank0和bank1直接与PS部分相连,EMIO分配在bank2和bank3直接和PL部分相连。除了bank1是22-bit之外,其他的bank都是32-bit。所以MIO有53个引脚可供我们使用,而EMIO有64个引脚可供我们使用。
使用EMIO的好处就,当MIO不够用时,PS可以通过驱动EMIO控制PL部分的引脚,接下来就来详细介绍下EMIO的使用。
EMIO的使用和MIO的使用其实是非常相似的。区别在于,EMIO的使用相当于,是一个PS + PL的结合使用的例子。所以,EMIO需要分配引脚,以及编译综合生成bit文件。
我们从添加ZYNQ的IP开始讲,这次添加一个配置更加简洁的ZYNQ IP:
添加了zynq IP之后,点击Run Block Automation,将DDR等引脚引出:
还是双击点击进入从新配置,选择Default:
再将EMIO引出8个引脚(最多能引出64个),引出的引脚都是按bank2到bank3顺序排列的,也就是说53个MIO之后,我们引出的这8个EMIO,分别是54~61号引脚,之后会在程序中体现。
PL的输出时钟,也勾选掉不要:
我们,没有用到AXI总线,这个也勾选掉不要:
OK,完成ZYNQ核的配置.
右击GPIO_0引脚部分,选择make external把GPIO_0引脚引出,
依然是,右键单击Block,文件选择Generate the output products,是文件得到一定的约束:
继续右键单击Block,文件选择Create a HDL wrapper,创建一个HDL 的顶层文件:
这里我们得去瞧瞧,Vivado到底给我创建了这样的顶层:
我们发现,之前引出的EMIO——GPIO_0,到了顶层他的名字叫gpio_0_tri_io,而不是GPIO_0。所以分配引脚的时候就要注意了名字别错了,
创建一个约束文件,分配引脚如下:
set_property PACKAGE_PIN T22 [get_ports {gpio_0_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[0]}]
set_property PACKAGE_PIN T21 [get_ports {gpio_0_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[1]}]
set_property PACKAGE_PIN U22 [get_ports {gpio_0_tri_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[2]}]
set_property PACKAGE_PIN U21 [get_ports {gpio_0_tri_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[3]}]
set_property PACKAGE_PIN V22 [get_ports {gpio_0_tri_io[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[5]}]
set_property PACKAGE_PIN W22 [get_ports {gpio_0_tri_io[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[6]}]
set_property PACKAGE_PIN U19 [get_ports {gpio_0_tri_io[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_0_tri_io[7]}]
set_property PACKAGE_PIN U14 [get_ports {gpio_0_tri_io[7]}]
可以,开始生成bit文件了:
编译成功之后,依然是导出硬件,打开SDK,然后新建一个工程,以及添加一个main.C文件,具体过程参加上一篇笔记。
添加程序如下:
#include
#include"xgpiops.h"
#include"sleep.h"
#include#include "xgpiops.h" #include "sleep.h" int main() { static XGpioPs psGpioInstancePtr; XGpioPs_Config* GpioConfigPtr; int iPinNumber= 54; //54,EMIO的第一个引脚 u32 uPinDirection = 0x1; //1表示输出,0表示输入 int xStatus; //--IO的初始化 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"); //--IO的输入输出操作 XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumber,uPinDirection);//配置MIO输出方向 XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);//配置MIO的第7位输出 //--IO的段操作 XGpioPs_SetDirection(&psGpioInstancePtr,2,0xffffffff); //bank2的EMIO全部配置成输出 XGpioPs_SetOutputEnable(&psGpioInstancePtr,2,0xffffffff); //bank2的EMIO全部使能 XGpioPs_Write(&psGpioInstancePtr,2,0x50); //对整个bank2的IO进行段操作 while(1) { XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 1);//点亮 sleep(1); //延时 XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 0);//熄灭 sleep(1); //延时 } return 0; }
我们发现,驱动EMIO和MIO基本是一模一样的,上篇笔记中的添加的"xgpio.h"其实是多此一举,上次的程序中我们只要把
static XGpio psGpioInstancePtr;
这句替换成:
static XGpioPs psGpioInstancePtr;
"xgpio.h"其实是为系统自带的以总线的方式驱动IO的GPIO核服务的。这一点也是很容易搞错的地方。(呵呵,我之前就弄错了)GPIO核的使用也非常简单,我看看是否在下篇笔记里讲讲。
调试过程,也和上次笔记基本一样(请参考上篇笔记),不同的是,在此之前得先下载bit文件,下载文件可以直接在SDK中进行:
这次我们看看,如何在线调试,点击状态栏中的小爬虫:
最后,想说明一点,SDK的调试功能。不管是在线调试还是调试,这个不是非常好用,可能存在有时可以有时又不行(zed,和MiZ702我都试过),所以一定要确保USB线的稳定,最后插到电脑主机后面的USB,或者弄一个好点的可以单独供电的USB分线器。