正点原子 发表于 2020-10-12 10:27:46

【正点原子FPGA连载】第二章Hello World--摘自【正点原子】达芬奇之Microblaze 开发指南

本帖最后由 正点原子 于 2020-10-16 16:36 编辑

1)实验平台:正点原子达芬奇FPGA开发板
2)购买链接:https://detail.tmall.com/item.htm?id=624335496505
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz_dafenqi.html
4) 正点原子官方B站:https://space.bilibili.com/394620890
5)对正点原子FPGA感兴趣的同学可以加群讨论:876744900 点击加入:                                                                                                                     
6)关注正点原子公众号,获取最新资料





第二章Hello World


“Hello World!”实验是各种编程语言中最简单,同时也是最经典的入门实验。因此,我们将“Hello World”作为Microblaze嵌入式开发的开篇实验。这里建议大家跟着的文档一步步地进行操作,从而熟悉Microblaze嵌入式开发的设计流程,并学习各个工具的使用。
本章包括以下几个部分:
22.1简介
2.2实验任务
2.3硬件设计
2.4软件设计
2.5下载验证



2.1简介
首先我们来了解一下达芬奇开发板用MicroBlaze软核进行嵌入式系统开发的流程。

图 2.1.1 达芬奇嵌入式系统开发流程
如上图所示,开发流程大体可以分为6步。其中step1至step4为硬件设计部分,在Vivado软件中实现;step5为软件设计部分,在Vitis软件中实现;step6为功能的验证。复杂的程序还涉及Debug,这个也是在Vitis软件中实施,具体每一步的操作我们会在后面详细介绍。
在简单了解嵌入式系统的开发流程后,接下来我们来看一下什么是嵌入式最小系统。嵌入式最小系统的概念包括以下两个方面:一、它是使系统正常工作的最小条件;二、它是其他系统建立的基础。

图 2.1.2 MicroBlaze嵌入式最小系统
如图 2.1.2所示,以MicroBlaze为核心、LocalMemory(片上存储)为内存,加上传输信息使用的UART串口就构成了嵌入式最小系统。
当程序比较简单时,Local Memory可以作为程序的运行空间以及存储空间,空间大小可以根据需要设置最小8KB到最大128KB;当程序比较复杂的时候,我们也可以使用片上搭载的外部存储器(如DDR3)作为程序的运行空间以及存储空间。
AXI Interconnect IP核用于将一个(或多个)AXI存储器映射的主器件与一个(或多个)存储器映射互联。在这里我们解释一下这个术语——互联(Interconnect):互联实际上是一个开关,它管理并指挥所连接的AXI接口之间的通信。
下面我们将按照嵌入式系统开发流程,一步步地搭建上图所示的最小系统。
2.2实验任务
本章的实验任务是在达芬奇开发板上搭建基于BRAM的MicroBlaze嵌入式最小系统,并使用串口打印“Hello World”信息。
2.3硬件设计
在图 2.1.1中我们将硬件设计分为了四步,接下来我们将按照这四步进行硬件设计。
step1:创建Vivado工程
打开Vivado,进入Vivado界面后,点击“Quick Start”栏的“Create Project”。然后在弹出的创建Vivado工程向导界面,点击“Next”。如图 2.3.1和图图 2.3.2所示:

图 2.3.1 点击创建工程


图 2.3.2 创建工程向导
设置工程名为“hello_world”,工程路径可使用任意路径,本章我们将工程放在 G: /vitis_pro/hello_world文件夹下。注意,工程名和路径只能由英文字母、数字和下划线组成,不能包含中文、空格以及特殊字符!
确认已经勾选“Create project subdirectory”,点击“Next”如下图 2.3.3所示:


图 2.3.3 设置工程信息
在Prioject Type界面我们选择“RTL Project”。本次实验不需要添加源文件和约束文件,所以勾选“Do not specify sources at this time”。如图图 2.3.4所示:

图 2.3.4 选择工程类型
勾选之后会省略后面添加源文件和约束文件的步骤,点击“Next”直接跳到器件选型界面。

