ZYNQ SD卡启动镜像制作全解析:从FSBL到BOOT.bin的完整流程 📅 2026/8/6 13:13:30 1. 从调试到部署为什么程序固化是ZYNQ开发的关键一步如果你已经用ZYNQ的PS处理器系统和PL可编程逻辑部分跑通了一个功能比如在Redpitaya或者黑金这类开发板上通过Vivado搭建了硬件平台又在Vitis SDK里写好了软件代码并且成功通过JTAG下载运行了。那么恭喜你你已经完成了开发中最激动人心的“验证”环节。但接下来一个非常现实的问题就摆在了面前总不能每次上电都连着电脑和JTAG下载器吧这就像你写了个手机App总不能每次打开都连着电脑用调试器启动。程序固化就是把你的“实验成果”变成可以独立运行的“产品”的第一步。这个过程的核心就是把编译好的硬件比特流.bit文件对应PL配置、软件可执行文件.elf文件对应PS应用程序以及必要的启动引导文件如FSBL打包成一个完整的启动镜像并写入到开发板的非易失性存储介质中最常见的就是SD卡。对于ZYNQ来说上电后处理器会执行芯片内部ROM中的一段固化代码BootROM这段代码会按照预设的顺序比如先看SD卡0再看QSPI Flash去寻找有效的启动镜像。一旦在SD卡里找到了我们制作好的镜像文件BOOT.bin就会将其加载到内存中由FSBLFirst Stage Bootloader接手完成PL的配置、应用程序的加载最终跳转到我们的主程序运行。整个过程完全脱机实现了真正的“上电即用”。我遇到过不少开发者在调试阶段一切顺利但一到固化就卡壳出现的错误五花八门比如SD卡无法识别、启动失败卡在某个阶段、PL逻辑没加载等等。这通常是因为对ZYNQ的启动流程理解不够清晰或者镜像制作、SD卡格式化的某个细节没做到位。这篇文章我就以Redpitaya开发板其核心是Zynq 7010/7020和常见的黑金ZYNQ开发板为例抛开Petalinux等复杂框架聚焦最基础的“PLPS裸机工程”的SD卡固化流程把每一步的原理、操作和容易踩的坑都掰开揉碎了讲清楚。无论你是学生做课程设计还是工程师做原型验证掌握这套“标准动作”都至关重要。2. 固化前的核心准备理解ZYNQ启动链与文件清单在动手操作之前我们必须先搞清楚ZYNQ上电后到底干了什么以及我们需要为它准备哪些“食材”。很多固化失败的问题根源就在于文件不全或文件顺序错误。2.1 ZYNQ启动流程的三段式拆解ZYNQ的启动是一个多阶段、分工明确的过程可以粗略分为三个阶段阶段0BootROM这是芯片出厂时就固化在硅片里的代码用户无法修改。一上电CPU0Cortex-A9 Core 0会从复位向量开始执行这段ROM代码。它的任务很简单根据硬件引脚如MIO[5:2]设置的启动模式例如SD卡模式初始化最基本的外设如SD卡控制器然后从存储介质的特定位置对于SD卡是第一个FAT32分区的根目录寻找一个名为BOOT.bin的文件。找到后将其加载到芯片内部RAMOCM中。阶段1FSBL - First Stage Bootloader这个BOOT.bin文件并不是我们的应用程序直接打包它的第一个组成部分必须是FSBL。BootROM把控制权交给FSBL。FSBL是我们用Vitis SDK可以生成的一个轻量级引导程序它的职责很重初始化更多PS端外设比如DDR内存控制器。没有它你的程序无法在大容量的DDR中运行。配置PL可编程逻辑读取BOOT.bin文件中包含的比特流.bit文件通过PCAP接口对PL进行编程。这是实现“PLPS”协同工作的关键一步加载阶段2的应用程序将BOOT.bin文件中包含的应用程序.elf加载到DDR内存的指定地址。跳转执行最后FSBL将CPU的控制权交给我们的应用程序。阶段2用户应用程序这就是我们在Vitis SDK中编写的C/C应用程序.elf。此时硬件平台PL已经配置好DDR内存也已就绪程序可以完全在PS端运行并通过AXI总线与PL进行交互。注意对于单纯的PS程序不使用PLBOOT.bin中可以只包含FSBL和应用程序不需要.bit文件。但我们的场景是“PLPS”所以.bit文件是必需的。2.2 你需要准备哪些关键文件理解了流程我们就知道需要准备以下三个核心文件来制作BOOT.binFirst Stage Bootloader (FSBL.elf)在Vitis SDK中基于你的硬件平台.xsa文件创建FSBL应用工程编译生成。硬件比特流文件 (.bit)在Vivado中完成综合与实现后生成的*.bit文件。它包含了PL部分的网表信息和配置数据。一个关键细节Vivado默认生成的.bit文件不包含PS的配置信息如时钟、MIO引脚对于SD卡启动我们需要的是“包含PS配置的比特流”。通常在Vivado中File - Export - Export Hardware...时勾选Include bitstream导出的.xsa文件中就封装了正确的.bit。或者在Vitis中创建平台工程时会自动处理这个问题。用户应用程序 (.elf)在Vitis SDK中你的主工程编译后生成的可执行文件。除了这三个有时根据需求还会加入Second Stage Bootloader (如U-Boot.elf)用于引导Linux内核在裸机程序中不需要。设备树Blob (.dtb)用于Linux系统裸机不需要。为什么顺序很重要在制作BOOT.bin时文件的排列顺序必须严格遵守FSBL - 比特流(.bit) - 应用程序(.elf)。这个顺序直接对应了启动链的执行顺序。BootROM先加载FSBLFSBL运行时按顺序处理后面的文件先找到.bit就配置PL再找到.elf就加载它。顺序错了FSBL就会“吃错药”导致配置失败。3. 实战操作从Vivado工程到可启动SD卡理论清晰后我们进入实战环节。假设你已经在Vivado中创建了一个包含ZYNQ Processing System和自定义IP或逻辑的工程并且生成了比特流。3.1 第一步导出硬件与创建Vitis平台工程在Vivado中导出硬件打开实现Implemented后的Vivado工程。点击菜单栏File - Export - Export Hardware...。在弹出的对话框中选择Include bitstream。这是关键确保导出的硬件描述包含PL配置信息。指定导出路径例如./project_1.sdk点击OK。这会生成一个.xsa(Xilinx Support Archive) 文件。这个文件替代了旧版本的.hdf文件它打包了硬件比特流、硬件描述信息等一切Vitis需要的东西。启动Vitis并创建平台工程打开Vitis IDE。建议在Vivado中直接点击Tools - Launch Vitis这样可以自动关联当前工程路径。在Vitis中首先需要指定一个工作空间Workspace。在左侧的Explorer视图中右键点击选择Create Platform Project。输入平台工程名称如platform_redpitaya点击Next。在Hardware Specification页面选择Browse找到并选中你刚才导出的.xsa文件。操作系统OS选择standalone因为我们做裸机处理器CPU根据你的设计选择通常是ps7_cortexa9_0。点击Finish完成创建。Vitis会自动根据.xsa文件生成对应的BSPBoard Support Package和硬件平台。3.2 第二步创建并编译FSBL与应用程序创建FSBL应用工程在Vitis菜单栏点击File - New - Application Project。第一步选择刚才创建的平台工程如platform_redpitaya作为目标硬件平台。输入工程名例如fsbl。点击Next。在Templates选择页面这是关键一步在左侧筛选框选择Show All Templates然后在列表中找到并选择Zynq FSBL。这个模板是Xilinx提供的标准FSBL源码。点击Finish。Vitis会自动创建并编译FSBL工程。编译成功后在工程目录下的Debug或Release文件夹内取决于你的构建配置可以找到fsbl.elf文件。创建用户应用程序工程同样通过File - New - Application Project创建新工程例如命名为my_app。硬件平台选择同一个。在模板选择页面你可以选择Empty Application自己从头写或者Hello World等简单模板进行测试。编写你的应用程序代码。一个至关重要的连接你的应用程序需要能访问到PL部分。这通常通过在代码中读写特定内存映射地址对应PL的寄存器空间来实现。这些地址信息来源于Vivado中的地址编辑器Address Editor并在Vitis平台的BSP中生成对应的xparameters.h头文件里面定义了诸如XPAR_MY_AXI_GPIO_0_BASEADDR这样的宏。在你的main.c中需要包含这个头文件#include xparameters.h。编译应用程序工程生成my_app.elf。3.3 第三步制作BOOT.bin启动镜像现在我们有了fsbl.elf 隐含在平台中的.bit 以及my_app.elf。接下来打包。在Vitis中创建Boot Image在菜单栏选择Xilinx - Create Boot Image。这会打开一个图形化向导。Boot image output path选择输出路径比如SD卡的盘符根目录或者本地一个临时文件夹。最重要的部分是Basic标签页下的Partition列表。点击Add添加第一个分区File path浏览并选择fsbl.elf。Partition type选择bootloader。再次点击Add添加第二个分区File path这里需要找到比特流文件。它通常在你的平台工程目录下例如platform_redpitaya/export/platform_redpitaya/hw/*.bit。或者更简单的方法是File path选择你的.xsa文件Vitis会自动识别其中的比特流。Partition type选择datafile。第三次点击Add添加第三个分区File path浏览并选择my_app.elf。Partition type选择datafile。检查顺序确保分区列表从上到下依次是fsbl.elf (bootloader)-硬件比特流 (datafile)-my_app.elf (datafile)。在Output format下选择BIF和Binary。BIF文件是描述镜像构成的文本文件Binary就是最终生成的BOOT.bin。点击Create Image按钮。理解BIF文件进阶点击创建后Vitis会在输出目录生成一个.bif文件。你可以用文本编辑器打开它内容大致如下//arch zynq; split false; format BIN the_ROM_image: { [bootloader, destination_cpua53-0] fsbl.elf platform_redpitaya.bit my_app.elf }这个文件清晰地定义了镜像的组成和顺序是bootgen工具Vitis背后调用的命令行工具的输入。如果你熟悉命令行也可以直接使用bootgen来生成这在脚本化构建中非常有用。操作完成后你会在指定输出目录得到BOOT.bin文件。这就是我们需要的唯一启动文件。3.4 第四步SD卡格式化与文件拷贝这一步看似简单却是“翻车”高发区。SD卡格式化必须使用FAT32文件系统。ZYNQ的BootROM只识别FAT32格式的第一个分区。分区方案必须是MBR主引导记录而不是GPTGUID分区表。大多数新版电脑的磁盘管理工具默认是GPT需要特别注意。操作建议在Windows上可以使用diskpart命令行工具或第三方工具如SD Card Formatter进行格式化确保选择FAT32和MBR。一个更稳妥的方法是使用开源工具Rufus。插入SD卡打开Rufus设备选择你的SD卡引导类型选择“非可启动镜像”分区类型选择“MBR”文件系统选择“FAT32”然后点击开始。Rufus会帮你处理好一切。容量问题虽然FAT32不支持单文件大于4GB但我们的BOOT.bin通常只有几MB到几十MB完全没问题。SD卡本身容量大小8G, 16G, 32G不影响只要格式化成FAT32即可。文件拷贝将上一步生成的BOOT.bin文件直接拷贝到SD卡根目录。不需要其他文件。确保文件名就是BOOT.bin大小写敏感。有些BootROM可能只认全大写的BOOT.BIN但通常小写也可以。为了保险起见可以用全大写。安全弹出SD卡。4. 上电测试、问题排查与深度优化将制作好的SD卡插入开发板的SD卡槽设置启动模式为SD卡启动对于Redpitaya通常是通过板载跳线帽对于黑金开发板可能需要拨动开关具体看板卡手册然后上电。4.1 观察现象与基础调试成功现象如果一切顺利你应该看到预期的程序行为。例如如果程序控制了LED闪烁那么LED就会开始闪烁如果程序通过UART打印信息你可以在串口终端如Putty、MobaXterm看到输出记得连接串口线并设置正确的波特率通常是115200。失败现象完全无反应电源灯亮但没有任何其他现象。这通常意味着BootROM没有找到或无法加载BOOT.bin。卡在某个阶段例如只有PS端的程序跑了但PL逻辑没工作比如自定义的LED不亮。这通常意味着比特流加载失败。串口输出乱码或错误信息FSBL或应用程序在运行中出错。4.2 常见问题排查链路当启动失败时可以按照以下链路逐步排查检查SD卡和启动模式确认启动模式设置百分之五十的问题出在这里。反复核对开发板手册确认跳线或开关确实设置在了SD卡启动模式例如ZYNQ的MIO[5:2]0010代表从SD0启动。换一张SD卡试试有些SD卡特别是大容量、高速卡或山寨卡兼容性可能有问题。换一张品牌可靠、容量适中如8GB或16GB的卡并严格按照FAT32MBR重新格式化。检查接触SD卡槽接触不良也是常见问题可以重新插拔几次。检查BOOT.bin镜像验证文件顺序再次用Vitis打开Create Boot Image工具或查看BIF文件确认分区顺序是FSBL - .bit - App。验证文件完整性确认你加入镜像的.elf文件是最新编译的。有时候在Vitis中修改了代码但忘了重新编译my_app工程导致镜像里是旧程序。尝试最小系统创建一个最简单的应用程序比如只让一个PS端的MIO引脚控制的LED闪烁不包含任何PL逻辑制作镜像测试。如果这个能成功说明SD卡启动流程是通的问题可能出在PL部分或你的应用程序与PL的交互上。利用FSBL的调试信息串口是好朋友FSBL在运行时会通过UART0打印丰富的调试信息。务必连接串口到电脑打开终端软件波特率115200。解读信息FSBL会打印诸如“XFsbl_Initialize - Boot mode is SD”、“XFsbl_LoadBitstream - Loading bitstream...”等信息。如果卡在某个地方信息会停止这能精确定位问题阶段。例如如果没打印“Loading bitstream”说明FSBL可能没找到或无法解析.bit文件。PL配置失败排查如果FSBL打印了加载比特流但后续失败或者应用程序运行但PL没反应问题可能出在比特流本身。确认比特流来源确保制作镜像使用的.bit文件是来自包含PS配置的.xsa导出而不是Vivado直接生成的.bit。后者可能缺少必要的PS初始化信息。检查PL电源和时钟在硬件设计中确认给PL部分的电源和时钟来自PS的FCLK是否正确配置并启用。一个错误的约束如时钟引脚分配错误可能导致PL无法正常工作。用JTAG回退验证重新通过JTAG下载完整的硬件比特流和软件程序确认功能正常。这能排除硬件设计本身的缺陷。4.3 进阶优化启动速度与镜像管理当基本功能跑通后可以考虑一些优化压缩比特流Vivado生成的.bit文件可能很大。在Create Boot Image时可以勾选Compress bitstream选项。FSBL在加载时会先解压这能显著减少BOOT.bin文件大小和从SD卡读取的时间。使用bootgen命令行对于自动化脚本构建如CI/CD图形界面不方便。你可以编写一个.bif文件然后调用命令行工具bootgen。bootgen -image myboot.bif -arch zynq -o BOOT.bin -w on其中-w on表示如果输出文件已存在则覆盖。这可以轻松集成到Makefile或Python脚本中。多应用程序镜像一个BOOT.bin里可以包含多个应用程序.elfFSBL会按顺序加载它们。但更常见的做法是FSBL只加载一个“引导程序”由这个引导程序来决定运行哪个用户程序例如通过检测某个GPIO的状态这提供了更大的灵活性。固化程序到SD卡是ZYNQ开发从实验走向实用的里程碑。这个过程综合了硬件设计、软件编译和系统启动的知识。最关键的是理解启动链并耐心、细致地检查每一个环节硬件导出、文件生成、镜像打包、SD卡格式化。一旦掌握了这个流程你就能让你的ZYNQ项目脱离电脑的“脐带”真正独立运行起来。