ZYNQ 有多种启动方式可以选择,除了之前介绍的从QSPI FLASH 的方式来启动外,还可以让系统从TF 卡的方式来启动,本文将通过一个EMIO 点LED 灯的方式来演示 TF 卡的启动过程。
本文在 vivado2018.3版本上 演示, 其他版本请自行研究
(备注 此章节内容适用于 Smart ZYNQ SP和SL 版的板子,如果是Smart ZYNQ 标准版请看对应板子目录)
1 ZYNQ启动流程
1.首先了解ZYNQ的启动过程, ZYNQ的启动过程以 ARM核为主, 上电后 硬件先读取ARM核PS端的IO 以确定 系统从NAND ,QSPI ,SD Card还是 JTAG 启动系统。
具体的启动方式如下图所示, 我们的最小系统板只有 QSPI 和TF的硬件,所以只需要关注QUAD-SPI ,SD,JTAG 三种启动方式就好。也就是看系统上电瞬间MIO5和MIO4两个管脚的电平状态,用来区分不同的上电启动方式。
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-52.png)
在电路上 设计的过程中已将MIO5和MIO4分别接到了 拨动开关上了,也就是按照拨动开关在上电瞬间的状态即可控制系统的启动方式 ,具体可参考板子上的丝印标注
将拨码开关调整到如图所示状态 ,此时如果TF卡上有可执行程序,断电重启后,系统将会从TF卡启动了
![](http://www.hellofpga.com/wp-content/uploads/2023/01/image-76.png)
2 软件部分配置
2.1 创建一个BLOCK设计
1)IP INTEGRATOR→Create Block Design,在弹出的对话框中输入设计名,最后点击“OK”,如下图所示
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-1.png)
2)在右侧的窗口里 ,点击加号,在选择框里搜索ZYNQ,并找到ZYNQ7 PROCESSING SYSTEM ,双击并打开
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-2.png)
3)软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-3.png)
4)依次在弹窗里找到DDR Configuration→DDR Controller Configuration→DDR3,在Memory Part下拉菜单中根据自己板子上的DDR来选择相应的DDR3,本实验所用到型号:MT41K256M16RE-125,数据位宽选择16bit 最后点击“OK”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2023/01/image-70.png)
5)在PS的MIO配置选项的GPIO栏里,增加两路EMIO(因为本次测试的是两个,如果需要增加按键或者其它IO 这里可以对应的调整(这里两路GPIO是为了点亮LED灯看效果演示用的,非TF启动必须)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-41.png)
6). 重要的一步 MIO Configuration 中 使能SD 0的功能,这一步是 TF卡启动的关键设置
![](http://www.hellofpga.com/wp-content/uploads/2022/03/image-5.png)
7)最后 点击“Run Block Automation”如下图所示。在弹出的选项中保持默认,点击“OK”,即可完成对ZYNQ7 Processing System的配置
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-43.png)
8)将刚才添加EMIO GPIO 引出 右键GPIO_0—->Make External
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-44.png)
9)用线将M_AXI_GP0_ACLK与 FCLK_CLK0连接起来
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-47.png)
10)source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-12.png)
11)在弹出的对话框里保持默认
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-13.png)
12)软件自动为我们生成HDL文件
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-14.png)
2.2创建约束文件,并且定义管脚
1)Add Source → Add or create constraints 点Next
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-15.png)
因为这个项目没有创建过约束文件 所以这里创建一个约束文件,并在File name 里设置约束文件的名称,并且点击FINISH 完成约束文件的创建
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-16.png)
2)Sources → Constraints 里找到刚才创建的约束文件 双击并打开该XDC约束文件
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-17.png)
在约束文件里面复制下面代码来对输出的GPIO进行管脚(所有的管脚转接板上丝印都有实际标注对应的IO)
set_property IOSTANDARD LVCMOS33 [get_ports GPIO_0_0_tri_io[0]] set_property IOSTANDARD LVCMOS33 [get_ports GPIO_0_0_tri_io[1]] set_property PACKAGE_PIN P20 [get_ports GPIO_0_0_tri_io[0]] set_property PACKAGE_PIN P21 [get_ports GPIO_0_0_tri_io[1]]
3.SDK程序编写
1)File→Export→Export hardware…,在弹出的对话框中勾选“include bitstream”,点击“OK”确认,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-20.png)
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-24.png)
2)File→Lauch SDK,在弹出的对话框中,保存默认,点击“OK”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-21.png)
系统将自动打开SDK开发环境
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-22.png)
3)新建一个工程 file→new→Application Project,来新建一个“Application Project”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-23.png)
4)在新建工程名中输入自己的工程名称,点击NEXT
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-37.png)
5)选择空工程,点击完成FINISH
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-26.png)
6) 在工程中添加main.c文件 src—>New—>Source File 如下图所示
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-48.png)
7)在弹出的窗口中填入main.c 并且保存
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-49.png)
8).打开刚才创建的main.c
然后 写入以下代码(代码是在 例程的基础上进行精简的) 有一个地方值得注意 EMIO的 IO口编号 是从54开始的,也就是我VIVADO 下创建的 EMIO端口,在PS端都是从54-55-56 依次排序的(小贴士 小于54的是MIO 也就是芯片PS的硬件IO口)
#include "xparameters.h" #include "xgpiops.h" #include "xstatus.h" #include "xplatform_info.h" #define LED1 54 #define LED2 55 #define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID XGpioPs Gpio; void Gpio_Init(void){ XGpioPs_Config *ConfigPtr; ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID); XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr); XGpioPs_SetDirectionPin(&Gpio, LED1, 1); XGpioPs_SetOutputEnablePin(&Gpio, LED1, 1); XGpioPs_SetDirectionPin(&Gpio, LED2, 1); XGpioPs_SetOutputEnablePin(&Gpio, LED2, 1); XGpioPs_WritePin(&Gpio, LED1, 0); XGpioPs_WritePin(&Gpio, LED2, 0); } #define LED_DELAY 10000000 volatile int Delay; int main(void) { Gpio_Init(); while(1){ XGpioPs_WritePin(&Gpio, LED1, 0); XGpioPs_WritePin(&Gpio, LED2, 1); for (Delay = 0; Delay < LED_DELAY; Delay++); XGpioPs_WritePin(&Gpio, LED1, 1); XGpioPs_WritePin(&Gpio, LED2, 0); for (Delay = 0; Delay < LED_DELAY; Delay++); }; return 0; }
4.下载到板子上进行验证
选中工程中的硬件平台,并点击右键→Program FPGA,在弹出的对话框中选择默认,点击“program”,完成FPGA PL部分的Program工作
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-42.png)
2)选中我们生成的GPIO工程 展开绿色箭头(RUN)右边的图标,选择Run As→1 Launch on Hardware(System Debugger)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-50.png)
可以看到板子上的两个LED灯在交替着闪烁
备注 :如果 RUN 的时候弹出错误 可以按照下面的操作 进行设置 再进行DEBUG
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-51.png)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-39.png)
之后点 APPLY 然后 再选择Run As→1 Launch on Hardware(System Debugger)看是否下载成功(如果仍然不行,请对板子进行断电后重试,一般发生这种问题的原因是因为debug的时候跟之前运行的程序产生冲突导致的)
5. 创建TF卡的 镜像文件
创建镜像文件分两步1. 创建FSBL模块,2.创建image(boot.bin)文件
在zynq上运行程序的时候,加载过程中肯定需要用到一个文件,那就是fsbl,是zynq启动第一阶段的加载程序,经过了fsbl这一阶段,后面系统才能够运行裸奔程序或者是引导操作系统的u-boot
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-60.png)
1)创建FSBL:在SDK中新建工程如下
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-61.png)
设置工程名fsbl,点next选择FSBL模板
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-62.png)
![](http://www.hellofpga.com/wp-content/uploads/2021/12/image-2.png)
2)创建TF卡镜像文件
BOOT.bin由 fsbl.elf文件 vivado生成的fpga 的bit文件 app工程的elf文件(这里为led工程的elf)三个文件组成。在生成image的时候要分别填入三个文件的路径, 这里也有个偷懒的方法,就是在点 create boot image之前先选中 我们的APP工程,这样系统会自动为我们添加路径。如下所示
a) 先选中 我们的APP工程目录,这里是LED_CODE( 不是FSBL 也不是BSP 和 platform) 如果一开始已经被选中了,请先用鼠标选择上下任意一个目录,再选择回APP目录,否则路径可能不自动加载
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-63.png)
b) 点xilinx –>create boot image
![](http://www.hellofpga.com/wp-content/uploads/2021/12/image-3.png)
在界面里分别设置 boot.bin的输出路径,以及生成boot.bin需要的三个文件的路径(这里有一个偷懒的方法,就是在点下Create Boot Image 之前先选中我们的APP工程),如下图所示,如果没有出现三个文件的路径,请重试上一步。 如果有三个文件路径,则直接点create image生成镜像
![](http://www.hellofpga.com/wp-content/uploads/2023/04/image-26-1024x550.png)
6. 验证SD TF 卡启动
- 1)在刚才create boot image 中的 ouput bif中 和boot.bin文件的导出文件夹中,复制出这两个文件到空的TF卡中 (切记 需要格式化成FAT32格式)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-71.png)
2. 将TF 卡插入到 主板的卡槽中
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-73.png)
3. 将板子设置成 TF卡启动模式 如下图所示
![](http://www.hellofpga.com/wp-content/uploads/2023/01/image-77.png)
4.重新断电再上电(或者按下POR_RST键), 正常情况下 系统的两个指示灯开始交替闪烁,说明TF卡启动成功了
如果启动不成功,有可能是以下几种情况
a. TF卡的 格式不对 必须是FAT32格式
b. TF卡有多个分区,需要统一成一个再进行格式化,(用老毛桃等工具做过启动盘的会出现这种情况)
c. TF卡不支持,尝试更换不同品牌 不同容量大小的TF卡, 大容量,越高速的TF卡的兼容性越差(PS 我这边测试 128g的闪迪高速盘也能支持)
完整的工程如下