图 2.3.5 选择芯片型号
如图 2.3.5所示,选择器件型号的方式有两种,一种是根据 Parts,另一种是根据 Boards,此处我们使用Parts选择器件。在Family栏里选择“Artix-7”,Speed栏选择“-2”,在Package栏选择“fgg484”。然后根据所使用的芯片型号,在下面的器件列表中选择“xc7a35tfgg484-2”,然后点击“Next”。

图 2.3.6 工程摘要
如图 2.3.6所示,在工程摘要界面检查前面所设置的工程名称、所选择的器件型号等信息。如果发现工程设置有误,则可以通过“Back”按钮返回前面的步骤,重新设置。检查无误后点击“Finish”,完成工程创建。
至此我们的工程已经创建完成,接下开我们将要进行“Block Design”的设计。
Step2:使用IP Integrator创建Processing System
首先在Vivado界面左侧“Flow Nevagator”栏点击“Creat Block Design”,并在弹出提示框后,在“Design name”一栏将名称改为“system”点击“OK”,如图 2.3.7所示:

图 2.3.7 开始Block Design设计
在生成的“Diagram”页面,我们点击“+”按钮(或快捷键Ctrl+I)添加IP核,在弹出的搜索框中输入“mic”,选择“MicroBlaze”并双击该IP核,如图 2.3.8所示:

图 2.3.8 添加MicroBlaze IP核
添加“MicroBlaze”IP核后的界面如图 2.3.9所示:

图 2.3.9 添加MicroBlaze IP核后的界面
双击“microblaze_0”模块进入MicroBlaze的配置界面第一页“Welcome to Micro Blaze Configuration Wizard”,该页面提供模板选择和一般设置。

图 2.3.10 MicroBlaze 配置第一页
下面我们将简单介绍一下各个选项的功能:
Predefined Configurations:配置模板,点击Select Configuration右侧的目录框我们能够看到多个模板选项(Minimum Area、Maximum Performance等),但本次试验不需要用到模板,因此保持默认选项“Current settings”就可以。
Select Processor Implementation:选择32位或64位处理器。64位处理器将两个32位通用寄存器扩展为一个64位寄存器,提供处理64位数据的附加指令,并且可以使用最多64位地址寻址和最多4个EB指令和数据。一般情况使用32位处理器就可以了。
Select implementation optimization;用于使能面积优化功能,打开其右侧的目录,我们可以看到有PERFORMANCE、AREA和FREQUENCY三个选项表示三种优化方式,其中AREA(区域)表示三级优化,速度最慢占用资源最少;FREQUENCY(频率)表示八级优化,速度最快占用资源最多;PERFORMANCE(性能)是五级优化,速度和资源占用量在AREA和FREQUENCY两者之间,本实验我们选择PERFORMANCE。
Enable MicroBlaze Debug Module Interface:使能调试功能,一般情况下我们都开启该功能,只有在资源十分紧张的情况下才会禁止此功能。
Use Instruction and Data Caches:使用指令和数据缓存。当使用外部存储时,激活这个选项可以明显地改善性能,由于本次实验我们使用的是本地存储,该选项对实验没影响,因此不选择。
Enable Exceptions:异常功能的使能。
Enable Discrete Ports:使能软核上的独立端口。
配置完成后点击“Next”进入第二页General页面,General页面能够选择单元的选择和优化。直接保持默认就可以了,点击“Next”进入Debug页面,如图 2.3.11所示:

图 2.3.11 General页面
需要注意的是Debug页面只有我们在第一页选择了使能调试选项才会出现。
Debug页面是进行断点设置和查看点的数量。这里我们同样保持默认设置,直接点击“Next”进入下一页,Buses页面,如图 2.3.12所示。

