ZYNQ_SDK EMIO
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 端。
步骤
step1: 配置EMIO
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一栏中将该接口的名称修改
step2: 生成顶层HDL
在 Sources 窗口中展开 Design Sources,然后右键点击 sysetm_wrapper 下的 system.bd,在弹出的菜
单中选择 Generate Output Products
step3: 创建顶层HDL Wrapper
step4: 生成Bitstream文件导出到SDK
Flow Navigator 导航栏中找到 RTL ANALYSIS,点击该选项中的"Open Elaborated Design"
I/O Planning:在 I/O Ports 窗口中对 PL 部分的接口进行管脚分配
如果是MIO的输入/输出接口不需要手动进行管脚分配,选择"Generate Output Products"之后,Vivado 工具会自动创建 PS 端的管
脚约束文件。
自行扩展的GPIO的接口信号,需要手动将其分配引脚,要与原理图对应。
按键SW :
LED:
引脚绑定:
step5: 导出硬件
File -> Export -> Export Hardware
在弹出的对话框中,勾选“Include bitstream”
如果设计使用了 PL 的资源,比如使用了 PL 的引脚,或者在 PL 内实现了部分功能模块,那么就需要生成 Bitstream 文件,并在导出硬件的时候包含该文件。
资源消耗
在 IMPLEMENTED DESIGN 界面可以查看设计对 PL 资源的使用情况。
在左侧 Flow Navigator 导航栏中找到 IMPLEMENTATION,点击该选项中的"Report Utilization"
软件设计
导出的为硬件设计文件
步骤
step1: 在SDK中创建应用工程
File > New > Application Project,新建一个 SDK 应用工程
- Project name : 指定项目名称
- Hardware Platform 指定硬件设计文件
- Board Support Package : BSP 板级支持包,可以指定名称
step2: 应用程序编写
/** * 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 没有任何区别。
头文件说明:
- xparameters.h 定义了 设备地址、参数等等信息
- xgpiops.h 包含了 ps操作gpio相关的操作
基本操作流程:
- 根据器件 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));