当前位置: 首页 > news >正文

ZYNQ 程序固化与升级指南

文章目录

    • 前言
    • 一、ZYNQ 烧录文件的组成
      • 1.1 裸机/裸跑程序
      • 1.2 Linux 系统
    • 二、核心概念:FSBL 是什么?
      • 2.1 FSBL 的定义
      • 2.2 FSBL 的核心职责
      • 2.3 FSBL 的生成时机
    • 三、更底层的起点:BootROM
      • 3.1 BootROM 是什么?
      • 3.2 BootROM 的核心职责
      • 3.3 为什么需要 BootROM?
      • 3.4 BootROM 与 FSBL 的分工
    • 四、完整的程序加载流程
      • 4.1 启动链路全景图
      • 4.2 简化版流程图
    • 五、常见问题与解答
      • Q1:什么情况需要烧录 .elf?
      • Q2:既然 .elf 被打包在 BOOT.bin,为什么还要每次固化 .elf?
      • Q3:XSA文件不变,是不是就不需要更换 .elf?
      • Q4:升级过程会自动校验吗?
    • 六、升级文件的产生流程
      • 6.1 完整的文件生成链路
      • 6.2 不同场景下的升级文件
    • 七、实践:一键烧录脚本
      • 7.1 使用说明
      • 7.2 运行日志
      • 7.3 U-Boot 命令详解
    • 八、总结
    • 附录:常用 Flash 类型参数

前言

在 ZYNQ 开发过程中,程序如何固化、如何升级是每个开发者都会遇到的问题。本文将以问答形式,系统梳理 ZYNQ 程序烧录相关的核心知识点,帮助你从原理到实践全面掌握。

一、ZYNQ 烧录文件的组成

1.1 裸机/裸跑程序

ZYNQ 的烧录文件通常打包成一个BOOT.bin文件,包含三个核心部分:

组成部分文件格式作用
FSBL.elf第一阶段引导加载程序,初始化PS端硬件
硬件逻辑.bit配置FPGA逻辑电路
用户程序.elf在ARM上运行的应用程序

这三部分按照FSBL → BIT → ELF的顺序打包成 BOOT.bin,顺序错误会导致启动失败。

1.2 Linux 系统

Linux 系统的启动文件更为复杂,通常包含:

  • BOOT.bin:FSBL + .bit + U-Boot
  • uImage:Linux内核镜像
  • devicetree.dtb:硬件描述文件
  • uramdisk.image.gz:根文件系统

二、核心概念:FSBL 是什么?

2.1 FSBL 的定义

FSBLFirst Stage Boot Loader(第一阶段引导加载程序)的缩写。简单理解:ZYNQ 上电后,ARM 核心执行的第一段用户程序就是 FSBL。

2.2 FSBL 的核心职责

职责具体内容
初始化PS端配置ARM核心、DDR内存、时钟、中断等
加载PL端.bit文件配置到FPGA逻辑区域
加载用户程序从Flash读取程序到DDR,然后跳转执行
支持安全启动可选:验证镜像签名、解密等

2.3 FSBL 的生成时机

FSBL 是在Vitis(旧称 SDK)中生成的,流程如下:

text

Vivado硬件设计 → 导出XSA文件 → Vitis创建FSBL工程 → 编译生成fsbl.elf

关键点:只要 Vivado 硬件设计变了(PS配置、DDR参数、引脚分配等),就必须重新生成 FSBL

三、更底层的起点:BootROM

3.1 BootROM 是什么?

BootROM是 ZYNQ 芯片内部固化、不可修改的一段只读代码,位于芯片的 ROM 中。它是 ZYNQ 上电后执行的第一段代码

可以把它理解为芯片的“硬件出厂设置”——类似电脑主板的 BIOS,但更底层。

3.2 BootROM 的核心职责

职责说明
初始化基本硬件配置 CPU、时钟等最基础的功能
读取启动模式检测拨码开关,确定从 QSPI/SD卡/JTAG 等介质启动
加载 FSBL从启动介质读取BOOT.bin头部,加载到芯片内部 RAM(OCM)
验证并跳转检查 CRC 校验和,通过后跳转到 FSBL 执行

3.3 为什么需要 BootROM?

没有 BootROM,ZYNQ 上电后不知道该怎么启动。

核心原因:要从外部 Flash 读取代码,必须先有代码来初始化 Flash 控制器——这是一个“先有鸡还是先有蛋”的问题。BootROM 作为芯片内部预置的代码,解决了这个悖论。

3.4 BootROM 与 FSBL 的分工