图 2.3.12 Debug页面
如图 2.3.13所示,Buses页面能进行总线设置。Local Memory Bus Interfaces是本地内存总线接口(LMB),我们将两项都选中;AXI and ACE Interfaces是AXI和ACE接口,下拉选择AXI接口,勾选Enable Peripheral AXI Data interface用来控制外围模块(AXI数据接口是与外围接口数据交互的总线,之后所有模块都挂在这个总线上);Stream Interfaces和Other Interfaces分别用于开启Stream流接口和一些其它接口,本实验中我们直接保持默认配置就好了,配置完成后点击“OK”完成MicroBlaze的配置。

图 2.3.13 Buses页面

图 2.3.14 Run Block Automation
如图 2.3.14所示,点击左上方的“Run Block Automation”添加内存,在弹出的界面选择“Local Memory”为64KB,其余选项默认,点击“OK”。
然后会生成如图 2.3.15所示界面,该界面可以看到,软件自动生成了四个模块。clk_wiz_1模块提供系统时钟,rst_clk_wiz_1_100M是系统复位模块,用以给系统各个模块提供复位信号,mdm_1是MicroBlaze调试模块,microblaze_0_local_memory模块是片上存储模块。点击图 2.3.15中红色箭头所示的按钮,进行自动布局布线。

图 2.3.15 Run Block Automation
双击clk_wiz_1模块,进入时钟设置页面,进行时钟配置,首先点击“AUTO”按钮,将输入时钟设为50MHz,在Source目录将信号类型改为单端信号,如图 2.3.16所示:

图 2.3.16 设置输入时钟
接着切换到Output Clocks页面设置输出时钟,输出时钟设为100MHz,在Reset Type栏选择“Acitive Low”设置为低电压复位,点击“OK”如图 2.3.17所示:

图 2.3.17 设置输出时钟
clk_wiz_1模块配置完成后,可以看到clk_wiz_1模块的输入时钟变成了单端输入,复位为低电平有效。

图 2.3.18 Diagram界面
将光标移动到图 2.3.18中箭头所指示的位置,会发现光标变成了铅笔的样式。点击选中该端口,然后点击鼠标右键,在弹出的列表中选择“Make External”。如图 2.3.19所示:

图 2.3.19 Block Design连线
可以看到clk_wiz_1模块引出了一个名为“resetn”的接口,如下图 2.3.20所示:

图 2.3.20 引出的resetn接口
点击选中该接口,在左侧External Interface Properties一栏中将该接口的名称修改为“sys_rst_n”。如图 2.3.21所示:

图 2.3.21 修改接口名称
使用同样的方法,引出“clk_in1”并将引出的接口名称改为“sys_clk”。然后将“ext_rest_in”与“sys_rst_n”连接,如图 2.3.22所示:

图 2.3.22 连接复位信号
根据实验任务,我们是要用串口打印信息,因此还需添加Axi Uartlite IP核,同之前添加MicroBlaze IP核一样,点击“+”在弹出的搜索框内输入“uart”,在生成的选项中选择“Axi Uartlite”并双击添加IP核,如图 2.3.23所示:

图 2.3.23 添加Axi Uartlite IP核
添加好IP核后,双击Axi Uartlite IP核,将波特率设置为“115200”,点击“OK”如图 2.3.24所示:

图 2.3.24 设置波特率
接着点击左上方“Run Bonnection Autmation”在弹出的页面中,选中所有信号,点击“OK”进行自动连线,如图 2.3.25所示。

图 2.3.25 自动连线
连线完成后,在Diagram页面空白处右击,弹出的菜单栏选择“Regenerate Layout”按钮进行自动布局,如图 2.3.26所示:

图 2.3.26 选择自动排版
并将uart_rtl_0改为“UART”,最后的界面就是“hello_world”工程最终的Block Design连接图,如所图 2.3.27示:

图 2.3.27 Block Design连接图
从上图中可以看到,在执行了自动连接之后,工具自动添加了microblaze_0_axi_periph模块(AXI Interconnect)。

