告别Jtag!手把手教你将ZYNQ PL端LED程序烧写到QSPI Flash自启动
告别JTAG!ZYNQ PL端程序固化到QSPI Flash全流程实战指南
当你完成了一个基于ZYNQ PL端的LED闪烁设计并通过JTAG验证后,下一步自然希望它能够独立运行——无需连接电脑和调试器,上电即工作。这种需求在产品开发中极为常见,但很多工程师在从原型到产品的转化过程中会遇到各种"坑"。本文将带你完整走通从Vivado生成bit文件到QSPI Flash编程的全流程,特别针对不同Vivado版本的关键差异给出明确解决方案。
1. 环境准备与基础概念
在开始实际操作前,我们需要明确几个关键概念和准备工作:
- PL(Programmable Logic)与PS(Processing System):ZYNQ芯片包含这两部分,即使我们只使用PL,也需要配置最小化的PS系统来协助启动
- BootROM与FSBL(First Stage Boot Loader):ZYNQ上电后首先执行BootROM中的代码,它会加载FSBL,再由FSBL加载我们的PL配置
- Boot Image组成:一个完整的启动镜像包含FSBL、bit文件(PL配置)和可选的用户应用程序
所需工具清单:
- Vivado设计套件(本文以2019.1版本为例,同时说明新旧版本差异)
- 对应的SDK工具
- ZYNQ开发板(需支持QSPI Flash)
- USB转JTAG编程器(如Digilent JTAG-HS2)
提示:建议在开始前确认你的开发板QSPI Flash型号,常见的有Spansion S25FL128S或Micron N25Q128A,这会影响后续的配置参数。
2. 生成PL配置bit文件
首先确保你的PL设计已经完成综合、实现并生成bit流文件。这一步骤与常规JTAG调试流程一致,但有几点需要特别注意:
- 在Vivado中打开已完成的工程
- 确认约束文件中的时钟和复位信号配置正确
- 运行
Generate Bitstream,等待生成完成
关键检查点:
- 生成的bit文件大小应该与你的设计复杂度匹配
- 检查Timing Summary确保没有时序违例
- 确认bit文件生成路径(通常位于
<project>.runs/impl_1目录)
# 如果需要通过TCL命令生成bit文件,可以使用以下命令 launch_runs impl_1 -to_step write_bitstream -jobs 4 wait_on_run impl_13. 创建最小化PS系统
即使我们只使用PL,也需要配置一个最小化的PS系统来协助启动过程。以下是具体步骤:
3.1 创建Block Design
- 在Vivado中新建或打开Block Design
- 添加ZYNQ Processing System IP核
- 双击IP核进行基本配置:
- 在
PS-PL Configuration中关闭所有PL接口(因为我们只使用PL) - 在
Peripheral I/O Pins中启用QSPI Flash控制器 - 在
Clock Configuration中设置合适的输入时钟频率
- 在
3.2 配置QSPI Flash参数
这一步至关重要,错误的配置会导致无法正常启动:
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| QSPI总线模式 | Single或Dual | 根据Flash型号选择 |
| Flash时钟频率 | 50-100MHz | 保守起见可从低频率开始 |
| 连接方式 | 1-bit或2-bit | 与硬件设计匹配 |
3.3 生成硬件平台
- 验证并保存Block Design
- 在Sources面板右键点击设计,选择
Create HDL Wrapper - 生成输出产品(Generate Output Products)
- 导出硬件(Export Hardware),勾选
Include bitstream
4. 生成FSBL与Boot Image
4.1 创建FSBL工程
- 启动Vivado SDK(File → Launch SDK)
- 在SDK中创建新的Application Project
- 选择模板为
Zynq FSBL - 编译生成FSBL.elf文件
注意:Vivado 2019.1及以后版本对FSBL处理有变化,如果遇到问题可以尝试以下方法:
- 手动修改
xfsbl_config.h中的FSBL_DEBUG_DETAILED选项- 确保
FSBL_PERF宏定义正确
4.2 合成Boot Image
- 在SDK菜单中选择
Xilinx → Create Boot Image - 添加以下三个文件并按顺序排列:
- FSBL.elf
- 你的bit文件
- (可选)用户应用程序.elf
- 设置输出路径和文件名(默认为BOOT.bin)
文件顺序必须严格遵循:
- FSBL
- bit文件
- 应用程序(如果有)
# 也可以通过bootgen工具命令行生成 bootgen -image boot.bif -arch zynq -o BOOT.bin -w on对应的boot.bif文件内容示例:
the_ROM_image: { [bootloader]fsbl.elf system.bit application.elf }5. 编程QSPI Flash
5.1 硬件连接
- 确保开发板断电
- 连接JTAG调试器
- 设置启动模式跳线为QSPI启动(参考开发板手册)
5.2 使用SDK编程Flash
- 在SDK中打开
Xilinx Tools → Program Flash - 选择生成的BOOT.bin文件
- 配置Flash类型和参数(必须与硬件匹配)
- 点击Program开始烧写
常见问题排查:
- 如果编程失败,尝试降低QSPI时钟频率
- 确认Flash保护位未被设置
- 检查电源稳定性,特别是Flash芯片供电
5.3 验证编程结果
- 编程完成后,断开JTAG连接
- 重新上电,观察PL端LED是否按预期工作
- 可以通过串口查看FSBL启动日志(如果启用调试输出)
6. 不同场景下的优化技巧
6.1 仅PL设计的优化
对于只有PL逻辑的设计,可以进一步优化启动时间:
- 在FSBL中禁用不必要的初始化代码
- 使用压缩bit文件(通过Vivado的
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]) - 调整FSBL中的延迟参数
6.2 多版本备份方案
在产品开发中,建议实现多镜像备份机制:
- 在QSPI Flash中划分多个区域存储不同版本的BOOT.bin
- 通过GPIO或寄存器选择启动版本
- 实现简单的回滚机制
// 示例:FSBL中的多镜像选择逻辑 if(GPIO_Read(BOOT_SEL_PIN) == 1) { image_offset = SECONDARY_IMAGE_OFFSET; } else { image_offset = PRIMARY_IMAGE_OFFSET; }6.3 量产编程方案
对于批量生产,可以考虑:
- 制作Flash编程夹具
- 使用Xilinx提供的Production Programmer工具
- 实现自动化测试流程
7. 常见问题与解决方案
在实际项目中,我们可能会遇到各种意外情况。以下是几个典型问题及其解决方法:
问题1:编程成功但无法启动
- 检查启动模式跳线设置
- 确认BOOT.bin文件顺序正确
- 测量QSPI时钟信号质量
问题2:Vivado版本差异导致的FSBL问题
- 2019.1之前版本:FSBL自动处理bit文件
- 2019.1及以后:需要手动配置
xfsbl_config.h - 推荐使用LTS版本以获得更好稳定性
问题3:Flash寿命问题
- 避免频繁重复编程
- 实现磨损均衡算法(如果是NOR Flash)
- 考虑使用外部Flash存储动态数据
在一次工业控制器开发中,我们发现上电后偶尔无法启动,最终定位问题是电源时序问题——Flash在FPGA完成配置前就开始响应请求。通过在FSBL中添加50ms延迟解决了这个问题。这种实际经验告诉我们,即使所有步骤都正确,硬件特性也可能带来意外挑战。