BootROMFSBL
位置芯片内部 ROM(固化)外部 Flash(可更新)
是否可修改❌ 不可修改✅ 可以修改
主要任务加载 FSBL初始化 DDR、配置 PL、加载用户程序
对开发者的影响只需遵守其格式要求需要根据硬件生成

一句话总结:BootROM 负责找到并加载 FSBL,然后就把控制权交出去了。开发者无需修改它,只需要按照它的要求打包 BOOT.bin 即可。

四、完整的程序加载流程

4.1 启动链路全景图

┌─────────────────────────────────────────────────────────────┐ │ 1. 上电复位 │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 2. BootROM(芯片内部固定,不可修改) │ │ - 初始化最基本硬件(CPU、时钟等) │ │ - 读取启动模式拨码开关(QSPI/SD卡/JTAG) │ │ - 从启动介质读取 BOOT.bin 头部 │ │ - 验证 Header 的 CRC 校验和 │ │ - 将 FSBL 加载到 OCM(芯片内部 RAM) │ │ - 跳转到 FSBL │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 3. FSBL(存储在 Flash 中,用户可以修改) │ │ - 初始化 DDR 内存 │ │ - 配置 PL(加载 .bit 文件到 FPGA) │ │ - 从 Flash 读取用户程序到 DDR │ │ - 验证分区校验和 │ │ - 跳转到用户程序 │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 4. 用户应用程序 │ │ - 裸机程序:直接运行 │ │ - Linux:运行 U-Boot → 加载内核 → 挂载文件系统 │ └─────────────────────────────────────────────────────────────┘

4.2 简化版流程图

上电复位 ↓ ┌─────────────────────────────────────────┐ │ BootROM(芯片固化,不可修改) │ │ 读取启动模式 → 加载FSBL → 验证 → 跳转 │ └─────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ FSBL(可更新) │ │ 初始化DDR → 配置PL → 加载用户程序 → 跳转 │ └─────────────────────────────────────────┘ ↓ 用户应用程序

五、常见问题与解答

Q1:什么情况需要烧录 .elf?

答案:FSBL(.elf文件)变了,或者 Flash 里没有 FSBL 时才需要。

情况是否需要烧录.elf
Flash是空白的(第一次烧录)✅ 必须
Vivado硬件设计变了✅ 必须
只改了C代码(app.elf)❌ 不需要
只改了PL逻辑(.bit)❌ 通常不需要
量产时升级固件❌ 不需要

Q2:既然 .elf 被打包在 BOOT.bin,为什么还要每次固化 .elf?

这是一个很容易混淆的问题。关键在于:烧录时指定的-fsbl参数,和打包在BOOT.bin里的 FSBL,是两个不同用途的 FSBL。

烧录工具使用的FSBL打包在BOOT.bin里的FSBL
存放位置电脑硬盘上的.elf文件BOOT.bin镜像内部
运行时间烧录过程中临时运行正常启动时运行
核心任务为烧录工具提供运行环境初始化系统并启动应用
是否需要频繁更新不需要看硬件是否变化

通俗理解

  • 烧录时的FSBL = U盘启动盘(制作一次可反复使用)
  • BOOT.bin里的FSBL = C盘里的系统引导程序(随系统更新而变化)

Q3:XSA文件不变,是不是就不需要更换 .elf?

是的,完全正确。

只要.xsa文件(硬件平台描述文件)没有变化,用于烧录的fsbl.elf就完全不需要更换

日常固件升级时,你只需要替换BOOT.binfsbl.elf可以视为一个固定不变的烧录“驱动”

Q4:升级过程会自动校验吗?

是的,升级过程会自动进行校验。

校验分为两个层面:

  1. 烧录过程校验program_flash工具):
    • 使用-verify选项,写入后自动读取Flash内容并比对
  2. 启动过程校验(BOOT.bin内部机制):
    • BootROM检查Header的CRC校验和
    • FSBL检查每个分区的校验和

建议:烧录命令中始终添加-verify选项,确保写入数据的完整性。

六、升级文件的产生流程

6.1 完整的文件生成链路

text

Vivado硬件设计 ↓ 导出 XSA文件(硬件平台描述) ↓ Vitis创建工程 FSBL工程 → 编译 → fsbl.elf ↓ 应用工程 → 编译 → app.elf ↓ Boot Image打包工具(bootgen) ↓ BOOT.bin(最终烧录文件)

6.2 不同场景下的升级文件

升级场景需要替换的文件是否需要换fsbl.elf
应用程序更新BOOT.bin
FPGA逻辑更新BOOT.bin(包含新.bit)否(除非接口变化)
硬件配置变化BOOT.bin + fsbl.elf
首次烧录空白板BOOT.bin + fsbl.elf

七、实践:一键烧录脚本