图 2.3.28 AXI互联
图 2.3.28中橙色高亮的两组信号线表明,在这个设计中,AXI互联实现了由主器件(MicroBlaze)到从器件(AXI Uartlite)一对一的连接。它也可以实现一对多、多对一以及多对多的AXI接口连接。
本次实验中,AXI Interconnect IP就实现了MicroBlaze与AXI Uartlite的互联,MicroBlaze中产生的数据能够通过AXI协议传输到AXI Uartlite模块,AXI Uartlite模块接收的数据也可以通过AXI协议传输到MicroBlaze。
接着我们点击图 2.3.29中圆圈所示的按钮进行设计验证,当弹出“Validation successful”时证明验证成功,点击“OK”。

图 2.3.29 设计验证
step3:生成顶层HDL模块
在Sources窗口中,选中Design Sources下的sysetm_bd,这就是我们刚刚完成的Block Design设计。右键点击“sysetm.bd”,在弹出的菜单栏中选择“Generate Output Products”,如图 2.3.30所示:

图 2.3.30 选择 Generate Output Products
弹出“Generate Output Products”对话框, 如图 2.3.31所示:

图 2.3.31 设置Generate选项
在对话框中Synthesis Options选择“Out of context per IP”,Run Setings用于设置生成过程中要使用的处理器的线程数,进行多线程处理,保持默认或设置为个人电脑处理器最大可使用线程数都可以,一般选择最大可使用线程数的一般。然后点击“Generate”来生成设计的综合、实现和仿真文件。
在“Generate”过程中会为设计生成所有需要的输出结果。“Generate”完成后,在弹出的对话框中点击“OK”。在Sources窗口中,点击“IP Source”标签页,可以看到Generate过程生成的输出结果。如图 2.3.32所示:

图 2.3.32 Block Design生成的结果
在“Hierarchy”标签页再次右键点击“system.bd”,然后选择“Create HDL Wrapper”。如图 2.3.33所示:

图 2.3.33 生成顶层模块
在弹出的对话框中确认勾选“Let Vivado manage wrapper and auto-update”,然后点击“OK”。如图 2.3.34所示:

图 2.3.34创建顶层HDL封装
创建完成后,Design Sources结构。如图 2.3.35所示:

图 2.3.35 生成 system_wrapper.v 顶层文件
system_wrapper.v为创建的Verilog文件,箭头所指的“品”字形图标指示当前模块为顶层模块。该模块使用Verilog HDL对设计进行封装,主要完成了对Block Design的例化,大家也可以双击打开该文件查看其中的内容。在以后的设计中,如果设计修改了Block Design导致模块端口有变化,就需要重新执行“Generate Output Products”和“Create HDL Wrapper”,重新生成顶层模块。
step4:生成Bitstream文件并将硬件信息文件导出到Vitis
点击source目录下的“+”,在弹出的界面选择“Add creat constraints”,点击“Next”进入“Add or creat Constraints”界面,开始添加XDC管脚约束文件。如图 2.3.36所示:

图 2.3.36 添加管脚约束
在“Add or creat Constraints”界面首先点击“Creat File”,在弹出的“Creat Constraints File”界面将“File name”设置为“system_wrapper”,然后点击“OK”,再点击“Finish”按钮,完成XDC文件创建。如图 2.3.37所示:

图 2.3.37 创建XDC文件
在source目录下双击“system_wrapper.xdc”文件夹,并在右侧弹出的空白界面添加管脚约束。如图 2.3.38所示:

图 2.3.38 打开管脚约束文件夹
添加完管脚约束后,点击保存图标,如图 2.3.39所示:

图 2.3.39 添加管脚约束文件
也可以直接拷贝下列约束语句:
create_clock -period 20.000 -name sys_clk
set_property PACKAGE_PIN R4
set_property IOSTANDARD LVCMOS33
set_property IOSTANDARD LVCMOS33
set_property PACKAGE_PIN U2

set_property IOSTANDARD LVCMOS33
set_property IOSTANDARD LVCMOS33
set_property PACKAGE_PIN U5
set_property PACKAGE_PIN T6
点击左侧“Flow Nevigator”目录下的“Generater Bitstream”弹出提示框后点击“OK”开始生成比特流。如图 2.3.40所示:

