admin 发表于 2022-8-6 11:31:26

【zynq课程笔记】【裸机】【第11课 】【GPIO_EMIO原理与应用】

更多课程笔记请查看:【zynq裸机编程课程笔记合集】
http://www.corecourse.cn/forum.php?mod=viewthread&tid=29095


1.      课程介绍

在第七、八课中,我们为大家介绍了GPIO的结构、原理以及编程思路,并使用C语言编程,实现了使用PS侧按键控制LED亮灭的效果,准确的说,是使用PS的MIO实现了按键控制LED的效果。
GPIO分为MIO与EMIO两种接口,这两种接口在功能结构以及寄存器设置上都是一致的,甚至SDK中提供的驱动库都是完全相同的同一套。不同之处在于:

[*]MIO信号全都直接映射到了Zynq芯片的确定管脚,其位置都是已知且不可更改的。
[*]EMIO是没有固定到芯片特定管脚的一组GPIO,其只能先映射到PL侧,连接PL侧的用户逻辑,或是直接通过PL引出到Zynq芯片的FPGA通用管脚。

总结就是:EMIO就是一种特殊的MIO,是一种可以导出到FPGA中,由FPGA来驱动和分配的MIO。



另外,由于PS的MIO管脚数量是有限的,而PS侧的各种外设控制器所需要引出到芯片管脚的信号总数大于MIO总数,所以当MIO不够用时,可以将这些外设功能,比如UART、SPI、I2C、网口等控制器的引出信号通过EMIO导出到FPGA,再通过FPGA侧的通用管脚连接外部的功能电路。
不过需要注意的是,不是所有的外设的信号都能通过EMIO导出到FPGA使用(打开ZYNQ核的MIO configuration界面),比如USB、Quad-SPI和SMC。
能够导出的功能,导出到EMIO的信号和直接使用MIO的信号名称以及类型都是一样的。但是有个例外,就是千兆以太网,对于千兆以太网,由于PL内部无法传递双数据速率信号,而PS的千兆网使用的RGMII接口是双数据速率IO(DDIO),因此通过EMIO导出到PL时,使用的是8位的GMII接口,FPGA侧可以直接使用FPGA IO来实现GMII接口,也可以在FPGA中使用双数据速率接口(DDIO)再转换为RGMII接口,以连接RGMII接口的以太网PHY。

PS的GPIO包含4个bank,其功能示意如下图所示:



从图中我们可以看到:
Bank0和Bank1映射到了MIO引脚,共54个;
Bank2和Bank3连接的是EMIO,共64个。
因此,在MIO引脚不够用时,我们可以驱动EMIO控制PL引脚,以实现更多可用的PS GPIO管脚。



2.      课程目的

既然EMIO这么方便易用,本节课程我们就使用EMIO接口,实现PL侧按键(S2)控制PL侧LED灯(D5)亮灭的设计。通过设计,带领大家了解EMIO的使用流程,以及使用时与MIO的差异。


3.      所包含硬件

本节课程只需要使用ACZ702开发板主板即可。在ACZ702开发板上,PS侧与PL侧各带有一个按键和LED灯,因此设计不需要外接任何外设。PL侧按键对应开发板上丝印为S2,PL侧LED灯对应丝印D5。




4.      系统框图

为了方便大家理解,这里为大家做了一张本次设计的简易框图。



在设计时,我们通过软件编程,将连接S2的EMIO配置为输入模式,用来捕获用户通过按键输入的电平;将连接D5的EMIO配置为输出模式,ARM将需要设置的LED的亮灭状态值通过EMIO输出,驱动LED亮灭显示。C软件程序,直接使用第八课的内容就可以、。



5.      创建工程

介绍完设计的系统模型,接下来我们就可以使用Vivado和SDK开始系统的设计和实现了。
1.      创建一个名为GPIO_EMIO的工程
2.      新建Block Design设计
3.      添加ZYNQ IP核



6.      IP核配置与端口导出