以下是一个带详细打印信息的烧录脚本,将所需文件放在同一文件夹,双击即可完成升级:

@echo off chcp65001>nul title Zynq QSPI Flash 烧录工具 color 0Aecho========================================echoZynq QSPI Flash 一键烧录脚本echo========================================echo. :: 设置Xilinx工具路径(请根据实际安装路径修改)setPATH_XILINX=C:\Softwares\Xilinx\Vitis\2021.1\bin :: 检查工具路径是否存在ifnot exist"%PATH_XILINX%\program_flash"(echo[错误]找不到 program_flashecho请检查路径: %PATH_XILINX% pauseexit/b1)echo[1/5]Xilinx 工具路径检测: 通过 echo. :: 检查当前目录下的文件echo[2/5]检查烧录文件...setBIN_FILE=setELF_FILE=for%%fin(*.bin)do(setBIN_FILE=%%fecho找到 BIN 文件: %%f)for%%fin(*.elf)do(setELF_FILE=%%fecho找到 ELF 文件: %%f)echo. :: 检查 .bin 文件是否存在if"%BIN_FILE%"==""(echo[错误]当前文件夹下没有找到 .bin 文件echo请确保 BOOT.bin 或其它 .bin 文件在此目录下 pauseexit/b1)::==========新增:强制要求 .elf 文件==========if"%ELF_FILE%"==""(echo[错误]当前文件夹下没有找到 .elf 文件echo烧录空白 Flash 时必须提供 fsbl.elf 文件echo请将 fsbl.elf 复制到当前目录后重试 echo.echo提示:如果 Flash 中已有 FSBL 且无需更新,echo请手动移除本脚本中的 .elf 检查逻辑 pauseexit/b1)::============================================echo[3/5]文件校验通过echo将烧录 BIN: %BIN_FILE%echo使用 FSBL: %ELF_FILE% echo. :: 用户确认echo[4/5]请确认以下事项:echo1. 板卡已设置为 JTAG 模式echo2. 下载器已连接并上电echo3. 即将烧录文件: %BIN_FILE% echo.set/pconfirm="确认继续烧录?(Y/N): "if/i not"%confirm%"=="Y"(echo用户取消烧录 pauseexit/b0):: 开始烧录 echo.echo[5/5]正在烧录 QSPI Flash...echo请勿断开电源或 USB 连接... echo. call"%PATH_XILINX%\program_flash"-f"%BIN_FILE%"-offset0-flash_typeqspi-x4-single-fsbl"%ELF_FILE%"-verify:: 检查结果if%errorlevel% neq0(echo.echo[错误]烧录失败!错误代码: %errorlevel%echo请检查:echo- 下载器是否连接正常echo- 板卡是否上电echo- flash_type 参数是否正确 pauseexit/b %errorlevel%):: 烧录成功 echo.echo========================================echo烧录成功完成!echo========================================echo.echo下一步操作:echo1. 断开电源echo2. 将板卡启动模式切换到 QSPIecho3. 重新上电,程序应从 Flash 启动 echo. pause

7.1 使用说明

  1. 将上述脚本保存为program_qspi.bat
  2. 修改脚本中的PATH_XILINX为你的实际安装路径
  3. BOOT.binfsbl.elf放在同一文件夹

  1. 板卡设置 JTAG 模式,连接下载器并上电
  2. 双击program_qspi.bat即可完成烧录

7.2 运行日志

7.3 U-Boot 命令详解

以下是嵌入式开发中最核心、最常用的 U-Boot 命令详解:

  • sf probe

    • 格式:sf probe <总线编号> [<时钟频率>] [<SPI模式>]

      • 总线编号:SPI 控制器的编号(通常是 0)

      • 时钟频率:设置 SPI 时钟频率(Hz),0表示使用 Flash 芯片的默认时钟频率(通常是 40-50 MHz)

      • SPI 模式:SPI 工作模式(0-3)

        模式说明
        0CPOL=0, CPHA=0(最常用)
        1CPOL=0, CPHA=1
        2CPOL=1, CPHA=0
        3CPOL=1, CPHA=1
    • 说明:U-Boot 中用于初始化和探测 SPI Flash 设备的命令。这是执行任何 Flash 操作(读、写、擦除)前必须首先运行的命令

  • sf erase

    • 格式:sf erase <偏移地址> <长度>
      • 偏移地址:Flash 中的起始位置(十六进制)
      • 长度:要擦除的字节数(十六进制)
    • 说明:U-Boot 中用于擦除 SPI Flash 数据的命令。由于 Flash 的物理特性,必须先擦除才能写入数据。
  • sf write

    • 格式:sf write <内存地址> <Flash偏移地址> <长度>
      • 内存地址:数据在 DDR 内存中的源地址
      • Flash偏移地址:写入 Flash 的目标起始地址
      • 长度:要写入的字节数(十六进制)
    • 说明:U-Boot 中用于将数据写入 SPI Flash的命令。在执行此命令前,必须先执行sf probe初始化 Flash,并且目标区域必须已经被擦除。
  • sf read

    • 格式:sf read <内存地址> <Flash偏移地址> <长度>
      • 内存地址:数据要写入的 DDR 内存目标地址
      • Flash偏移地址:Flash 中读取的起始位置
      • 长度:要读取的字节数(十六进制)
    • 说明:U-Boot 中用于从 SPI Flash 读取数据到内存的命令。这是验证烧录结果、备份数据、调试系统时最常用的命令之一。