图 2.3.40 生成比特流
编译完毕生成比特流之后,紧接着导出硬件,在菜单栏依次点击“File->Export->Export hardware”。

图 2.3.41 导出硬件
在如下图弹出的对话框中,勾选“Include bitstream”,在导出路径最后加入“/vitis”,请记住此路径,直接点击“OK”按钮。如图 2.3.42所示:

图 2.3.42 勾选Include bitstream
此时软件就会在路径下生成一个vitis文件夹,vitis就是此后软件设计的工作空间。在该文件夹下可以看到导出的system_wrapper.xsa文件,这个文件就包含了Vivado硬件设计的信息,供软件开发人员使用。

图 2.3.43 生成硬件平台
硬件导出完成后,在菜单栏中依次点击“Tools->Launch Vitis”,启动Vitis开发环境。如图 2.3.44所示:

图 2.3.44 启动Vitis开发环境
在弹出对话框中,点击“Browse…”,选择之前生成的vitis文件夹,不勾选“Use this as the default and do not ask agian”,点击“Launch”,即启动软件设计环境Vitis。如图 2.3.45所示:

图 2.3.45 设置工作空间
2.4软件设计
在硬件设计的最后,我们启动了软件开发环境Vitis。在菜单栏依次点击“File->New->Application Project”或点击下图红框,新建一个Vitis应用工程,如图 2.4.1所示。在弹出的对话框中,输入工程名“hello_world”,其他默认,点击“Next”。如图 2.4.2所示:

图 2.4.1 创建工程

图 2.4.2 输入工程名称
点击“Create a new platform hardware(XSA)”,软件提供了一些板卡的硬件平台以供选择,但对于我们自己的硬件平台需要手动添加,点击“+”,选择上小节图 2.3.43中的“system_wrapper.xsa”文件,即可成功添加我们自己的硬件平台,点击“Next”。如图 2.4.3所示:

图 2.4.3 选择添加硬件平台
CPU默认选择“microblaze_0”,OS选择“standalone”,语言选择“C”。点击“Next”。如图 2.4.4所示:

图 2.4.4 硬件平台配置
选择工程模版Hello World,然后点击“Finish”。

图 2.4.5 选择工程模版Hello World
此时,生成两个工程即APP工程和硬件平台Platfrom工程。如图 2.4.6所示:

图 2.4.6生成两个工程
点击展开硬件平台Platfrom工程“system_wrapper”,双击platform.spr即可看到Platform对应生成的BSP工程(Board Support Package板级支持包),在这里可以对BSP进行配置,里面包含了用于应用程序开发的驱动信息。如图 2.4.7所示:

图 2.4.7 板级支持包
双击打开 hello_world/src工程目录下helloworld.c文件,源代码如下:
1#include <stdio.h>
2#include "platform.h"
3#include "xil_printf.h"
4
5
6int main()
7{
8      init_platform();
9
10   print("Hello World\n\r");
11
12   cleanup_platform();
13   return 0;
14}
可以看到程序中主函数调用了3个函数,分别是init_platform()、cleanup_platform()和print()函数。我们将鼠标停留在各个函数名上,Vitis就会显示该函数的声明。
另外需要注意程序中打印字符串“Hello World”使用的是print()函数,而不是C语言里的printf()函数。print()函数是Xilinx定义的一个用于打印字符串的函数,调用该函数需要包含头文件“xil_printf.h”。
如果想查看函数的定义,可以按住Ctrl键不放,用鼠标点击相应的函数,就会跳转到其定义的地方。
init_platform和cleanup_platform函数定义如下:

图 2.4.8 init_platform 和 cleanup_platform 函数定义
可以看到init_platform函数的作用是使能caches和初始化uart;cleanup_platform函数的作用是取消使能caches。对于软件部分我们不需要做修改,直接使用官方的实例就可以了。
接下来编译工程,选中APP工程“hello_world_system”,右键“Build Project”或点击图中“锤子”按键,进行工程编译。如图 2.4.9所示:


图 2.4.9 编译工程
工程编译结束后,成功生成elf文件,在Vitis软件右下Console信息栏中会打印如图 2.4.10信息:

图 2.4.10 生成elf文件
至此,硬件和软件设计均已完成。
另外,可以调整Vitis文本中的字体大小等信息,以便开发。鼠标点入一个文本内如main.c,右键选择“Perferences”,如图 2.4.11所示:

图 2.4.11 Perferences
依据图 2.4.12所示,逐级点击展开菜单栏,选中“Text Font”,点击“Edit”。

图 2.4.12 点击Edit
在图 2.4.13界面中,即可选择合适的参数,最后点击确定。

图 2.4.13 字体设置
回到图 2.4.12后,点击右下角的“Apply and Close”即可。
此时发现文本内的字体已经发生了改变。
2.5下载验证
首先我们将下载器与达芬奇开发板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用USB连接线将开发板USB_UART接口与电脑连接,用于串口通信。最后连接开发板的电源,并打开电源开关。如图 2.5.1所示:

图 2.5.1 达芬奇开发板连接图
注意第一次连接达芬奇开发板上的USB_UART接口时,需要安装USB串口驱动。在开发板随附的资料中找到“6_软件资料/1_软件/CH340驱动(USB串口驱动)”文件夹,双击打开文件夹中的“SETUP.EXE”进行安装,驱动安装界面如下图所示。界面中提示INF文件为CH341SER.INF,我们不需要理会(CH341,CH340驱动是共用的),直接点安装即可。

图 2.5.2 安装 USB 串口驱动
在Vitis软件的下方,找到Terminal窗口。如果界面中没有找到该窗口,或者操作过程中把该窗口给关闭了,则可以通过在菜单栏中依次点击“Window->Show view->Terminal文件夹->Terminal”,最后点击“Open”,接口成功添加Terminal窗口。

图 2.5.3 Vitis软件自带的串口终端

图 2.5.4 Vitis软件自带的串口终端
      点击图 2.5.5所示,进行串口设置界面:

图 2.5.5串口设置
按照图 2.5.6对串口进行设置,选择串口“Serial Terminal”,设置的参数需要与硬件设计过程中配置的axi_uartlite_0保持一致,即波特率为 “115200”,数据位为8位,停止位为1位。点击“OK”后,如图 2.5.7所示,证明串口连接成功。

图 2.5.6 串口设置

图 2.5.7 串口连接成功
需要注意的是,在设置串口端口(Port)时,在下拉列表中可能会看到多个可选端口。我们需要选择与达芬奇开发板上的串口所连接的端口,具体的端口号可在计算机设备管理器中查看。因为开发板上使用的USB转串口芯片型号为CH340,因此在设备管理器中找到USB-SERIAL CH340所对应的端口,在我这台电脑上该端口号为COM7。如图 2.5.8所示:

图 2.5.8查看串口端口
在应用工程hello_world上右击,选择“Run As”,然后选择最后一项“Run Confagurations…”,如图 2.5.9所示:

图 2.5.9 Run Configuration
在Run Configuration页面点击“Debugger_hello_word-GDB”,点击菜单栏“Target Setup”。其中,“Hardware Platform”为硬件平台,Bitstream File为加载的bit流文件。勾选“Reset entire system”(系统复位)和“Program FPGA”(下载FPGA)然后点击“Run”开始下载程序,如图 2.5.10所示。

图 2.5.10 下载程序
下载完成后,应用程序会将字符串“Hello World”通过串口模块发送出去。在Terminal 窗口可以看到上位机接收到的字符串,如图 2.5.11所示:

图 2.5.11 成功打印字符串
程序成功打印出了“Hello World”字符串,说明本次实验在达芬奇开发板上面下载验证成功。



页: [1]
查看完整版本: 【正点原子FPGA连载】第二章Hello World--摘自【正点原子】达芬奇之Microblaze 开发指南