(1)      IP核配置
点击导航界面的GPIO,跳转到GPIO外设使能界面,使能GPIO MIO和EMIO GPIO(Width),设置EMIO GPIO(Width)的I/O数量为2。

[*]设置Bank1的电压为LVCMOS 1.8V
[*]配置DDR型号为MT41K128M16 JT-125
[*]取消M_AXI_GP0接口

这里给大家解释下Bank电平还有外设使能为什么需要这么配置:
首先是外设使能,勾选MIO是为了使设计更加灵活,当设计需要使用到MIO时,随时都能用到;在勾选EMIO GPIO(Width)时,默认就是使能了EMIO。S2和D5各需要一个EMIO接口,所以在勾选EMIO GPIO(Width)后将其I/O设置为2,这里的I/O指的是数量而不是类型。而PS的MIO接口因为是已经连接好的,固定的引脚,所以不需要也没有设置I/O数量这一选项。
接着是Bank电平配置,Bank的电平配置在ug585的Boot and Configuration章节中有所提及,这里给出手册中的关系表:



可以看到,Bank0和Bank1的电平标准分别由MIO7和MIO8的输入决定,开发板上这两个接口的硬件电路如下图



可以看到,MIO8接在3.3V上,输入高电平,对应Bank1的电平标准为LVCMOS 1.8V;MIO7接地,输入低电平,对应Bank0的电平标准为LVCMOS 3.3V。
至于为什么这里通过硬件将Bank1电平标准设置为LVCMOSS 1.8V,根据Xilinx原厂相关人员介绍,主要是考虑到rgmii速率较高,为了确保通信在任何情况下都能够确定可靠,所以推荐将以太网IO所在Bank电平标准设置为LVCMOS 1.8V。

(2)      端口连接
点击“Run Block Automation”,随后右键GPIO_0引脚选择make External导出引脚,为了方便辨别,这里可以给引脚命名为EMIO。



7.      管脚约束

当完成block design设计之后,我们还需要对该block design生成输出文件(generate output products),并生成一个例化了该设计的HDL格式的顶层文件。
当顶层文件生成好之后,点击“Open Elaborated Design”对设计进行详细的分析,分析完成后就可以自动打开管脚约束界面进行管脚约束,如果显示的界面不是管脚分配,大家可以通过手动在右上角的下拉列表中选择I/O planning选项卡以切换到IO分配界面。关于ACZ702开发版各项功能对应的管脚信息,可以直接在下述帖子中查看。
ACZ702开发板管脚信息表
http://www.corecourse.cn/forum.php?mod=viewthread&tid=29058
以下为本次实验所用功能对应的引脚分配表:


Pin NameSignial NamePin NO.
FPGA_LEDEMIO_tri_ioT14
FPGA_Key0EMIO_tri_ioF20


分配完成后将引脚电平标准修改为LVCMOS33,然后保存约束文件,命名为GPIO_EMIO.xdc,
到此,我们已经完成了整个系统的硬件系统部分的设计,接下来,我们就可以点击generate bitstream来生成本系统的PL配置文件,也就是我们常说的bit文件。


8.      查看编译报告

等待比特流生成完成,我们就可以通过点击Project Summary图标,并切换到Dashboard选项卡中,来查看当前设计的资源使用等信息。



9.      创建SDK工程并添加实例源码

通过前面的操作,我们已经完成了硬件系统的设计,并得到了相应的FPGA配置文件(bit)。
接下来我们还需要针对该硬件系统,生成对应的描述文件,只有基于这些描述文件,我们才能在SDK中对该系统进行正确的编程。
在菜单栏中点击File->Export->Export Hardware,以生成本系统的硬件描述文件,由于使用到了PL的引脚,导出时需要包含bitstream文件。这里建议大家无论设计是否使用了PL的资源,都选择包含比特流。就算是纯PS的设计,我们勾选包含比特流也不会对工程产生任何影响,但如果是涉及到PL资源的设计,如果没有勾选包含比特流,将会导致设计的失败。
导出硬件描述文件后我们就可以点击File->Launch SDK来打开Vivado提供的SDK集成开发软件。然后在软件中创建一个空白模板的SDK工程,创建好之后,在src文件夹下创建一个名为main.c的源文件,向其中添加本次设计源码,源码内容如下:

