实验前请确保开发板的BOOT处于JTAG模式

实验目的

本实验将通过Vitis Unified Ide进行点灯。同时将展示三种GPIO控制方法:MIOEMIOAXI_GPIO

前置知识

ZYNQ SoC 的 PS(Processing System)和 PL(Programmable Logic)

PS即处理器系统(ARM),PL即可编程逻辑(FPGA)

GPIO(General Purpose I/O),通用输入输出,是 ZYNQ 的外设之一。GPIO包括 MIO 与 EMIO,是 ZYNQ 上最常用的硬件资源。MIO 分配在 GPIO 的 Bank0 和Bank1,属于 ZYNQ 的 PS 部分, 而 EMIO 也是 PS 上 GPIO 的一部分,但连接到了PL, 分配在 GPIO 的 Bank2 和 Bank3。MIO 在芯片外部有 54 个引脚,这些引脚可以用于 GPIO、SPI、UART、USB 等功能上,每个引脚都同时具有多种功能。因为MIO 是 PS 部分的引脚且其操作对于 PL 端不可见,所以对 MIO 的操作可以视为纯 PS 端的操作。EMIO 有 64 个引脚, EMIO 与 MIO 的不同在于,EMIO 连接到了PL,再从 PL 输出信号,而 MIO 直接从 PS 端输出。

**MIO: ** PS –> GPIO(PS)

**EMIO: **PS –> PL –> GPIO(PL)

**AXI_GPIO: **PS -(AXI)-> PL –> GPIO(PL)

上面是三种控制方法的简单流图

实验步骤

新建项目

先建立Vivado项目,用于后续生成硬件描述文件(.xsa)

Create Block Design 并添加ZYNQ ip

image-20251115120029674

接下来需要配置DDR(双击ZYNQ ip打开配置界面)。对于小梅哥的BX71配置如下。野火的将DRAM位宽改为332bit即可。

image-20251115121024119

点击OK关闭设置弹窗后点击Run Block Automation进行DDR的自动连接。在未进行AXI_GPIO实验时,我们需要先将FCLK_CLK0M_AXI_GP0_ACLK连接起来

image-20251115121505881

接下来重新双击ZYNQ ip进行GPIO配置

对于小梅哥开发板上的LED_IO

Signial Name. Pin NO.
PS_LED0 PS_MIO0
FPGA_LED0 T10

其它开发板自行查询手册

配置

配置如下

image-20251115122002700

右键GPIO_0引出端口

image-20251115122204446image-20251115122303819image-20251115122355091

image-20251115122441546

绑定引脚

image-20251115122755758

生成bit流

image-20251115122823711

image-20251115123100591

image-20251115123131876

接下来我们在项目文件夹内新建一个文件夹用来存放vitis工程

image-20251115123207847

打开vitis,选择Set Workspace,选择刚刚新建的文件夹

image-20251115123251720

接下来我们新建一个Platform Component

image-20251115123354617

此处选择在vivado项目根目录下的.xsa文件

image-20251115123411849

再建立Application Component

此处选择刚刚新建的platform

image-20251115123604989

右键src新建C语言代码文件

image-20251115123719657

image-20251115123750734

image-20251115123810302

导入#include "xparameters.h" xgpiops.h

ctrl+左键进入xgpiops.h

image-20251115131648909

圈出部分就是ZYNQ7020对应的MIO/EMIO

"xparameters.h"中GPIO的BASEADDR

image-20251115131048687

代码部分

代码如下。可以观察到两个LED循环闪烁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "xparameters.h"
#include "xgpiops.h"
#include <xstatus.h>
#include "sleep.h"

#define LED_PS 0
#define LED_PL 54// 86+0
int main(){
XGpioPs_Config *gpio_mio_cfg = XGpioPs_LookupConfig(XPAR_GPIO0_BASEADDR);
XGpioPs GPIO_IO;
if(XGpioPs_CfgInitialize(&GPIO_IO, gpio_mio_cfg, gpio_mio_cfg->BaseAddr) != XST_SUCCESS){
return XST_FAILURE;
}

XGpioPs_SetDirectionPin(&GPIO_IO, LED_PS, 1);
XGpioPs_SetDirectionPin(&GPIO_IO, LED_PL, 1);

XGpioPs_SetOutputEnablePin(&GPIO_IO, LED_PS, 1);
XGpioPs_SetOutputEnablePin(&GPIO_IO, LED_PL, 1);

while (1) {
XGpioPs_WritePin(&GPIO_IO, LED_PL, 0x0);
sleep(1);
XGpioPs_WritePin(&GPIO_IO, LED_PL, 0x1);
sleep(1);
XGpioPs_WritePin(&GPIO_IO, LED_PS, 0x0);
sleep(1);
XGpioPs_WritePin(&GPIO_IO, LED_PS, 0x1);
sleep(1);
}
return 0;
}