前言:
**Xilinx ZYNQ
**系列的芯片,GPIO分为 MIO 、EMIO 、AXI_GPIO三种方式。
MIO:固定管脚,属于PS端,也就是ARM端。
EMIO:通过PL扩展,使用时需要分配PL (
FPGA)
管脚,消耗PL端资源。
AXI_GPIO:封装好的IP核,PS通过M_AXI总线可以控制PL的IO接口,使用时,消耗管脚资源和逻辑资源。
MIO:
MIO(Multiuse I/O) ,多功能IO接口,分配在GPIO的Bank0 和 Bank1 ,属于Zynq的**PS(ARM)**部分。
这些引脚,可以直接用在GPIO、SPI、UART、TIMER等等一些PS端外设,这些引脚与PS直接相连接,不需要添加引脚约束,并且也不占PL端资源。
Bank0有32个MIO引脚,Bank1有22个MIO引脚,54个引脚直接通过MIO连接到PS上。
EMIO:
EMIO(Express Multiuse I/O) ,扩展多功能IO,分布在BANK2、BANK3 ,依然属于Zynq的PS部分,只是直接连接到了PL上,当MIO不够使用时,可以通过EMIO控制PL部分的引脚。
当我们想通过PS来访问PL又不想浪费AXI总线时,就通过EMIO接口来访问,使用的时候,需要添加约束文件,分配PL端的引脚。
AXI_GPIO:
AXI_GPIO,相当于GPIO的IP核,通过AXI总线挂在PS上的GPIO。
我们在FPGA工程上添加相应的GPIO的IP核,然后生成相关PL端的逻辑,并且添加约束文件,以分配PL端的管脚才能正常使用。其占用了PL端的逻辑和资源。
开发目的:
PS端GPIO 外设使用、EMIO 使用、PS与PL联合调试
开发流程:
1,工程创建
双击打开Vivado软件,界面如下图所示
首先点击Quick Start 下的 Create Project 创建新工程,也可点击工具栏中的 File->Project->New...进行创建。
进入新建工程向导后next,编辑工程名称和工程目录
对需要的工程类型进行选择,将光标放置在对应的选项上即可出现对应的中文翻译。这里我们勾选"RTL Project",因为我们是完全新建工程,所以勾选下方的现在不指定资源,接着点击"next"进行下一步。
接下来选择对应的开发板型号
接下来会弹出工程摘要界面,该界面会对工程的类型以及所选用芯片的器件型号进行总结,用户可通过该界面检查是否有创建错误。确认无误后点击 Finish 完成工程创建
2,模块创建
创建完成后Vivado工程后软件界面及对应功能如下图
接下来点击"Create Block Design"创建一个模块设计,在弹出的窗口中对设计命名。
接下来对其命名 注意:不能使用中文以及空格命名。
创建完成后软件界面如图所示,可以看到此时Design栏中出现了我们刚创建好的"system"模块设计。此时我们的设计内没有任何内容,需要点击 "+"为设计添加IP核。
3,硬件系统创建
添加IP核
在弹出的搜索栏中输入 zynq,可以看到下方出现了"ZYNQ7 Processing System", 如图所示。该IP核为ZYNQ7 处理系统IP核,双击该IP核添加。 添加完成后的zynq IP核如图所
大部分IP核在添加完成后,并不能直接满足用户的需求,我们还需对IP核 的接口信号以及一些相关参数进行配置
双击IP核 进入配置
首先配置DDR
uart配置
uart波特率配置
GPIO配置
Bank电平配置 Bank0(3.3v) Bank1(1.8v)
使能完外设接口后我们返回图形化向导界面,如图所示。可以看到在GPIO外设和uart后面已经打上了√,代表此时我们已经使能该接口。在进行硬件逻辑系统搭建时,我们可以通过该界面快速一览使用到了哪些zynq资源。
配置完 DDR后即完成了本次 zynq IP 核的配置,点击 OK,可以看到此时 zynq IP 核如图 2-31所示,因为我们配置了GPIO外设,相较于配置前,此时多 了一个GPIO_0端口。
添加ila
然后导出引脚
在涉及到的模块较多的场合,系统会出现自动连接(Run Connection Automation)的选项,如图 所示。点击该项并设置需要连接的模块后,软件便会自动生成 AXI 互联 IP 核(AXI Interconnect)和处理器系统复位 IP 核 (Processor System Reset),并自动连接 AXI信号,部分时钟信号和复位信号。 但是软件在连接时,有时会将信号连接到用户期望之外的端口上。因此,连线复杂的设计通常需要手动对部分端口信号进行连接。
验证设计
端口连接完成后使用快捷键 Ctrl+S 或者点击左上方的保存按钮保存设计, 随后点击上方的√来对设计进行验证。
系统开始对设计进行验证,当出现以下弹窗时,证明设计无误。如果出现 警告,则需要重新检查系统。
4,生成封装
点击sources资源栏下我们创建的system模块设计,单击右键,在展开的功 能中选择"Generate Output Products..."生成输出。
接下来软件会弹出生成输出前的设置界面,如图所示。在合成选项栏 直接选择"Out Of context per IP"即可,下方的"Number of jobs"选项选择最 大值。该值会影响生成输出时的速度,该值越大,生成输出的速度就越快,最 大值与电脑配置有关,设置完成后点击"Generate"开始生成。
输出的生成比较慢需要等待一段时间,生成完成后软件会弹出如图 所 示弹窗,点击OK即可。
接着我们还是点击sources资源栏下我们创建的system模块设计,单击右键, 在展开的功能中选择"Create HDL Wrapper..."创建HDL封装。
在弹出的窗口中选择让 vivado管理封装和自动更新,随后点击 OK开始创建封装。
当Sources栏出现蓝色的设计文件时,则代表封装已经创建和更新完成,如图所示。
这里需要注意的是,mcu_design.v 文件为顶层例化文件,在用户修改设计并生成输出后,只要更新 Wrapper,mcu_design.v 中的内容便会被覆盖。 若用户需要在顶层中手动加入一些语句,在修改硬件生成输出后只要更新 Wrapper这些语句便会被覆盖。如果您的设计中需要加入自己的逻辑代码,建议用户手动创建一个顶层文件,在文件中例化mcu_design.v文件,并添加自己的逻辑代码。
5,管脚约束
对于使用过PL端的设计,在完成封装后,我们需要对涉及到的管脚进行分 配和约束。点击左侧导航栏的"Open Elaborated Design"进行约束和分配。
打开后管脚约束界面如图所示,如果软件没有正确显示该界面,可以 将右上角的下拉栏展开,打开I/O Planning皆可切换到该页面。
在管脚约束界面中,我们需要做的是对使用到的PL端的管脚进行分配并对 管脚电平进行约束,本次设计所涉及到的为PL端的按键和PL端的LED灯。
具体管脚查询自己所用到的开发板型号说明文件 查询完成管脚分配
完成分配后使用快捷键 Ctrl+S 对约束文件进行保存,此时软件会弹出弹窗 让用户进行命名,将光标停在英文上即可出现对应翻译。在下方File name中对文件进行命名,这里读者可自行命名,只要符合命名规范即可。
6,生成比特流
完成了管脚约束后即可开始比特流的生成,比特流中包含着对PL端的配置信息,其中就包括对引脚的分配以及电平的约束,因此生成比特流需要在进行管脚分配和约束之后。当然如果设计并未使用到PL部分资源,可以直接跳过该 环节。 点击"Generate Bitstream"开始生成比特流,如图所示。此时软件会提示没有可用的实现结果,是否先进行综合实现再自动生成比特流,我们直接 点击Yes即可。
比特流生成的时间较长,需要耐心等待,在生成比特流时,vivado 软件右 上角会显示此时的运行状态,如图所示。
当比特流生成完成时,右上角会出现√的标识,
7,导出硬件
首先点击 File,然后在展开的功能栏中选择 Export,最后在 Export 的多个 选择项中选择"ExportHardware..."将硬件描述文件导出。
此时软件会弹出弹窗询问我们是否包含比特流,对于本次设计,我们涉及到了 PL 端的资源使用,因此需要勾选比特流,如图 所示。勾选比特流后 点击OK开始导出。
比特流中包含有PL端的配置信息,因此对于涉及到PL端资源的设计,导 出硬件描述文件时我们需要包含比特流,以配置 PL。而对于纯 PS 端的设计, 用户在导出时无论是否勾选包含比特流都是可以的
8,启动SDK
硬件导出完成后 vivado 部分的设计已经完成,接下来打开 SDK开始 CPU 软件程序设计。点击File,在展开的功能栏中选择"Launch SDK"
接下来软件会弹出弹窗让我们设置硬件描述文件和工作空间的路径,这里我们保持默认即可,点击OK运行SDK。
9,CPU软件程序设计
打开SDK软件界面如图 所示,其中"system_wrapper_hw_platform_0" 为从vivado中导出的硬件资源描述文件。
创建SDK工程
接下来会进入工程创建界面,如图所示。此时需要为工程命名, 其余部分软件已经帮我们设置好了,例如工程所支持的硬件平台,处理器型号 等。这里我们保持默认,点击Next进行下一步。
这里我们需要为工程选择模板,选择 Empty Application,此时右边窗口便 会出现当前工程模板的描述,点击Finish完成工程创建。
创建完成可以看到工程资源中多了两个文件夹
添加用户代码
如图所示,将工程下拉展开,右键单击 src 文件夹,在弹出的功能栏 中选择New/Source File。
接下来我们需要对该源文件命名,这里必须命名为 main.c,其余部分保持 默认即可。点击Finish完成创建。
完成创建后软件的编辑器自动帮我们打开了 main.c 文件,同时还打开了一 个system.mss的文件,如图所示。
在写入用户代码前,我们先跳转到系统为我们打开的 system.mss 文件查看。 可以看到该文件除了对板级支持包进行了相关说明外,还提供了许多相关的驱 动例程和相关文档供开发者参考。
接下来返回main.c,向其中添加以下代码:
cpp
#include "xparameters.h"
#include "xgpiops.h"
#include "xstatus.h"
#include "xplatform_info.h"
#include <xil_printf.h>
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
#define LED_MIO0 7
#define LED_MIO1 8
#define LED_EMIO 54
XGpioPs Gpio_PS; /* The driver instance for GPIO Device. */
int main()
{
XGpioPs_Config *GPIO_ConfigPtr;
//初始化GPIO外设
GPIO_ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
XGpioPs_CfgInitialize(&Gpio_PS, GPIO_ConfigPtr,
GPIO_ConfigPtr->BaseAddr);
//选择gpio管教方向
XGpioPs_SetDirectionPin(&Gpio_PS, LED_MIO0, 1);
XGpioPs_SetDirectionPin(&Gpio_PS, LED_MIO1, 1);
XGpioPs_SetDirectionPin(&Gpio_PS, LED_EMIO, 1);
//使能gpio管教
XGpioPs_SetOutputEnablePin(&Gpio_PS, LED_MIO0, 1);
XGpioPs_SetOutputEnablePin(&Gpio_PS, LED_MIO1, 1);
XGpioPs_SetOutputEnablePin(&Gpio_PS, LED_EMIO, 1);
while(1)
{
XGpioPs_WritePin(&Gpio_PS, LED_MIO0,0x0);
XGpioPs_WritePin(&Gpio_PS, LED_MIO1,0x0);
XGpioPs_WritePin(&Gpio_PS, LED_EMIO,0x0);
sleep(1);
XGpioPs_WritePin(&Gpio_PS, LED_MIO0,0x1);
XGpioPs_WritePin(&Gpio_PS, LED_MIO1,0x1);
XGpioPs_WritePin(&Gpio_PS, LED_EMIO,0x1);
}
return 0;
}
Ctrl+S 保存设计,SDK 会自动编译,在确认编译无误后,接下来便可以开 始进行板级验证了。
10,下载验证
点击我们创建的led工程,随后点击上方菜单栏的Run,在展开的功能选项 中选择"Run Configurations..."。软件会打开如图所示界面。
接下来我们要新建一个任务,将烧录文件下载到开发板中具体步骤如下:
① 双击GDB或System Debugger新建配置任务
② 在右侧检查是否添加比特流文件和 PS初始化脚本,通常软件会自动添加,如果没有,用户可以关闭并重新打开该界面或自己手动添加。比特 流只在使用到PL资源时需要,在纯PS的设计中不需要添加比特流。
③ 确认下方四个选项都被勾选,这四个选项分别是系统复位、配置 FPGA、 PS 初始化和 PL-PS 电平转换。后两个选项通常是默认勾选的,用户需要手动勾选前两项以确保PL部分能够被正确配置。
④ 点击上方的Application切换到应用界面。
⑤ 检查.elf文件是否添加且烧录任务是否被选中。这里.elf文件由软件编译 产生,参与用户程序的运行。SDK默认情况下设置了自动编译,用户保 存设计后软件便会编译并生成.elf文件,所以当搜索不到.elf文件时检查 设计是否保存。
⑥点击"Run"开始烧录
下载完成后 即可观察板级结果
总结
在sdk开发中,sdk软件中提供了一些例程,在学习和开发的过程中可以查看学习这些例程更好的帮助我们学习和开发。