#include "xgpiops.h"
#include "unistd.h"

XGpioPs Gpio;
XGpioPs_Config *ConfigPtr;

int main(void)
{
    ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
    XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);

    /*设置EMIO0为输入,MIO有54个,EMIO0=54+0=54*/
    XGpioPs_SetDirectionPin(&Gpio, 54, 1);
    XGpioPs_SetOutputEnablePin(&Gpio, 54, 1);

    /*设置EMIO1为输入*/
    XGpioPs_SetDirectionPin(&Gpio, 55, 0);
    XGpioPs_SetOutputEnablePin(&Gpio, 55, 0);

    while(1)
    {
      while(!XGpioPs_ReadPin(&Gpio, 55))
      {
            //设置bit54输出1
            XGpioPs_WritePin(&Gpio, 54, 0x1);
            usleep(500000);

            //设置bit54输出0
            XGpioPs_WritePin(&Gpio, 54, 0x0);
            usleep(500000);
      }

      //设置bit54输出0
      XGpioPs_WritePin(&Gpio, 54, 0x0);
    }

    return 0;
}

可以看到,这里代码使用的是MIO驱动PS LED亮灭的设计中的代码,仅仅只修改了驱动的GPIO引脚。
到此,我们的应用程序就创建完了,程序写完之后,我们还需要下载到开发板中进行验证,观察实验效果是否正确。


10.      硬件连接

本次硬件连接如下图所示:



由于本实验只进行简单的LED驱动,所以整体设计功耗不高,不需要使用独立供电,使用调试口Type-C供电就足够。使用调试口供电时,右侧的电源开关需要拨到上端USB侧。连接调试口时注意是靠近电源接口一侧的Type-C接口。
(Run Configuration - SystemDebugger)



11.      运行程序

现象:长按开发板上按键S1,LED灯D5会每隔1s闪烁一次。



12.      总结

到这里,本节课程内容就已经基本结束了,在本节课程中我们学习了EMIO的相关原理,并带领大家完成了EMIO的应用设计。通过设计我们可以发现,作为PS GPIO的一部分,EMIO与MIO的编程思路是一致的,都需要进行如下步骤:
1.      初始化GPIO驱动程序
2.      设置指定引脚方向
3.      设置输出引脚的输出使能
4.      读/写指定管脚的值/状态
不同点仅在于MIO是用于PS侧,管脚早已固定,不需要、也不能进行手动分配,而EMIO是拓展到PL的MIO,具体路由到哪一个管脚,还是说直接在fpga内部连接到某个信号,需要用户手动编程或进行管脚分配。
最后,作为对本节课程的一个复习与巩固,这里为大家布置一个思考题,或者说是课后小作业。



13.      课后习题

使用开发板上PL端的按键S2,控制开发板上LED灯D4、D5交替闪烁。
要求:按键长按后,D4、D5每秒完成一次亮灭交替
注意,这个题目和本节课程讲解的内容差异在于,既控制了PL侧的LED灯,又控制了PS侧的LED灯,也就是MIO和EMIO都需要用到。

admin 发表于 2022-8-6 12:29:09

课程完整工程文件包括Vivado工程和SDK中的源码(工程发布前已经执行了reset_project操作,故大家下载后需要先执行generate bitstream操作)


单独的C源码

tb一下 发表于 2022-8-6 12:34:56

占楼

wqh1189 发表于 2023-12-6 08:18:45

楼主笔误,EMIO0应该是输出。楼主讲的挺好的,准备好好学习一下
页: [1]
查看完整版本: 【zynq课程笔记】【裸机】【第11课 】【GPIO_EMIO原理与应用】