八、总结

知识点核心要点
BOOT.bin组成FSBL + .bit + app.elf(顺序固定)
BootROM的作用芯片内部固化的引导代码,负责加载FSBL
FSBL的作用上电后第一段用户程序,初始化硬件、加载FPGA、启动应用
FSBL生成时机在Vitis中从XSA文件编译生成
何时需要烧录.elfXSA变化时,或首次烧录空白板
升级校验机制烧录用-verify + BootROM/FSBL的CRC校验
日常升级操作只需替换BOOT.bin,fsbl.elf固定不变

附录:常用 Flash 类型参数

Flash类型program_flash参数
单路QSPI(4线)qspi-x4-single(最常用)
双路QSPI(2线)qspi-x2-single
双片并联(8线)qspi-x8-dual_parallel

本文基于 ZYNQ 7000 系列编写,UltraScale+ 系列原理相同,具体参数请参考对应文档。

http://www.cnnetsun.cn/news/2025231.html

相关文章:

  • CUDA 11.7 自定义安装保姆级教程:告别C盘爆满,手把手教你指定安装路径
  • 终极指南:用Android手机变身专业USB键盘鼠标的完整解决方案
  • 3步搞定!TranslucentTB中文界面终极设置指南:让你的Windows任务栏完美透明化
  • 树莓派4B实时内核编译踩坑实录:从Ubuntu 20.04到RT-PREEMPT补丁的完整流程
  • 避坑指南:DSP28335中断系统配置详解(从PIE到GPIO外部中断)
  • 终极指南:在SketchUp中免费导入导出STL文件的完整解决方案
  • GraalVM镜像启动慢、RSS飙升、OOM频发,全链路内存剖析与5步精准瘦身法,今天不看明天上线翻车
  • 终极Windows任务栏透明美化指南:TranslucentTB让你的桌面焕然一新
  • SQL中INNER JOIN与LEFT JOIN的区别_通过实际场景对比分析
  • League Director:英雄联盟回放视频制作的终极掌控者
  • 终极指南:5分钟解锁VMware macOS支持,免费体验苹果系统
  • TranslucentTB架构深度解析:Windows任务栏透明效果的技术实现与优化
  • 告别旧版Uboot!在Ubuntu 24.04上为i.MX6ULL开发板移植U-Boot 2022.04(含设备树与NFSv3支持)
  • RH850 F1看门狗喂不活?手把手教你配置选项字节(OPBT0/OPBT1)避坑指南
  • ZYNQ 7045/690T项目实战:用Vitis/SDK给GD SPI Flash固化镜像的完整流程(含uboot文件替换指南)
  • LocalClaw Skill架构深度解析:如何从零构建自己的AI工具链
  • 3步实现窗口置顶:AlwaysOnTop让你的多任务处理效率翻倍
  • 三月七小助手:星穹铁道智能自动化解决方案,告别重复点击的终极指南
  • 免费字幕翻译神器:PotPlayer插件让外语视频秒变中文
  • 百度网盘高速下载终极指南:告别限速,轻松获取直连地址
  • 3分钟快速上手:深蓝词库转换工具完整指南 - 轻松迁移20+输入法词库
  • BetterJoy使用指南:三步搞定Switch控制器在PC上的完美体验
  • XUnity.AutoTranslator完整指南:5分钟实现Unity游戏多语言翻译
  • 统一过程模型和统一过程方法对比分析
  • 深入理解!Kotlin 高阶函数与内联函数:noinline、crossinline 那些坑都替你踩过了!
  • 零基础学云计算去哪家机构好?拿技术说话这几家推荐看看
  • PX4飞控源码解读:固定翼姿态控制器里的‘空速缩放’到底在解决什么问题?
  • 如何将照片从Android传输到笔记本电脑?
  • 在PyCharm的Django工程中修改初始页
  • 使用FCM进行编码解码