本帖最后由 正点原子01 于 2020-8-31 17:49 编辑
1)实验平台:正点原子领航者ZYNQ开发板
2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-301505-1-1.html
4)本章实例源码下载:
GPIO之EMIO按键控制LED实验.zip
(10.33 MB, 下载次数: 18)
5)对正点原子FPGA感兴趣的同学可以加群讨论:905624739 点击加入群聊:![]()
6)关注正点原子公众号,获取最新资料更新
第三章 GPIO之EMIO按键控制LED实验
PS和外部设备之间的通信主要是通过复用的输入/输出(Multiplexed Input/Output,MIO)实现的。除此之外,PS还可以通过扩展的MIO(Extended MIO,EMIO)来实现与外部设备的连接。EMIO使用了PL的I/O资源,当PS需要扩展超过54个引脚的时候可以用EMIO,也可以用它来连接PL中实现的IP模块。 本章我们将学习GPIO中EMIO接口信号的使用。本章包括以下几个部分: 1.1 简介 1.2 实验任务 1.3 硬件设计 1.4 软件设计 1.5 下载验证 1.1 简介ZYNQ GPIO接口信号被分成四组,分别是从BANK0到BANK3。其中BANK0和BANK1中共计54个信号通过MIO连接到ZYNQ器件的引脚上,这些引脚属于PS端;而BANK2和BANK3中共计64个信号则通过EMIO连接到了ZYNQ器件的PL端。如下图所示:
在大多数情况下,PS端经由EMIO引出的接口会直接连接到PL端的器件引脚上,通过IO管脚约束来指定所连接PL引脚的位置。通过这种方式,EMIO可以为PS端实现额外的64个输入引脚或64个带有输出使能的输出引脚。EMIO还有一种使用方式,就是用于连接PL内实现的功能模块(IP核),此时PL端的IP作为PS端的一个外部设备。如图3.1.2所示:
1.2 实验任务本章的实验任务是使用领航者ZYNQ底板上的三个用户按键分别控制PS端三个LED的亮灭。其中一个按键PL_KEY0连接到了PL端,需要通过EMIO进行扩展。 1.3 硬件设计根据实验任务我们可以画出本次实验的系统框图,如下图所示:
与《GPIO之MIO控制LED实验》中的系统框图相比,图 5.3.1中的PS端多了EMIO模块。除此之外,因为EMIO使用了PL端的IO资源,所以图中增加了PL部分。PL端与按键PL_KEY0相连的引脚直接通过EMIO连接到PS端。 step1:创建Vivado工程 本次实验可以在前一个实验的基础上进行。 1-1 我们打开《GPIO之MIO控制LED实验》中的Vivado工程“gpio_mio”,打开后在菜单栏中选择File > Project > Save As,如下图所示:
1-2 在弹出的对话框中输入新的工程名,在Project name一栏输入工程名“gpio_emio”,工程位置保持默认即可,如下图所示:
点击“OK”按钮,原先的Vivado工程会关闭,并打开一个新的工程“gpio_emio”。 此时如果我们打开工程所在的路径,即F:\ZYNQ\Embedded_System\gpio_emio,可以看到如下图所示的文件目录:
此时我们就在gpio_mio工程的基础上得到了一个新的工程gpio_emio,这样就省去了重新搭建硬件的过程。由于我们不需要原工程中的软件工程,因此将图3.3.4中红色方框所指示的“gpio_emio.sdk”文件夹删除。 接下来我们将在《GPIO之MIO控制LED实验》中硬件设计的基础上搭建本次实验的硬件平台。 step2:使用IP Integrator创建Processing System 2-1在Flow Navigator中,点击IP INTEGRATOR下的Open Block Design,如下图所示:
2-2 在Diagram窗口中,双击打开ZYNQ7 Processing System重定义窗口。
图 4.3.6 重定义ZYNQ7 Processing System 2-3 在下图所示的配置界面中,点击左侧的MIO Configuration。然后在右侧展开GPIO一栏,勾选EMIO GPIO,并设置位宽为1。该设置将通过EMIO扩展一个1位的GPIO接口信号,此信号将用于连接PL端的引脚。
完成配置后,点击右下角的“OK”按钮。然后在Diagram窗口中可以看到ZYNQ7 Processing System多了一个GPIO_0端口,如下图所示:
将光标移动到上图中箭头所指示的位置,会发现光标变成了铅笔的样式。点击选中该端口,然后点击鼠标右键,在弹出的列表中选择“Make External”。如下图所示:
可以看到ZYNQ7 ProcessingSystem引出了一个名为GPIO_0_0的接口,如下图所示:
点击选中该接口,在左侧ExternalInterface Properties一栏中将该接口的名称修改为GPIO_EMIO_KEY。如下图所示:
2-4 本次实验不需要添加其它的IP,按Ctrl+S快捷键保存设计。 step3:生成顶层HDL 3-1 在Sources窗口中展开Design Sources,然后右键点击sysetm_wrapper下的system.bd,在弹出的菜单中选择Generate Output Products,如下图所示:
图 4.3.12 选择Generate Output Products... 3-2 在弹出的对话框中选择“Generate”,然后等待Generate完成后点击“OK”。 3-3 创建顶层HDL Wrapper 在之前的实验中,我们创建顶层模块时选择了“Let Vivado manage wrapper and auto-update”选项,所以此处无需再创建顶层HDL Wrapper,Vivado会自动更新顶层HDL Wrapper。 step4:生成Bitstream文件并导出到SDK 4-1在左侧Flow Navigator导航栏中找到RTL ANALYSIS,点击该选项中的“Open Elaborated Design”。如下图所示:
在弹出的对话框中点击“OK”。如下图所示:
图 4.3.14 Elaborate Design 对话框 在ELABORATEDDESIGN界面下方找到I/O Ports窗口。如果没有找到I/O Ports一栏则通过在菜单栏中点击Layout,然后在下拉列表中选择I/O Planning。我们将在I/O Ports窗口中对PL部分的接口进行管脚分配。
在上图中,DDR_12642和FIXED_IO_12642里面是PS端的输入/输出接口,这部分接口不需要我们手动进行管脚分配。在图 3.3.12中选择“GenerateOutput Products”之后,Vivado工具会自动创建PS端的管脚约束文件。 在本次实验中,我们通过EMIO扩展了一个GPIO的接口信号,即上图中的GPIO_EMIO_KEY。我们需要将其分配到PL的L20引脚上,从原理图上可以看到,该引脚最终与领航者ZYNQ底板上的按键PL_KEY0相连接。另外L20位于ZYNQ7020芯片的BANK35内,该BANK的供电电压为3.3V,因此I/OStd一列对应的电平也需要修改。如下图所示:
4-2设置完成后按快捷Ctrl+S保存管脚约束,在弹出的对话框输入文件名“Navigator”,最后点击“OK”,如下图所示: 图 4.3.17 保存约束 4-3在左侧Flow Navigator导航栏中找到PROGRAM AND DEBUG,点击该选项中的“Generate Bitstream”,然后在连续弹出的对话框中依次点击“YES”、“OK”。此时,Vivado工具开始对设计进行综合、实现、并生成Bitstream文件。 4-4 生成Bitstream完成后,在弹出的对话框中选择“Open ImplementedDesign”,如下图所示:
点击“OK”,会弹出对话框提示关闭Elaborated Design,点击“YES”。 在IMPLEMENTEDDESIGN界面我们可以查看设计对PL资源的使用情况。在左侧FlowNavigator导航栏中找到IMPLEMENTATION,点击该选项中的“Report Utilization”,然后在弹出的对话框中点击“OK”。如下图所示:
在界面下方的Utilization标签页中,选择左侧的Summary,然后在右侧会以表格和柱状图两种方式显示当前PL资源的使用情况。在我们本次实验中,只消耗了PL端1个LUT和一个IO资源,这个IO就是PS通过EMIO扩展GPIO接口信号时所使用的PL引脚。如下图所示:
4-5 导出硬件。 在菜单栏中选择 File> Export > Export hardware。 在弹出的对话框中,勾选“Includebitstream”,然后点击“OK”按钮。如下图所示:
图 4.3.21勾选“Include bitstream” 在此处需要注意,如果我们的设计使用了PL的资源,比如使用了PL的引脚,或者在PL内实现了部分功能模块,那么我们就需要生成Bitstream文件,并在导出硬件的时候包含该文件。 4-2 硬件导出完成后,在菜单栏选择File > Launch SDK,启动SDK开发环境。在弹出的对话框中,直接点击“OK”。 到这里我们的硬件设计部分已经结束,接下来的软件设计部分需要在SDK软件中进行。 1.4 软件设计在硬件设计的最后,我们打开了SDK开发环境,如下图所示:
图 3.4.1中红色方框所指示的文件夹是我们本次实验所导出的硬件设计文件。 需要注意的是,本次实验是在gpio_mio实验工程的基础上进行的,但是我们不需要之前工程中的SDK应用程序。因此在图3.3.4所示的步骤中,我们要将工程文件夹中后缀为.sdk的文件夹删除,否则在上图中将会保留前一实验中的软件工程文件。如下图所示:
上图中箭头所指示的文件夹是我们本次实验所导出的硬件设计文件。而红色方框里的是前一实验的工程文件,我们直接选中,然后按键盘上的Delete键将其删除。在弹出的删除对话框中,勾选“Delete projectcontents on disk”,然后点击“OK”按钮。 step5:在SDK中创建应用工程 5-1在菜单栏中选择File > New > Application Project, 新建一个SDK应用工程。 4.4.3 创建应用工程 5-2 在弹出的图2.4.4所示界面中,输入工程名“gpio_emio”。 在该页面中,我们需要确认HardwarePlatform一栏中选择的是本次实验新导出的硬件平台system_wrapper_hw_platform_0。如果我们没有删除前一实验的工程文件,那么此处就要选择图 3.4.2中箭头所指示的硬件平台system_wrapper_hw_platform_1。另外,在BoardSupport Package一栏选择“Create New”,其他选项保持默认。 5-3 在图2.4.4中点击“Next”,然后选择工程模版Empty Application,然后点击“Finish”。 5-4 可以看到在左侧Project Explorer中创建了一个gpio_emio工程目录和gpio_emio_bsp工程目录。 5-5 新建源文件。在gpio_emio/src目录上右键点击,选择New > Source File,如下图所示:
在弹出的对话框中Source file一栏输入文件名“main.c”,然后点击“Finish”。
5-10 新建源文件之后,在左侧gpio_emio/src目录下可以看到main.c文件,同时在SDK主页面已经打开了该文件的文本编辑框。我们在新建的main.c文件中输入以下代码: - #include "stdio.h"
- #include "xparameters.h"
- #include "xgpiops.h"
- #define GPIOPS_ID XPAR_XGPIOPS_0_DEVICE_ID //PS端 GPIO器件 ID
- #define MIO_LED0 7 //PS_LED0连接到 MIO7
- #define MIO_LED1 8 //PS_LED1连接到 MIO8
- #define MIO_LED2 0 //PS_LED2连接到 MIO0
- #define MIO_KEY0 12 //PS_KEY0 连接到 MIO7
- #define MIO_KEY1 11 //PS_KEY1 连接到 MIO8
- #define EMIO_KEY 54 //PL_KEY0 连接到EMIO0
- int main()
- {
- printf("EMIOTEST!\n");
- 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, MIO_LED0,1);
- XGpioPs_SetDirectionPin(&gpiops_inst, MIO_LED1,1);
- XGpioPs_SetDirectionPin(&gpiops_inst, MIO_LED2,1);
- //使能LED输出
- XGpioPs_SetOutputEnablePin(&gpiops_inst, MIO_LED0,1);
- XGpioPs_SetOutputEnablePin(&gpiops_inst, MIO_LED1,1);
- XGpioPs_SetOutputEnablePin(&gpiops_inst, MIO_LED2,1);
- //设置KEY为输入
- XGpioPs_SetDirectionPin(&gpiops_inst, MIO_KEY0,0);
- XGpioPs_SetDirectionPin(&gpiops_inst, MIO_KEY1,0);
- XGpioPs_SetDirectionPin(&gpiops_inst, EMIO_KEY,0);
- //读取按键状态,用于控制LED亮灭
- while(1){
- XGpioPs_WritePin(&gpiops_inst, MIO_LED0,
- ~XGpioPs_ReadPin(&gpiops_inst, MIO_KEY0));
- XGpioPs_WritePin(&gpiops_inst, MIO_LED1,
- ~XGpioPs_ReadPin(&gpiops_inst, MIO_KEY1));
- XGpioPs_WritePin(&gpiops_inst, MIO_LED2,
- ~XGpioPs_ReadPin(&gpiops_inst, EMIO_KEY));
- }
- return 0;
- }
复制代码在代码的第7至12行,我们指定了PS端的按键和LED所连接的MIO引脚编号,这些编号可以从领航者ZYNQ核心板和底板的原理图中查到。而在代码的第14行则指定了PL端的按键PL_KEY0连接到了GPIO的第54号引脚,那么这个54是怎么来的呢? 在本章的简介部分我们提到过,ZYNQ的GPIO被分成了4组,其中通过EMIO扩展的GPIO接口位于BANK2和BANK3中,如图 3.1.1所示。在本次实验中我们通过EMIO扩展了1个GPIO信号,即BANK2的EMIO0。由于GPIO的BANK0和BANK1分别有32和22个信号,所以BANK2的EMIO0编号为54(从0开始编号)。 我们按住Ctrl键,然后点击代码开头处所引用的头文件“xgpiops.h”以打开该文件。在文本编辑界面的左侧空白边框处右击,然后选择“ShowLine Numbers”可以显示代码的行号。 在xgpiops.h文件第162行给出了ZYNQ器件GPIO最大的引脚数目,共118个,分别位于4个Bank中。在下面的注释中则分别列出了各Bank的引脚编号范围,同样可以看到Bank2的第一个引脚编号为54。
在程序的第42至52行,我们在一个死循环中不断读取各按键的状态,然后将读到的值取反后分别写入对应的LED中,从而实现按键控制LED的功能。从上面的程序中大家也可以看出,通过EMIO扩展的GPIO接口的使用方法和MIO没有任何区别。如果大家对GPIO的使用不熟悉的话,请参考《GPIO之MIO控制LED实验》。 5-6 我们按快捷键Ctrl+S保存main.c文件,工具会自动进行编译,编译过程可以在SDK下方的控制台(Console)中看到。编译完成后Console中会出现提示信息“Build Finished”,同时在gpio_emio的Binaries目录下可以看到生成的elf文件。如下图所示: 1.5 下载验证首先我们将下载器与领航者底板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用Mini USB连接线将开发板左侧的USB_UART接口与电脑连接,用于串口通信。最后连接开发板的电源,并打开电源开关。 step6:板级验证 6-1在SDK软件下方的SDK Terminal窗口中点击右上角的加号连接串口,并在弹出的窗口中对串口进行设置。 需要注意的是,在设置端口(Port)时,在下拉列表中可能会看到多个可选端口。我们需要选择与领航者底板上的串口所连接的端口,具体的端口号可在计算机设备管理器中查看。因为底板上使用的USB转串口芯片型号为CH340,因此在设备管理器中找到USB-SERIAL CH340所对应的端口,在我这台电脑上该端口号为COM12。如下图所示:
串口的设置如下图所示:
6-2 下载程序。因为本次实验使用了PL内的资源,因此我们在下载软件编译生成的elf文件之前,需要先下载硬件设计过程中生成的bitstream文件,对PL部分进行配置。 在菜单栏中点击“Xilinx”,然后选择“Program FPGA”。在弹出的对话框中Bitstream一栏,确认已经加载了本次实验硬件设计过程中所生成的BIT文件——“system_wrapper.bit”。最后点击右下角的“Program”,如下图所示:
配置PL完成后,接下来我们要下载软件程序。在应用工程gpio_emio上右击,选择“Run As”,然后选择第一项“1 Launch on Hardware (System Debugger)”。 软件程序下载完成后,在下方的SDKTerminal中可以看到应用程序打印的信息“EMIO TEST!”,如下图所示:
我们分别按下领航者底板上的两个PS端的用户按键PS_KEY0和PS_KEY1,可以看到底板上对应的两个PS端的LED灯在按键按下时点亮,释放后熄灭。 然后再按下底板上PL端的用户按键PL_KEY0,可以看到核心板上PS端的LED2(红色)在按键按下时点亮,释放后熄灭。说明我们通过EMIO扩展GPIO接口,使用PL端按键控制PS端LED的实验在领航者ZYNQ开发板上面下载验证成功。实验结果如下图所示:
|