PS 和外部设备之间的通信主要是通过复用的输入/输出(Multiplexed Input/Output,MIO)实现的。除此之外,PS 还可以通过扩展的 MIO(Extended MIO,EMIO)来实现与外部设备的连接。
EMIO 使用了 PL 的I/O 资源,可以用来扩展PS引脚,也可以用来连接PL中实现的IP模块。
ZYNQ GPIO 接口信号被分成四组,分别是从 BANK0 到 BANK3。
其中 BANK0 和 BANK1 中共计 54个信号通过 MIO 连接到 ZYNQ 器件的引脚上,这些引脚属于 PS 端
BANK2 和 BANK3 中共计 64 个信号则通过 EMIO 连接到了 ZYNQ 器件的 PL 端
PS 端经由 EMIO 引出的接口会直接连接到 PL 端的器件引脚上,通过 IO 管脚约束来指定所连接 PL 引脚的位置。( MIO 不需要手动指定引脚约束 )
通过这种方式,EMIO 可以为 PS 端实现额外的 64 个输入引脚或 64 个带有输出使能的输出引脚。
输入引脚 和 带输出使能的输出引脚
EMIO 还有一种使用方式,就是用于连接 PL 内实现的功能模块(IP 核),此时 PL 端的 IP 作为 PS 端的一个外部设备
因为 EMIO 使用了 PL 端的 IO 资源,所以增加了 PL 部分,PL 端与按键 KEY和LED相连的引脚直接通过 EMIO 连接到 PS 端。
MIO Configuration -> GPIO -> 勾选EMIO GPIO -> 位宽 2
将 EMIO 扩展一个 2 位的 GPIO 接口信号,此信号将用于连接 PL 端的引脚
在 Diagram 窗口中可以看到 ZYNQ7 Processing System多了一个 GPIO_0 端口
点击选中该端口,然后点击鼠标右键,在弹出的列表中选择"Make External"( 引出 ),可以看到ZYNQ7 Processing System 引出了一个名为GPIO_0_0的接口
点击选中该接口,在左侧 External Interface Properties一栏中将该接口的名称修改
在 Sources 窗口中展开 Design Sources,然后右键点击 sysetm_wrapper 下的 system.bd,在弹出的菜
单中选择 Generate Output Products
Flow Navigator 导航栏中找到 RTL ANALYSIS,点击该选项中的"Open Elaborated Design"
I/O Planning:在 I/O Ports 窗口中对 PL 部分的接口进行管脚分配
如果是MIO的输入/输出接口不需要手动进行管脚分配,选择"Generate Output Products"之后,Vivado 工具会自动创建 PS 端的管
脚约束文件。
自行扩展的GPIO的接口信号,需要手动将其分配引脚,要与原理图对应。
按键SW :
LED:
引脚绑定:
File -> Export -> Export Hardware
在弹出的对话框中,勾选“Include bitstream”
如果设计使用了 PL 的资源,比如使用了 PL 的引脚,或者在 PL 内实现了部分功能模块,那么就需要生成 Bitstream 文件,并在导出硬件的时候包含该文件。
在 IMPLEMENTED DESIGN 界面可以查看设计对 PL 资源的使用情况。
在左侧 Flow Navigator 导航栏中找到 IMPLEMENTATION,点击该选项中的"Report Utilization"
导出的为硬件设计文件
File > New > Application Project,新建一个 SDK 应用工程
/**
* Create by wkk 2023.3.20
* read sw state to control led
*/
#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"
#define GPIOPS_ID XPAR_XGPIOPS_0_DEVICE_ID //PS 端 GPIO 器件 ID
#define EMIO_LED 54 //PL_LED 连接到 EMIO0
#define EMIO_KEY 55 //PL_KEY 连接到 EMIO1
int main()
{
XGpioPs gpiops_inst; //PS 端 GPIO 驱动实例
XGpioPs_Config *gpiops_cfg_ptr; //PS 端 GPIO 配置信息
//根据器件 ID 查找配置信息
gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_ID);
//初始化器件驱动
XGpioPs_CfgInitialize(&gpiops_inst, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr);
//设置 LED 为输出
XGpioPs_SetDirectionPin(&gpiops_inst, EMIO_LED, 1);
//使能 LED 输出
XGpioPs_SetOutputEnablePin(&gpiops_inst, EMIO_LED, 1);
//设置 KEY 为输入
XGpioPs_SetDirectionPin(&gpiops_inst, EMIO_KEY, 0);
//读取按键状态,用于控制 LED 亮灭
while(1){ // 按键按下与抬起是不同的状态
XGpioPs_WritePin(&gpiops_inst, EMIO_LED,~XGpioPs_ReadPin(&gpiops_inst, EMIO_KEY));
}
return 0;
}
说明:
引脚编号
#define EMIO_LED 54 //PL_LED 连接到 EMIO0
#define EMIO_KEY 55 //PL_KEY 连接到 EMIO1
引脚编号可以在xgpiops.h头文件中查找, 0-53为MIO, 后面为EMIO,依次编号
下载说明
使用了PL内的资源,在下载软件编译生成的elf文件之前,需要先下载硬件设计生成的bitstream文件,对PL部分进行配置。
也可以在Run Configuration 中配置,先进行系统复位,然后Program FPGA, 然后再Run as
点击Run 后,SDK软件首先会复位整个系统,清除FPGA逻辑,重新下载bitstream 和 elf 文件。
通过 EMIO 扩展的 GPIO 接口的使用方法和 MIO 没有任何区别。
头文件说明:
基本操作流程:
根据器件 ID 查找配置信息
XGpioPs_Config *gpiops_cfg_ptr; //PS 端 GPIO 配置信息
//根据器件 ID 查找配置信息
gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_ID);
初始化器件驱动
XGpioPs gpiops_inst; //PS 端 GPIO 驱动实例
//初始化器件驱动
XGpioPs_CfgInitialize(&gpiops_inst, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr);
设置输入输出模式
// 0 for Input Direction, 1 for Output Direction.
XGpioPs_SetDirectionPin(&gpiops_inst, EMIO_LED, 1);
读写操作
XGpioPs_WritePin(&gpiops_inst, EMIO_LED,0x01)
XGpioPs_ReadPin(&gpiops_inst, EMIO_KEY));