Xilinx ZYNQ 7000+Vivado2015.2系列(四)之GPIO的三种方式:MIO、EMIO、AXI_GPIO

2024-07-06

前言:

ZYNQ 7000有三种GPIO:MIO,EMIO,AXI_GPIO

MIO是固定管脚的,属于PS,使用时不消耗PL资源;

EMIO通过PL扩展,使用时需要分配管脚,使用时消耗PL管脚资源;

AXI_GPIO是封装好的IP核,PS通过M_AXI_GPIO接口控制PL部分实现IO,使用时消耗管脚资源和逻辑资源。

使用的板子是zc702。

1.MIO方式

Zynq7000 系列芯片有 54 个 MIO(multiuse I/O), 它们分配在 GPIO 的 Bank0 和Bank1 隶属于 PS 部分。

这些 IO 与 PS 直接相连。 不需要添加引脚约束。

MIO 信号对 PL部分是透明的, 不可见。 所以对 MIO 的操作可以看作是纯 PS 的操作。

新建Vivado工程,添加ZYNQ CPU核,双击,配置好时钟和内存类型,确认勾选MIO:

如系列(三)文章所述,生成bit stream,然后Launch SDK。

在SDK中新建工程,源文件如下:

#include "xgpiops.h"

#include "sleep.h"

int main(){

static XGpioPs psGpioInstancePtr;

XGpioPs_Config* GpioConfigPtr;

int iPinNumber= 8;

u32 uPinDirection = 0x1;

int xStatus;

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");

XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumber,uPinDirection);

XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);

while(1){

XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 1);

usleep(500000);

XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 0);

usleep(500000);

}

return 0;

}

下载到板子上,DS12就开始闪烁了。

2.EMIO方式

EMIO 分配在 bank2 和 bank3 和 PL部分相连。EMIO 有 64 个引脚可供我们使用 。

当 MIO 不够用时, PS 可以通过驱动 EMIO 控制 PL 部分的引脚 。

Vivado工程里ZYNQ CPU核配置,确保EMIO勾选,这里我设置了位宽为4,后面为其分配了四个管脚:

在Diagram里面将GPIO_0的引脚引出来,生成顶层文件后查看这个引脚的名字,因为我修改了名字,这里叫emio_0_tri_io

管脚约束文件:

#GPIO PMOD1

set_property PACKAGE_PIN E15 [get_ports {emio_0_tri_io[0]}]

set_property IOSTANDARD LVCMOS25 [get_ports {emio_0_tri_io[0]}]

set_property PACKAGE_PIN D15 [get_ports {emio_0_tri_io[1]}]

set_property IOSTANDARD LVCMOS25 [get_ports {emio_0_tri_io[1]}]

set_property PACKAGE_PIN W17 [get_ports {emio_0_tri_io[2]}]

set_property IOSTANDARD LVCMOS25 [get_ports {emio_0_tri_io[2]}]

set_property PACKAGE_PIN W5 [get_ports {emio_0_tri_io[3]}]

set_property IOSTANDARD LVCMOS25 [get_ports {emio_0_tri_io[3]}]

SDK部分:MIO号是0~53,EMIO从54开始

#include "xgpiops.h"

#include "sleep.h"

int main()

{

static XGpioPs psGpioInstancePtr;

XGpioPs_Config* GpioConfigPtr;

int xStatus;

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");

XGpioPs_SetDirectionPin(&psGpioInstancePtr, 54,1);

XGpioPs_SetDirectionPin(&psGpioInstancePtr, 55,1);

XGpioPs_SetDirectionPin(&psGpioInstancePtr, 56,1);

XGpioPs_SetDirectionPin(&psGpioInstancePtr, 57,1);

XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 54,1);

XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 55,1);

XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 56,1);

XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 57,1);

while(1)

{

XGpioPs_WritePin(&psGpioInstancePtr, 54, 1);

usleep(200000);

XGpioPs_WritePin(&psGpioInstancePtr, 54, 0);

usleep(200000);

XGpioPs_WritePin(&psGpioInstancePtr, 55, 1);

usleep(200000);

XGpioPs_WritePin(&psGpioInstancePtr, 55, 0);

usleep(200000);

XGpioPs_WritePin(&psGpioInstancePtr, 56, 1);

usleep(200000);

XGpioPs_WritePin(&psGpioInstancePtr, 56, 0);

usleep(200000);

XGpioPs_WritePin(&psGpioInstancePtr, 57, 1);

usleep(200000);

XGpioPs_WritePin(&psGpioInstancePtr, 57, 0);

usleep(200000);

}

return 0;

}

下载到板子里,PMOD1的4个led灯交替闪烁。

3.AXI_GPIO方式

VIvado工程里,ZYNQ CPU核配置:

勾选M_AXI_GPIO 接口:

勾选复位信号:

给PL的时钟信号:

加入AXI_GPIO IP,这里设置位宽为4,后面将控制4个led灯:

自动连接后如下图:

管脚约束如下:

#GPIO PMOD1

set_property PACKAGE_PIN E15 [get_ports {gpio_sw_tri_o[0]}]

set_property IOSTANDARD LVCMOS25 [get_ports {gpio_sw_tri_o[0]}]

set_property PACKAGE_PIN D15 [get_ports {gpio_sw_tri_o[1]}]

set_property IOSTANDARD LVCMOS25 [get_ports {gpio_sw_tri_o[1]}]

set_property PACKAGE_PIN W17 [get_ports {gpio_sw_tri_o[2]}]

set_property IOSTANDARD LVCMOS25 [get_ports {gpio_sw_tri_o[2]}]

set_property PACKAGE_PIN W5 [get_ports {gpio_sw_tri_o[3]}]

set_property IOSTANDARD LVCMOS25 [get_ports {gpio_sw_tri_o[3]}]

SDk部分如下:

#include

#include "platform.h"

#include "xparameters.h"

#include "xgpio.h"

int main() {

XGpio gpio_led;

int status;

int i,x,y;

init_platform();

status = XGpio_Initialize(&gpio_led, 0);

if(status == 0){

printf("success \r\n");

}

XGpio_SetDataDirection(&gpio_led,1,0);

while (1){

for (i = 0; i<=3; i++){

XGpio_DiscreteWrite(&gpio_led, 1, 0x01<

for(x =1000; x > 0; x-- ){

for (y = 100000; y > 0; y--);

}

}

}

cleanup_platform();

return 0;

}

可以看到,与EMIO一样需要分配管脚,

但是AXI_GPIO使用的头文件是#include "xgpio.h",

而EMIO是#include "xgpiops.h"。

下载完成后,PMOD1 的四个LED灯依次闪烁。

总结:

MIO和EMIO使用PS的GPIO,,MIO固定管脚,EMIO手动分配管脚;IP方式手动分配管脚,综合后需要消耗PL的逻辑资源。