ZYNQ SD卡启动全流程详解:从FSBL到BOOT.BIN的固化实践 📅 2026/8/6 10:57:36 1. 项目概述与核心价值最近在折腾一块Red Pitaya板子顺带也回顾了一下手头的黑金ZYNQ开发板发现很多朋友在完成一个完整的PL可编程逻辑 PS处理系统工程后面对“如何把程序固化到SD卡里让板子上电就能跑”这个问题时还是会有点懵。这确实是个从“玩具”到“产品”的关键一步。你可能会想我在Vivado里仿真、综合、实现都通过了在SDK/Vitis里也能通过JTAG下载运行一切都很美好。但一旦拔掉下载器断电重启板子又“失忆”了一切归零。这种感觉就像辛辛苦苦搭了个乐高城堡第二天起来发现它又变回了一堆散件。这个笔记要解决的就是如何给你的ZYNQ城堡打上“永久烙印”。具体来说就是将你在Vivado中创建的包含PL硬件设计比如自定义的IP核、FPGA逻辑和PS软件应用比如跑在ARM Cortex-A9上的裸机程序或简单操作系统的工程打包生成一组特定的文件并正确地烧录到SD卡中。之后你只需要将这张SD卡插入板子上电整个系统就能自动加载并运行完全脱离电脑和JTAG调试器。这对于产品原型演示、野外测试或者任何需要脱机运行的场景都至关重要。无论是Red Pitaya这种集成了高速ADC/DAC的“科学仪器”板卡还是黑金这类更通用的教学/开发板其ZYNQ芯片的启动流程本质是相通的。核心都在于理解ZYNQ的启动过程BootROM - FSBL - 应用以及各阶段文件BOOT.BIN, image.ub, u-boot, dtb等的作用。网上教程很多但往往只讲某一步操作缺乏对“为什么这么做”的串联解释导致一旦换块板子或者工程结构稍有变化就容易卡壳。这篇笔记我会结合这两类板卡的实际操作把每一步背后的逻辑和踩过的坑都捋清楚目标是让你看完后不仅能照着步骤做成功更能明白其中的道理做到举一反三。2. 工程整体设计与固化思路拆解2.1 ZYNQ启动流程深度解析在动手之前我们必须吃透ZYNQ的启动链Boot Chain。这是所有固化操作的理论基础不理解它后面的步骤就只是机械的模仿出了问题根本无法排查。ZYNQ芯片上电或复位后首先运行的是芯片内部ROM中固化的代码我们称之为BootROM。这段代码是芯片出厂时就写死的它的使命非常明确按照预先设定的顺序去各个可能的启动设备如QSPI Flash、SD卡、NAND等上寻找一个叫做“Boot Header”的特殊数据结构。对于我们常用的SD卡启动模式BootROM就会去SD卡的第一个FAT32分区寻找这个头。Boot Header里包含了关键信息比如下一个要加载的代码通常是FSBL存放在SD卡的什么位置、长度是多少、加载到内存的哪个地址。BootROM根据这些信息将FSBL从SD卡加载到芯片内部的内存OCM中然后跳转执行。至此BootROM的任务完成接力棒交给了FSBL。FSBLFirst Stage Boot Loader是我们需要生成的第一段关键代码。它通常由Vitis或旧版的SDK根据你的硬件设计自动生成。FSBL的职责更重一些初始化PS端更复杂的硬件比如DDR内存控制器。BootROM只做了最基础的初始化完整的DDR初始化要靠FSBL。加载比特流Bitstream。FSBL会从SD卡上找到PL部分的配置文件.bit文件并将其编程到FPGA配置存储器中从而“烧写”PL逻辑。这一步完成后你设计的硬件如自定义IP、加速器才真正在芯片上就绪。加载并跳转到第二段程序。这第二段程序可以是裸机应用程序.elf、u-boot引导Linux或者其他系统。FSBL会把它加载到DDR内存中然后跳转过去执行。所以一个典型的从SD卡启动的ZYNQ系统其启动文件的核心就是一个由FSBL、硬件比特流和应用程序打包而成的BOOT.BIN文件。BootROM找到它读取头信息加载FSBLFSBL运行后再从BOOT.BIN内部解压出比特流和应用程序分别进行配置和加载。2.2 固化方案选型为什么是SD卡对于开发和原型阶段将程序固化到存储介质常见的选择有QSPI Flash、SD卡和eMMC。这里我们选择SD卡主要基于以下几点考量极高的便利性与灵活性SD卡可以随时通过读卡器在电脑上修改内容无需专用编程器。调试阶段你可能需要频繁更换应用程序甚至硬件比特流SD卡方案就像U盘一样即插即用大大提升了迭代效率。相比之下QSPI Flash每次烧写都需要通过JTAG过程更耗时。容量优势SD卡容量通常远大于板载的QSPI Flash后者常见16Mb~128Mb。如果你的应用包含大型的应用程序、文件系统或者Linux内核与根文件系统SD卡是更合适的选择。Red Pitaya和很多黑金板卡都直接设计了SD卡槽就是为了充分利用这一点。广泛的板卡支持无论是Red Pitaya还是黑金的ZYNQ开发板SD卡启动都是官方支持和演示的首选方式资料和社区经验最为丰富降低了学习成本。容错与恢复简单如果烧写失败导致系统无法启动对于SD卡你只需要把卡拔下来在电脑上重新格式化并复制正确的文件即可。而对于Flash可能需要通过JTAG进行恢复性擦写操作更复杂。当然SD卡方案也有其局限性比如物理尺寸较大、不如芯片贴片式Flash可靠等。但在产品原型、实验验证和教育学习场景下它的优势是压倒性的。因此本笔记聚焦于SD卡固化方案。2.3 工程准备与文件清单在开始生成固化文件之前请确保你的Vivado工程已经完成了以下步骤并准备好了对应的输出文件Vivado工程已经创建了Block Design正确配置了ZYNQ PS包括DDR型号、时钟、外设等这部分配置必须与你的物理板卡完全一致尤其是DDR型号错了百分之百无法启动并添加了PL端的逻辑如果有。完成综合Synthesis、实现Implementation并生成比特流Generate Bitstream。导出硬件平台在Vivado中使用File - Export - Export Hardware...功能。这一步至关重要它会将你的硬件设计信息包括PS配置、地址映射等打包成一个.xsa(Xilinx Support Archive) 文件。请务必勾选“Include bitstream”这样比特流信息也会包含在内。这个.xsa文件是后续在Vitis中创建平台项目和应用程序的基础。Vitis应用程序在Vitis中基于导出的.xsa文件创建平台项目Platform Project和应用程序项目Application Project。编写、编译你的PS端C/C代码成功生成.elf可执行文件。至此你应该拥有以下核心文件design_1_wrapper.bit(或类似名称): 来自Vivado的PL硬件比特流文件。design_1.xsa(或类似名称): 从Vivado导出的硬件平台描述文件。hello_world.elf(或你的应用程序名): 来自Vitis的PS端应用程序可执行文件。注意文件路径与命名建议将所有工程文件放在一个没有中文和特殊字符的路径下。文件名也尽量使用英文。有些工具链对中文路径支持不佳可能导致难以察觉的错误。3. 核心文件生成与配置详解3.1 创建FSBL第一级启动加载器FSBL是启动链条中的关键一环我们需要在Vitis中专门为它创建一个项目。在Vitis中选择File - New - Application Project。在弹出的向导中选择之前基于.xsa文件创建的硬件平台Platform。在“Templates”选择页面不要选择空项目或其他直接滚动找到并选择“Zynq FSBL”模板。Vitis会自动为你创建一个配置好的FSBL工程。点击FinishVitis会自动生成并编译FSBL工程。编译成功后在工程目录的Debug或Release文件夹下取决于你的编译配置你会找到fsbl.elf文件。为什么必须用模板FSBL的代码结构、链接脚本Linker Script和启动代码Boot.S都是特定的它需要知道如何初始化DDR、如何解析Boot Header、如何加载比特流等。使用官方模板能确保这些底层机制正确无误自己从头编写极易出错。3.2 打包生成BOOT.BIN文件这是固化流程中最核心的一步我们需要将FSBL、硬件比特流和应用程序三个文件“打包”成一个BootROM能识别的BOOT.BIN。在Vitis中这个工作可以通过创建“系统项目System Project”或直接使用“Create Boot Image”工具来完成。这里介绍更直观的图形化工具方法。在Vitis中找到菜单栏Xilinx - Create Boot Image。这会打开一个独立工具窗口。选择输出路径Boot image output path指定一个你希望存放BOOT.BIN的文件夹例如工程根目录下的boot_image文件夹。添加启动文件Boot image partitions点击Add首先添加fsbl.elf。在“Partition type”下拉菜单中必须为其选择bootloader。再次点击Add添加你的硬件比特流文件.bit。它的类型会自动识别为datafile。第三次点击Add添加你的应用程序文件.elf例如hello_world.elf。它的类型应设置为datafile。添加文件的顺序至关重要必须严格按照bootloader(fsbl) -datafile(bitstream) -datafile(application) 的顺序排列。这个顺序对应了启动时的加载和执行顺序。配置选项在“Output format”中选择BIF和Binary。确保“Architecture”选择正确如zynq。其他选项通常保持默认即可。点击Create Image按钮。工具会运行并在输出目录生成BOOT.BIN文件同时也会生成一个.bif(Boot Image Format) 文本文件它描述了打包的规则你可以打开查看以作验证。关键点解析BIF文件生成的.bif文件内容大致如下//arch zynq; split false; format BIN the_ROM_image: { [bootloader] fsbl.elf design_1_wrapper.bit hello_world.elf }这个文件清晰地定义了启动镜像的构成。你可以手动编辑这个.bif文件然后使用命令行工具bootgen来生成BOOT.BIN这在脚本化或自动化构建中非常有用。命令类似bootgen -image myboot.bif -arch zynq -o BOOT.BIN -w on。3.3 SD卡分区与格式化准备不是简单地把BOOT.BIN扔进SD卡就行。SD卡需要被准备成ZYNQ BootROM期望的格式。备份数据首先备份SD卡内所有重要数据接下来的操作会清空整张卡。使用分区工具在Windows下可以使用diskpart命令或第三方工具如SD Card Formatter、Rufus或MiniTool Partition Wizard。在Linux下可以使用fdisk或gparted。创建分区表将SD卡的分区表格式化为MBRMaster Boot Record格式。虽然有些新的板卡或UEFI支持GPT但ZYNQ的BootROM通常只认MBR这是最保险的选择。创建第一个分区大小至少几百MB建议1GB以上以便存放后续可能增加的Linux内核等文件。文件系统必须是FAT32。BootROM只能识别FAT16/FAT32文件系统。分区属性需要将该分区设置为“可启动”或“活动”分区。在diskpart中使用active命令在图形化工具中通常有对应的复选框。格式化使用工具对创建好的FAT32分区进行快速格式化。实操心得SD卡的选择与格式化工具SD卡质量尽量使用品牌可靠、速度等级Class 10或UHS-I较高的卡。劣质卡可能导致启动不稳定、加载失败甚至无法识别。格式化工具Windows自带的格式化工具有时可能无法正确设置活动分区。我强烈推荐使用SD Card Formatter这个官方工具。它专为SD卡优化能彻底清空并格式化避免残留数据导致的问题成功率极高。在Linux下使用mkfs.vfat -F 32 /dev/sdX1命令格式化即可请将sdX1替换为你的实际设备名操作前务必确认设备名以免误格式化系统盘。4. 文件部署与上电测试4.1 复制启动文件到SD卡将上一步生成的BOOT.BIN文件直接复制或拖拽到SD卡FAT32分区的根目录下。根目录指的是打开SD卡盘符后直接进入的位置不要放在任何子文件夹里。为什么必须是根目录BootROM的代码逻辑固定地从存储设备的第一个活动FAT分区的根目录寻找启动文件。它不会去遍历子目录。文件名也通常是固定的如BOOT.BIN但有些BootROM也支持其他名称如boot.bin不过使用全大写的BOOT.BIN是兼容性最好的做法。对于简单的裸机程序只有一个BOOT.BIN通常就够了。如果你的应用更复杂例如运行Linux你还需要将Linux内核镜像image.ub或uImage、设备树文件devicetree.dtb和根文件系统也放到SD卡上。BOOT.BIN里包含的可能是u-boot然后由u-boot来加载这些文件。应用程序需要访问数据文件你可以把其他数据文件如图片、配置文件也放在SD卡根目录或自建的子目录下在你的应用程序代码中通过文件系统API去读取。4.2 硬件连接与上电启动安全插入SD卡将准备好的SD卡插入开发板的SD卡槽。确保插入方向正确听到“咔哒”声表示已锁紧。配置启动模式这是非常关键且容易出错的一步ZYNQ芯片有一组特定的引脚MIO[5:0]或EMIO在上电复位时被采样其电平状态决定了启动设备SD卡、QSPI、JTAG等。你需要根据开发板原理图或用户手册将板上的启动模式跳线帽设置到SD卡启动的位置。Red Pitaya通常通过板载的微型拨码开关来设置。请查阅其官方文档找到SD卡启动对应的二进制编码例如MIO5..0 001010。黑金开发板通常使用跳线帽连接特定的排针。同样需要查阅手册例如AX7020/AX7010等型号SD卡启动可能是将MIO5-0跳线设置为0-1-0-1-0-0之类的组合。通用规律大多数板卡SD卡启动模式对应的MIO5和MIO4通常为0和1即01但具体请以手册为准。设置错误将导致BootROM根本不去读SD卡。连接串口可选但强烈推荐将板子的UART串口通过USB转串口线连接到电脑。在电脑上使用串口终端软件如Putty、MobaXterm、SecureCRT或Vitis自带的串口终端。配置正确的COM端口、波特率ZYNQ通常为115200、数据位8、停止位1、无校验位和无流控。串口是观察启动过程、调试错误的最重要窗口。上电给开发板上电。观察串口终端是否有输出信息。4.3 启动现象分析与成功验证如果一切配置正确你应该在串口终端看到类似如下的启动日志以裸机程序为例Xilinx First Stage Boot Loader Release 2023.1 Dec 14 2023 - 09:15:23 ... Boot mode is SD ... ****** SD Init Started ****** ... SD Init Done ... ****** SD Read Started ****** ... SD Read Done ... ****** Programming FPGA Started ****** ... Programming FPGA Done ... ****** SD Read for Application Started ****** ... SD Read for Application Done ... ****** Application Started ******最后你应该看到你的应用程序输出的信息例如 “Hello World”。同时如果PL部分有设计比如点亮了LED对应的硬件功能也会生效。成功标志串口打印了完整的FSBL日志并显示“Application Started”。你的应用程序预期功能正常串口打印、LED闪烁、计算等。最关键的是此时完全断开JTAG下载器和电脑的连接仅保留电源和串口线给板子重新上电或按下复位键。系统应该能再次自动从SD卡启动并运行你的程序。这才是真正意义上的“固化”成功。5. 常见问题与深度排查指南即使按照步骤操作也可能会遇到启动失败的情况。下面是一些常见问题及其排查思路我把它们整理成了表格方便快速对照。现象可能原因排查步骤与解决方案串口无任何输出1. 启动模式跳线设置错误。2. SD卡未正确格式化非FAT32/非活动分区。3. BOOT.BIN文件损坏或未在根目录。4. 硬件问题电源、时钟、DDR配置错误。5. 串口连接或配置错误。1.反复检查启动模式跳线对照板卡手册确认。这是最高频的错误点。2. 使用SD Card Formatter工具重新格式化SD卡确保是FAT32且为活动主分区。3. 将SD卡插回电脑确认BOOT.BIN文件大小正常并位于根目录。4. 先用JTAG模式启动在Vitis中运行一下硬件自检或DDR测试程序确认硬件基础是否正常。5. 检查串口线、驱动、端口号、波特率(115200)设置。FSBL卡在“SD Init”或“SD Read”阶段1. SD卡兼容性问题或接触不良。2. Vivado中ZYNQ IP的SD/SDIO外设配置错误如时钟频率。3. 板卡供电不足导致SD卡无法正常工作。1. 换一张品牌好、速度等级高的SD卡试试。确保SD卡槽接触良好。2. 检查Vivado Block Design中ZYNQ IP的MIO配置确认SD 0外设已使能且引脚分配与原理图一致。3. 尝试使用外部电源适配器而非USB供电确保电流充足。FPGA编程失败Programming FPGA Done未打印1. 比特流文件(.bit)未正确打包进BOOT.BIN。2. 比特流文件本身生成有问题布局布线失败。3. PL部分功耗或资源超限上电后不稳定。1. 检查创建Boot Image时是否添加了.bit文件并确认顺序在fsbl之后、app之前。2. 在Vivado中尝试通过JTAG直接编程比特流看是否能成功。确保比特流是针对当前板卡生成的。3. 检查Vivado实现后的报告确认无时序违例、资源利用率正常。应用程序未启动无应用打印输出1. 应用程序.elf文件未打包或损坏。2. 应用程序链接地址Load Address与FSBL加载地址不匹配。3. 应用程序代码本身有Bug如死循环、内存访问错误。1. 检查BOOT.BIN打包列表确认包含了应用程序.elf。2.重点检查在Vitis中打开应用程序工程的属性Properties找到C/C Build - Settings - Tool Settings - Linker - Script。确认使用的链接脚本是否正确。对于裸机程序它应该链接到DDR内存地址例如0x00100000而不是默认的OCM地址。FSBL默认会将应用程序加载到0x00100000这个地址。如果链接地址错了跳转后必然崩溃。3. 先用JTAG模式在调试环境下运行应用程序排除软件逻辑错误。能启动但功能不正常如LED不亮1. PL比特流虽加载但对应的PS端驱动未正确初始化或控制。2. 硬件约束文件XDC中引脚分配错误与板卡实际电路不符。3. PS端时钟或复位信号未正确提供给PL。1. 确认应用程序中包含了初始化和控制PL自定义IP如AXI GPIO的代码。2.仔细核对XDC文件确保每个PL端口的引脚编号如“F14”与开发板原理图完全一致。一个引脚错误就可能导致信号无法输出到正确的物理引脚上。3. 检查Block Design中从ZYNQ IP到PL的时钟和复位连接是否已正确建立并导出。高级调试技巧使用FSBL调试信息如果问题棘手可以启用FSBL的详细调试信息。修改FSBL工程的源代码在main.c或相关配置文件中在编译前定义宏FSBL_DEBUG_DETAILED。重新编译FSBL并打包BOOT.BIN它会输出更详细的初始化过程帮助你定位是卡在哪个具体的硬件初始化步骤。关于Red Pitaya和黑金板卡的特别提示Red Pitaya它本质上是一块定制的ZYNQ板卡其启动原理与通用板无异。但需要特别注意其启动拨码开关的设置以及原厂SD卡镜像的分区结构它通常包含多个分区用于其生态系统。当你制作自己的启动卡时只需一个FAT32分区存放BOOT.BIN即可。另外Red Pitaya的PS端时钟和DDR配置是固定的在Vivado中创建硬件平台时建议直接导入其官方提供的预设文件.xdc或 .tcl避免手动配置出错。黑金开发板不同型号如AX7020, AX7010的DDR芯片型号和时钟频率可能不同。务必务必务必在Vivado中配置ZYNQ IP核时在“DDR Configuration”选项中选择与你手中板卡型号完全一致的DDR部件号。这是导致无法启动的最常见硬件配置错误。黑金通常会提供对应的预设文件.tcl直接运行它来配置ZYNQ IP是最稳妥的方式。固化过程中最考验耐心的是对细节的把握。每一次失败都请优先检查启动模式、SD卡格式、文件位置、DDR配置、引脚分配。把这几个关键点锁死成功就是水到渠成的事情。当你第一次看到板子脱离电脑独立跑起自己的程序时那种成就感绝对是调试LED闪烁时无法比拟的。这标志着你的ZYNQ开发从“实验”迈向了“系统”。