本帖最后由 正点原子运营官 于 2020-8-26 17:17 编辑
1)实验平台:正点原子领航者ZYNQ
开发板
2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/
FPGA/zdyz_linhanz.html
4)对正点原子FPGA感兴趣的同学可以加群讨论:876744900
5)关注正点原子公众号,获取最新资料
第一章Hello World实验
“Hello World!”是各种编程语言中最简单,同时也是最经典的入门实验。因此,我们将串口打印“Hello World”作为ZYNQ嵌入式系统的开篇实验,这也是我们步入ZYNQ的PS部分的始发点。通过本次实验我们将了解ZYNQ嵌入式系统的开发流程,熟悉ZYNQ嵌入式最小系统的搭建。
本章包括以下几个部分:
1.1简介
1.2实验任务
1.3硬件设计
1.4软件设计
1.5下载验证
1.1简介
首先我们来了解一下ZYNQ嵌入式系统的开发流程。
图 1.1.1 ZYNQ嵌入式系统开发流程
如上图所示,开发流程大体可以分为6步。其中step1至step4为硬件设计部分,在Vivado软件中实现;step5为软件设计部分,在SDK软件中实现;step6为功能的验证。复杂的程序还涉及Debug,这个也是在SDK软件中实施。具体每一步的操作我们会在后面详细介绍。
在简单了解ZYNQ嵌入式系统的开发流程后,接下来我们来看一下什么是ZYNQ嵌入式最小系统。ZYNQ嵌入式最小系统的概念包括以下两个方面:一、它是使系统正常工作的最小条件;二、它是其他系统建立的基础。
图 1.1.2 ZYNQ嵌入式最小系统
如图 1.1.2所示,以ARM Cortex-A9为核心、DDR3为内存,加上传输信息使用的UART串口就构成了ZYNQ嵌入式最小系统。可以看到,这个最小系统只包括了ZYNQ中的PS部分。
下面我们将按照ZYNQ嵌入式系统开发流程,一步步的搭建上图所示的最小系统。
1.2实验任务
本章的实验任务是在领航者ZYNQ开发板上搭建ZYNQ嵌入式最小系统,并使用串口打印“Hello World”信息。
1.3硬件设计
在图 1.1.1中,我们将step1至step4划分为硬件设计部分。
step1:创建Vivado工程
1-1 打开Vivado,进入Vivado界面后,点击“Quick Start”栏的 “Create Project”。然后在弹出的创建Vivado工程向导界面,点击“Next”。如下图所示:
图 1.3.1 点击创建工程
图 1.3.2 创建工程向导
1-2 进入工程命名界面。设置工程名为“hello_world”,工程路径可使用任意路径,本章我们将该工程放在F:ZYNQEmbedded_System文件夹下。注意,工程名和路径只能由英文字母、数字和下划线组成,不能包含中文、空格以及特殊字符!
确认已经勾选“Create project subdirectory”,点击“Next”,如下图所示:
图 1.3.3 设置工程信息
图 1.3.4 选择工程类型
1-3 进入图 1.3.4所示的界面,在此界面设置工程类型。此处我们选择 “RTL Project”。本次实验不需要添加源文件和约束文件,所以勾选“Do not specify sources at this
time”。勾选之后会省略后面添加源文件和约束文件的步骤,点击“Next”直接跳到器件选型界面。
1-4 器件选型界面。所选择的器件型号一定要跟领航者核心板上的ZYNQ芯片型号保持一致。领航者核心板上的ZYNQ芯片有两种型号,XC7Z010和XC7Z020。大家可以通过查看核心板上ZYNQ芯片的私印来确认所使用的芯片型号。这两个芯片主要的差异是PL部分的逻辑资源不同,PS部分相同,另外XC7Z010型号速度等级speed为“-1”,XC7Z020的为“-2”,这在器件选型的时候需要注意。此处以XC7Z020为例。
选择器件型号的方式有两种,一种是根据Parts,另一种是根据Boards,此处我们使用Parts选择器件。在Family栏里选择“Zynq-7000”, Speed栏选择“-2”,需要注意的是,在Package栏选择“clg400”。然后根据所使用的领航者核心板上的ZYNQ芯片型号,在下面的器件列表中选择“xc7z020clg400-2”,如下图所示。若是XC7Z010,相对应的器件为“xc7z010clg400-1”。
图 1.3.5 器件选型界面
选中之后,点击“Next”。
1-5 工程摘要界面。这是创建工程的最后一步,显示工程摘要信息,如图 1.3.6所示。在此界面检查前面所设置的工程名称、所选择的器件型号等信息。如果发现工程设置有误,则可以通过Back按钮返回前面的步骤,重新设置。检查无误后点击“Finish”,完成工程创建。
工程创建完成后的Vivado界面如图 1.3.7所示。
图 1.3.6 工程摘要界面
图 1.3.7 工程创建完成后的Vivado界面
step2:使用IP Integrator创建Processing System
Vivado开发套件中提供了一个图形化的设计开发工具——IP 集成器(IP Integrator),在IP集成器中可以非常方便的插入各种功能模块(IP)。它支持关键IP接口的智能自动连接、一键式IP子系统生成、实时DRC等功能,能够帮助我们快速组装复杂系统,加速设计流程。
接下来我们将在IP集成器中完成ZYNQ嵌入式系统的搭建。
2-1 在左侧导航栏(Flow Navigator)中,单击IP Integrator下的Create Block Design。然后在弹出的对话框中指定所创建的Block Design的名称,在Design name栏中输入“system”。如下图所示:
图 1.3.8 创建 Block Design
2-2点击“OK”按钮,此时Vivado界面如下图所示。注意右侧的Diagram窗口,我们将在该窗口中以图形化的方式完成设计。
图 1.3.9 Block Design界面
2-3 接下来在Diagram窗口中给设计添加 IP。点击上图中箭头所指示的加号“+”,会打开IP目录(IP Catalog)。也可以通过快捷键Ctrl + I,或者右键点击Diagram工作区中的空白位置,然后选择“ADD IP”。
2-4 打开IP目录后,在搜索栏中键入“zynq”,找到并双击“ZYNQ7 Processing System”,将ZYNQ7处理系统IP添加到设计中。
图 1.3.10 添加ZYNQ7 Processing System IP
2-5 添加完成后,ZYNQ7 Processing System模块出现在Diagram中,如下图所示:
图 1.3.11 ZYNQ7 Processing System IP
2-6 双击所添加的ZYNQ7 Processing System模块,进入ZYNQ7处理系统的配置界面。界面左侧为页面导航面板,右侧为配置信息面板。如下图所示:
图 1.3.12 ZYNQ7处理系统配置界面
下面我们简要地介绍一下页面导航面板中各个页面的作用。
在Zynq Block Design页面,显示了Zynq处理系统(PS)的各种可配置块,其中灰色部分是固定的,绿色部分是可配置的,按工程实际需求配置。可以直接单击各种可配置块(以绿色突出显示)进入相应的配置页面进行配置,也可以选择左侧的页导航面板进行系统配置。
PS-PL Configuration页面能够配置PS-PL接口,包括AXI、HP和ACP总线接口。
Peripheral IO Pins页面可以为不同的I/O外设选择MIO/EMIO配置。
MIO Configuration页面可以为不同的I/O外设具体配置MIO/EMIO。
Clock Configuration页面用来配置PS输入时钟、外设时钟,以及DDR和CPU时钟等。
DDR Configuration页面用于设置DDR控制器配置信息。
SMC Timing Calculation页面用于执行SMC时序计算。
Interrupts页面用于配置PS-PL中断端口。
2-7 配置PS的UART。点击Peripheral I/O Pins页面,出现以下IO引脚配置界面。
图 1.3.13 配置ZYNQ7 Processing System的UART
PS和外部设备之间的连接主要是通过复用的输入/输出(Multiplexed Input/Output,MIO)来实现的。PS的54个MIO引脚可以用于连接不同的外设接口,如图 1.3.13中的MIO14和MIO15,既可以配置成UART0的引脚接口,也可以配置成I2C0或CAN0的引脚接口。最终所选择的配置需要与领航者开发板的原理图相对应。
图 1.3.14 领航者核心板原理图
图 1.3.14是领航者核心板原理图的一部分。从图中我们可以看到,BANK500中的MIO14和MIO15被用作UART串口
通信的引脚,并最终与底板上的USB转串口芯片CH340连接。因此,为了实现串口通信的功能,我们需要在PS中将MIO14和MIO15配置成 UART0模块的接口引脚。
如下图所示,我们在MIO14和MIO15下点击UART0,方框的颜色会变成绿色,与此同时这两个MIO也会变成绿色。这就表明MIO14和MIO15被配置成了UART接口引脚,它们与PS中的串口
电路UART0相连接。
图 1.3.15 选中UART0
点击左侧的MIO Configuration页面,在右侧展开I/O Peripherals > UART0,可以看到更具体的引脚配置信息。其中MIO14作为RX引脚、MIO15作为TX引脚,如下图所示:
图 1.3.16 UART0的具体引脚配置
点击左侧的PS-PL Configuration页面,我们可以在这里设置UART0串口通信的波特率。在General目录下,可以看到UART0的波特率默认是115200。通过下拉按钮可以选择其他波特率,一般保持默认设置。
图 1.3.17 选择UART0的波特率
2-8 配置PS的DDR3控制器。
点击左侧的DDR Configuration页面,在右侧DDR Controller Configuration下的“Memory Part”一栏选择DDR的器件,XC7Z020的核心板选择MT41J256M16RE-125,XC7Z010的核心板选择MT41J128M16 HA-125。需要注意的是,我们在这里选择的型号并不是领航者核心板上的DDR3型号,而是参数接近的型号,或者说兼容的型号。其他的配置选项保持默认即可。
图 1.3.18 配置PS的DDR3控制器
2-9 配置PS的时钟。
点击左侧的Clock Configuration页面,该界面主要是配置ZYNQ PS中的时钟频率。比如输入时钟默认是33.33333Mhz,这与我们领航者核心板上的PS端输入时钟频率相同。对于CPU的时钟、DDR的时钟以及其它外设的时钟,我们直接保持默认设置即可。如下图所示:
图 1.3.19 配置PS的时钟
2-10 因为本实验是搭建ZYNQ的嵌入式最小系统,只需要使用ZYNQ中的PS端。因此我们将PS中与PL端交互的接口信号移除。
同样是在Clock Configuration页面,展开PL Fabric Clocks,取消勾选FCLK_CLK0,如下图所示:
图 1.3.20 去掉勾选FCLK_CLK0
点击左侧的PS-PL Configuration页面,然后在右侧展开General下的Enable Clock Resets,取消勾选其中的FCLK_RESET0_N。
另外在当前界面中展开AXI Non Secure Enablement下的GP Master AXI Interface,取消勾选其中的M AXI GP0 interface。如下图所示:
图 1.3.21 取消勾选FCLK_RESET0_N和M AXI GP0 interface
2-11 配置ZYNQ7 Processing System完成,点击“OK”。
返回到Vivado界面后,在Diagram中可以看到ZYNQ7 Processing System IP模块发生了变化,如图 1.3.22所示。 我们将其与图 1.3.11作对比可以发现,ZYNQ7 PS模块少了四个接口,这正是因为我们在配置ZYNQ7 PS的过程中移除了与PL相关的接口信号。
图 1.3.22 点击Run Block Automation
2-12 我们点击上图中箭头所指示的位置“Run Block Automation”,会弹出如下图所示的对话框:
图 1.3.23 完成对ZYNQ7 Processing System IP核的配置
在该界面中我们可以选择自动连接IP模块的接口,包括导出外部端口,甚至可以自动添加模块互联过程中所需的IP。在我们本次设计中只有一个IP模块,在左侧确认勾选processing_system7_0,然后点击“OK”。
此时ZYNQ7 PS模块引出了两组外部接口,分别是DDR和FIXED_IO,引出的接口将会被分配到ZYNQ器件具体的引脚上。大家也可以通过点击ZYNQ7 PS模块接口处的加号“+”,来展开这两组接口,观察其中都有哪些信号。如下图所示:
图 1.3.24 配置完成后的ZYNQ7 Processing System
2-12 本次实验不需要添加其它IP,直接按快捷键Ctrl+S保存当前设计。接下来点击下图箭头所指示的按钮,验证当前设计。验证完成后弹出对话框提示没有错误或者关键警告,点击“OK”,如下图所示:
图 1.3.25 验证设计
如果验证结果报出错误或者警告,大家需要重新检查自己的设计。
step3:生成顶层HDL模块
3-1 在Sources窗口中,选中Design Sources下的sysetm.bd, 这就是我们刚刚完成的Block Design设计。右键点击sysetm.bd,在弹出的菜单栏中选择“Generate Output Products”,如下图所示:
图 1.3.26 选择Generate Output Products
3-2 弹出“Generate Output Products”对话框,如下图所示:
图 1.3.27 设置Generate选项
在对话框中Synthesis Options选择Global;Run Setings用于设置生成过程中要使用的处理器的线程数,进行多线程处理,保持默认或设置为个人电脑处理器最大可使用线程数都可以,一般选择最大可使用线程数的一般。然后点击“Generate”来生成设计的综合、实现和
仿真文件。
在“Generate”过程中会为设计生成所有需要的输出结果。比如Vivado工具会自动生成处理系统的XDC约束文件,因此我们不需要手动对ZYNQ PS引出的接口(DDR和FIXED_IO)进行管脚分配。
Generate完成后,在弹出的对话框中点击“OK”。
在Sources窗口中,点击“IP Source”标签页,可以看到Generate过程生成的输出结果。
图 1.3.28 block design生成的结果
3-3 在“Hierarchy”标签页再次右键点击system.bd,然后选择“Create HDL Wrapper”。
图 1.3.29 生成顶层模块
在弹出的对话框中确认勾选“Let Vivado manage wrapper and auto-update”,然后点击“OK”。
图 1.3.30 创建顶层HDL封装
创建完成后,Design Sources结构如下图所示:
图 1.3.31 生成system_wrapper.v顶层文件
system_wrapper.v为创建的Verilog文件,箭头所指的“品”字形图标指示当前模块为顶层模块。该模块使用Verilog HDL对设计进行封装,主要完成了对block design的例化,大家也可以双击打开该文件查看其中的内容。
另外我们在图 1.3.30中勾选了“Let Vivado manage wrapper and auto-update”,这样我们在修改了Block Design之后就不需要再重新生成顶层模块,Vivado工具会自动更新该文件。
step4:生成Bitstream文件并导出到SDK
如果设计中使用了PL的资源,则需要添加引脚约束并对该设计进行综合、实现并生成Bitstream文件。由于本次实验未用到PL部分,所以无需生成Bitstream文件,只需将硬件导出到SDK即可。
4-1 导出硬件。
在菜单栏选择 File > Export > Export hardware。
图 1.3.32 导出硬件
在弹出的对话框中,因为没有生成bitstream文件,所以无需勾选“Include bitstream”,直接点击“OK”按钮。
图 1.3.33 无需勾选“Include bitstream”
在上图中,因为选择了“Exort to
”,Vivado工具会在当前工程目录下新建一个文件夹,名为“hello_world.sdk”,它是我们接下来软件开发的工作空间。
在Export Hardware的过程中,工具会将硬件以一个ZIP压缩文件的形式导出到该工作空间中,文件名为“system_wrapper.hdf”。该文件包含了我们前面所搭建的硬件平台的配置信息,其后缀名.hdf的含义为“Hardware Definition File”,即硬件定义文件。
4-2 硬件导出完成后,在菜单栏中选择File > Launch SDK,启动SDK开发环境。如下图所示:
图 1.3.34 启动SDK开发环境
在弹出对话框中,直接点击“OK”,如下图所示:
图 1.3.35 设置工作空间
到这里,我们已经完成了ZYNQ嵌入式系统的硬件设计部分。接下来需要到SDK软件中进行应用程序开发,也就是软件设计部分。
1.4软件设计
在硬件设计的最后,我们启动了软件开发环境(SDK,Software Development Kit),如下图所示:
图 1.4.1 SDK开发环境界面
SDK打开后,主页面会显示硬件描述文件system.hdf的内容。如图 1.4.1所示,system.hdf标签页显示了整个PS系统的地址映射信息。
大家应该还记得,在启动SDK之前,我们将硬件以一个ZIP压缩文件(system_wrapper.hdf)的形式导出到软件的工作空间。在SDK启动时,该文件会自动解压,大家可以在图 1.4.1的左侧看到解压后的所有文件。其中,前四个文件(ps7_init_gpl.c、ps7_init_gpl.h、ps7_init.c和ps7_init.h)包含了Zynq SOC处理系统的初始化代码,以及DDR、时钟、pll和MIO的初始化设置信息。在初始化过程中,SDK使用这些信息去配置相应的模块,使得应用程序能够在PS上运行。
step5:在SDK中创建应用工程
5-1 在菜单栏选择File > New > Application Project, 新建一个SDK应用工程。
图 1.4.2 新建应用工程
5-2 在弹出的对话框中,输入工程名“hello_world”,其它选项保持默认即可,点击“Next”。
图 1.4.3 配置工程
5-3 选择工程模版Hello World,然后点击“Finish”。
图 1.4.4 选择工程模版Hello World
5-4 SDK创建了一个hello_world应用工程和hello_world_bsp板级支持包(BSP)工程。同时工具会自动对工程进行编译,并生成ELF文件“hello_world.elf”,如下图所示:
图 1.4.5 工程创建后的界面
另外工程创建完成后,SDK主界面会打开BSP工程目录下的system.mss文件。MSS是英文Microprocessor Software Specification的缩写,即微处理器软件说明。该文件包含BSP的操作系统信息、硬件设计中各个外设的软件驱动等信息。
5-5 双击打开hello_world/src工程目录下helloworld.c文件,可以看到源代码如下:
- 1 #include
- 2 #include "platform.h"
- 3 #include "xil_printf.h"
- 4
- 5 int main()
- 6 {
- 7 init_platform();
- 8
- 9 print("Hello Worldnr");
- 10
- 11 cleanup_platform();
- 12 return 0;
- 13 }
复制代码
可以看到程序中主函数调用了3个函数,分别是init_platform()、cleanup_platform()和print()函数。我们将鼠标停留在各个函数名上,SDK就会显示该函数的声明。如果想查看函数的定义,可以按住Ctrl键不放,用鼠标点击相应的函数,就会跳转到其定义的地方。
init_platform和cleanup_platform函数定义如下:
图 1.4.6 init_platform和cleanup_platform函数定义
可以看到init_platform函数的作用是使能caches和初始化uart;cleanup_platform函数的作用是取消使能caches。实际上这两个函数在该工程中并没有启动任何作用,因为这两个函数是针对于特定平台如Microblaze的,对于我们使用的ZYNQ平台而言是不起作用的,所以main函数中只需包含第9行的print语句就可以了,出于平台的通用性和可移植性,此处我们保留这两个函数。
另外需要注意程序中打印字符串“Hello World”使用的是print()函数,而不是C语言里的printf()函数。print()函数是Xilinx定义的一个用于打印字符串的函数,调用该函数需要包含头文件“xil_printf.h”。
5-6 在我们修改并保存源文件后,SDK会自动对工程进行编译。编译进度可以在工具下方的控制台面板(Console)中进行查看,编译完成后控制台会显示信息“Finished building”,如下图所示:
图 1.4.7 编译完成
我们也可以在工具栏中点击“Build All”或通过快捷键Ctrl+B来编译工程,如下图所示:
图 1.4.8 编译工程
到这里我们已经完成了本次实验的软件设计部分。
1.5下载验证
首先我们将下载器与领航者底板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用Mini USB连接线将开发板左侧的USB_UART接口与电脑连接,用于串口通信。最后连接开发板的电源,并打开电源开关。如下图所示:
图 1.5.1 领航者ZYNQ开发板实物图
注意第一次连接领航者底板上的USB_232接口时,需要安装USB串口驱动。在开发板随附的资料中找到“6_软件资料/1_软件/CH340驱动(USB串口驱动)”文件夹,双击打开文件夹中的“SETUP.EXE”进行安装,驱动安装界面如下图所示。界面中提示INF文件为CH341SER.INF,我们不需要理会(CH341,CH340驱动是共用的),直接点安装即可。
图 1.5.2 安装USB串口驱动
step6:板级验证
6-1 在SDK软件的下方,找到SDK Terminal窗口。如果界面中没有找到该窗口,或者操作过程中把该窗口给关闭了,则可以通过在菜单栏中选择Window > Show View > Other,在Show View窗口中搜索添加SDK Terminal。
图 1.5.3 SDK软件自带的串口终端
如上图所示,在SDK Terminal窗口中点击右上角的加号“+”连接串口,并在弹出的窗口中对串口进行设置。设置的参数需要与硬件设计过程中配置的UART0保持一致,即波特率为115200,数据位为8位,停止位为1位。如下图所示:
图 1.5.4 设置UART串口
需要注意的是,在设置串口端口(Port)时,在下拉列表中可能会看到多个可选端口。我们需要选择与领航者底板上的串口所连接的端口,具体的端口号可在计算机设备管理器中查看。因为底板上使用的USB转串口芯片型号为CH340,因此在设备管理器中找到USB-SERIAL CH340所对应的端口,在我这台电脑上该端口号为COM12。如下图所示:
图 1.5.5 查看串口端口
6-2 下载程序。右键点击hello_world工程,在弹出的菜单栏中选择Run as > 1 Launch on Hardware (sysntem Debugger),如下图所示:
图 1.5.6 下载程序
6-3 下载完成后,应用程序会将字符串“Hello World”通过ZYNQ PS端的串口模块UART0发送出去。在SDK Terminal窗口可以看到上位机接收到的字符串,如下图所示:
图 1.5.7 程序运行结果
程序成功打印出了“Hello World”字符串,说明本次实验在领航者ZYNQ开发板上面下载验证成功。