ZYNQ_SDK HelloWorld实验
了解 ZYNQ 嵌入式系统的开发流程
熟悉 ZYNQ 嵌入式最小系统的搭建
型号
- xc7z020clg484-1
简介
ZYNQ 嵌入式系统的开发流程
- step1 至 step4 为硬件设计部分,在 Vivado 软件中实现
- step5 为软件设计部分,在 SDK 软件中实现
- step6 为功能的验证
ZYNQ 嵌入式最小系统
- 使系统正常工作的最小条件
- 是其他系统建立的基础
- 以 ARM Cortex-A9 为核心、DDR3 为内存,加上传输信息使用的 UART 串口就构成
了 ZYNQ 嵌入式最小系统
只包括了 ZYNQ 中的 PS 部分
实施过程
硬件设计
step1 创建Vivado工程
勾选 Do not specify sources at this time 后会省略后面添加源文件和约束文件的步骤
直接跳到器件选型界面
step2 使用IP Integrator 创建Porcessing System
Vivado 开发套件中提供了一个图形化的设计开发工具——IP 集成器(IP Integrator),在 IP 集成器中可以非常方便的插入各种功能模块(IP)
- 支持关键 IP 接口的智能自动连
- 一键式 IP 子系统生成
- 实时 DRC
Create Block Design --> 指定名称
添加IP核 ( 快捷键 : Ctrl + I
搜索: zynq, 添加ZYNQ7 Processing System 的 ZYNQ7处理系统IP
双击模块,进入配置界面
左侧为页面导航面板,右侧为配置信息面板
页面导航面板中各个页面的作用
- Zynq Block Design
显示了zynq处理系统 (PS) 的各种可配置块,灰色部分是固定的,绿色部分是可以配置的,按照工程实际需要配置。可以单击进入配置页面配置,也可以选择左侧的页面导航面板进行配置 - PS-PL Configuration
配置PS-PL接口,包括AXI, HP, ACP总线接口 - Peripheral IO Pins
为不同的IO 外设选择MIO/EMIO配置 - MIO Configuration
为不同的I/O外设具体配置MIO/EMIO - Clock Configuration
用来配置PS输入时钟,外设时钟,以及DDR 和 CPU时钟 - DDR Configuration
设置DDR控制器配置信息 - SMC Timing Calculation
执行SMC时序计算 - Interrupts
配置PS-PL中断端口
配置PS的UART
点击 Peripheral I/O pins页面 --> I/O 引脚配置界面
PS和外部设备zhi’jian之间的连接主要是通过复用的输入/输出 ( Multiplexed Input/Output , MIO) 来实现的。
PS的54个MIO引脚可以用于连接不同的外设接口。
最终所选择的配置要与实际的开发板原理相对应
在 PS 中将 MIO50和 MIO51 配置成 UART0 模块的接口引脚
在MIO50 和 MIO51下点击UART0, 方框的颜色会变绿,表明MIO50和MIO51被配置成了UART接口引脚, 与PS中的串口电路UART0相连接
点击左侧的MIO Configuration 页面,在右侧展开I/O Periphal > UART0 ,可以看到更具体的引脚配置信息。
- MIO50 RX
- MIO51 TX
点击左侧的PS-PL Configure 页面,可以设置UART0串口通信的波特率。
在General 目录下,可以看到默认波特率为115200, 可以选择其他波特率
配置PS的DDR3控制器
点击DDR Configuration 页面, 在DDR Controller Configuration 下的 Memory Part一栏选择DDR的器件,其他参数保持默认
开发板DDR型号: MT41K256M16 RE-15E
配置PS的时钟
点击Clock Configuration 页面,主要是配置ZYNQ PS中的时钟。
输入时钟默认是 33.33333Mhz。
对于CPU时钟,DDR的时钟以及其他外设的时钟,保持默认设置
去除PS中与PS端交互的接口信号
ZYNQ嵌入式最小系统,只需要使用ZYNQ中的PS端,因此将PS中与PL端交互的接口信号移除
Clock Configuration --> PL Fabric Clocks 取消勾选 FCLK_CLK0
点击PS-PL Configuration 页面, 展开General 下的Enable Clock Resets ,取消勾选FCLK_RESET0_N
此外,在当前界面中展开AXI Non Secure Enablement 下的 GP Master AXI Interface ,取消勾选其中的M AXI GP0 Interface。
配置ZYNQ7 Processing System 完成,点击OK
返回Vivado 界面后,在Diagram 中可以看到ZYNQ7 Processing System IP模块少了四个接口,正是移除了与PL相关的接口信号。
点击Run Block Automation
选择自动连接IP模块的接口,包括导出外部端口,甚至可以自动添加模块互联过程中所需要的IP
本次设计中只有一个IP模块,在左侧确认勾选processing system7_0
此时ZYNQ7 PS 模块引出了两组外部接口,分别是DDR 和 FIXED_IO, 引出的接口将会分配到ZYNQ器件的具体引脚上。
可以通过PS模块接口处的+号,来展开这些接口,观察其中的信号。
保存当前设计 ( Ctrl + S )
不需要添加其他IP,直接保存当前设计。
验证当前设计
验证完成后弹出对话框提示没有错误或者关键警告
step3 生成顶层HDL设计
在Sources 窗口中,选中Design Sources 下的sytem.bd 就是刚刚完成的Block Design设计
.bd 文件就是Block Design 设计文件
右击system.bd, 选择Generate Output Products
弹出Generate Output Products对话框
在Synthesis Options 中选择Global
Run Setings 用于设置生成过程中要使用的处理器的线程数,进行多线程处理,保持默认或者设为个人电脑处理器最大可以使用线程数。
Generate --> 生成设计的综合、实现和仿真文件
在Sources窗口中,点击IP Sources 标签页,可以看到Generate 过程中生成的输出结果
在Hierarchy 标签页再次右击system.bd, 然后选择Create HDL Wrapper
在弹出的对话框中确认勾选 Let Vivado manage wrapper and auto-update
创建完成后,Design Sources 结构如下
system_wrapper.v 为创建的verilog文件,前面的品 字形图形指示当前模块为顶层模块。
该模块使用Verilog HDL对设计进行封装,主要完成了block design 的例化。
勾选 "Let vivado manage wrapper and auto- update"后, 修改了Block Design之后不需要再重新生成顶层模块,Vivado 工具会自动更新该文件。
step4 生成BitStream 文件并导出到SDK
如果设计中使用了PL的资源,则需要添加引脚约束并对该设计进行综合、实现并生成Bitstream 文件。
本实验没有用到PL部分,所以无需生成Bitstream 文件,只需要将硬件导出到SDK即可。
导出硬件 菜单栏–> File --> Export --> Export hardware
在弹出的对话框中,因为没有生成bitstream 文件,所以无需勾选 Include bitstream 文件
因为选择了 Export to < Local to Project > Vivado 工具会在当前工程目录下新建一个文件夹名为hello_world.sdk, 就是接下来的开发的工作空间。
在Export Hardware过程中, 工具会将硬件以一个ZIP压缩文件的形式导出到该工作空间中,文件名为system.wrapper.hdf, 该文件包含了前面所搭建的硬件平台的配置信息,后缀名为.hdf的含义为Hardware Definition File
硬件导出完成后,在菜单栏中选择File > Launch SDK ,启动SDK 开发环境
到这里,已经完成了ZYNQ嵌入式系统的硬件设计部分,接下来需要到SDK软件中进行应用程序的开发–> 软件设计部分
软件设计
启动软件开发环境(SDK,Software Development Kit)
SDK打开后, 主页面会显示硬件描述文件system.hdf的内容, system.hdf标签页显示了整个PS系统的地址映射信息
在启动SDK之前,将硬件以一个ZIP压缩文件(system_wrapper.hdf) 的形式导出到软件的工作空间,在SDK启动时, 该文件会自动解压。
解压后的文件中的前四个文件( ps7_init_gpl.c ,ps7_init_gpl.h, ps7_inti.c, ps7_init.h) 包含了ZynqSOC处理系统初始化代码, 以及DDR, 时钟,PLL和MIO的初始化设置信息。
在初始化过程中,SDK利用这些信息去配置相应的模块, 使得应用程序能够在PS上运行。
step5 在SDK中创建应用程序
在菜单栏选择File > New >Application Project , 新建一个SDK应用程序
在弹出的对话框中,输入工程名,其他选项保持默认, 单击Next
选择工程模版 Hello World,然后点击“Finish”
SDK创建了一个HelloWorld应用工程和HelloWorld_bsp板级支持包(BSP)工程同时工具自动对工程进行编译,并生成ELF文件HelloWorld.elf
工程创建完成后, SDK主界面会打开BSP工程目录下的system.mss文件,MSS是英文Microprocessor Software Specification 的缩写, 即微处理器软件说明,该文件包含了BSP的操作系统的信息、硬件设计中各个外设的软件驱动等信息。
打开helloworld.c文件
/* * helloworld.c: simple test application * * This application configures UART 16550 to baud rate 9600. * PS7 UART (Zynq) is not initialized by this application, since * bootrom/bsp configures it to baud rate 115200 * * ------------------------------------------------ * | UART TYPE BAUD RATE | * ------------------------------------------------ * uartns550 9600 * uartlite Configurable only in HW design * ps7_uart 115200 (configured by bootrom/bsp) */ #include <stdio.h> #include "platform.h" #include "xil_printf.h" int main() { init_platform(); print("Hello World\n\r"); cleanup_platform(); return 0; }
可以看到主函数中调用了3个函数
- init_platform()
- cleanup_platform()
- print()
将鼠标停留在各个函数名上,SDK 就会显示该函数的声明
如果想查看函数的定义,可以按住 Ctrl 键不放,用鼠标点击相应的函数,就会跳转到其定义的地方。
init_platform 函数的作用是使能 caches 和初始化 uart
cleanup_platform 函数的作用是取消使能 caches
实际上这两个函数在该工程中并没有启动任何作用,因为这两个函数是针对于特定平台如Microblaze 的,对于我们使用的 ZYNQ 平台而言是不起作用的
所以 main 函数中只需包含第 9 行的 print语句就可以了,出于平台的通用性和可移植性,此处保留这两个函数。
程序中打印字符串“Hello World”使用的是 print()函数,而不是 C 语言里的 printf()函数。print()函数是 Xilinx 定义的一个用于打印字符串的函数,调用该函数需要包含头文件“xil_printf.h”。
在修改并保存源文件后,SDK会自动对工程进行编译,编译进度可以在工具下方的控制台面板(Console)中查看。编译完成后,控制台会显示信息 Finished building
也可以在工具栏点击Build All 或者通过快捷键Ctrl + B来编译工程
至此已完成软件设计部分
下载验证
step6 板级验证
在 SDK 软件的下方,找到 SDK Terminal 窗口。
如果界面中没有找到该窗口,或者操作过程中把该窗口给关闭了,则可以通过在菜单栏中选择 Window > Show View > Other,在 Show View 窗口中搜索添加SDK Terminal。
在SDK Terminal 窗口中点击+号连接串口,在弹出的窗口中对串口进行设置。
下载程序,右击hello_world工程,在弹出的菜单栏中选择 Run as > 1 Launch on Hardware (sysntem Debugger)
下载完成后,应用程序会将字符串“Hello World”通过 ZYNQ PS 端的串口模块 UART0 发送出去。
在 SDK Terminal 窗口可以看到上位机接收到的字符串
参考内容
正点原子–2_启明星ZYNQ之嵌入式SDK开发指南_V2.0