搞FPGA开发这几年,我踩过最多的坑不是RTL逻辑写不出来,而是卡在工具链上。Vivado 2023.2配合Vitis跑Zynq的Hello World到BOOT.BIN生成,这条链路几乎每个新手都会走一遍,但过程中会遇到license失效、WinPcap装不上、JTAG识别不到芯片、比特流生成变红、固化后板子不启动等一系列问题。这篇文章把我从零开始跑通整个流程的完整操作、踩坑记录和排查思路都写出来,希望能帮你少走几个月的弯路。
这套流程适合谁?刚拿到Zynq开发板、想从纯FPGA逻辑转到片上系统开发的工程师,或者学校实验室准备用Zynq做项目、需要快速上手的同学。只要你能看懂基本的Verilog代码、知道Vivado是什么,就可以照着走完整个流程。我会从安装开始讲,一直到生成BOOT.BIN、把程序固化到QSPI Flash里跑起来,全程不跳步。
1. 整体设计与方案选型思路
1.1 这条全流程到底解决什么问题
Zynq开发最让人困惑的地方在于,它是一个双核ARM Cortex-A9处理器加上一块FPGA逻辑的异构芯片。你需要先在Vivado里搭建硬件工程,把PS端的配置写清楚,然后把硬件信息导出给Vitis,在Vitis里写C语言程序跑在ARM上,最后还要考虑怎么让程序上电就能自动运行,而不是每次都要依赖JTAG下载。
很多新手拿到板子后的第一反应是像做纯FPGA工程一样直接写代码、综合、上板。但Zynq的Hello World并不是简单的Helloworld,它涉及硬件工程建立、比特流生成、硬件平台导出、软件工程编译、启动镜像制作,这一整条链路每个环节都有自己的坑。
说白了,这条流程解决的核心问题就是把Zynq这种异构芯片真正跑起来。弄清楚整条链路,后续不管是做Linux系统、做硬件加速还是做实时控制,都只是在这条骨架上的延伸。
1.2 为什么选择Vivado 2023.2+Vitis这个组合
截至我写这篇文章的时间,Vivado 2023.2是稳定性比较好、资料比较全的一个版本。它比更早的版本多了些新器件支持,但又没有新版本刚发布时那些莫名其妙的bug。更重要的是,2023.2还是传统的Vitis统一IDE形态,熟悉这个操作方式的人仍然很多,遇到问题能搜到的解决方案也比较丰富。
传统SDK在这个版本被Vitis取代,但Vitis本质上是把原来的SDK和新的应用开发能力整合在一起。对于只想跑裸机程序的新手来说,Vitis就是原来SDK的升级版,界面变了,但核心逻辑没变。选这个版本还有一个现实原因:教程多。B站、论坛、公众号上大量资料都基于2020.x到2023.x版本的界面,照着操作不容易迷路。
1.3 从Hello World到BOOT.BIN的完整链路
这条链路可以拆成五步:
第一步,在Vivado里创建一个以Zynq PS为核心的工程,配置DDR、串口、时钟这些基础外设,然后综合、实现、生成比特流。第二步,把带硬件信息的比特流和硬件描述导出成XSA文件。第三步,打开Vitis,用XSA文件创建硬件平台,再基于这个平台创建Hello World应用程序。第四步,JTAG下载,在终端里看到Hello World打印出来。第五步,把FSBL、比特流、应用程序打包成BOOT.BIN,固化到SD卡或QSPI Flash里,实现上电自启动。
每一步之间环环相扣,前一步出错后面的全部白搭。我的建议是别急着跳步,老老实实走完JTAG调试这一步再考虑固化,否则出了问题根本不知道是软件问题还是启动流程的问题。
2. 环境准备:从安装包到License的实战细节
2.1 Vivado 2023.2下载安装的几个关键选项
很多人卡在安装这一步,其实安装本身不难,难的是选对版本和组件。去Xilinx官网下载页面选择Vivado 2023.2时,会让你选安装包类型。这里有个容易踩的坑:Vivado有三个版本,Vivado ML Enterprise、Vivado ML Standard和Vivado Lab Solutions。新手直接用Vivado ML Standard就够了,它免费、支持所有器件,只是没有Enterprise版的一些高级功能。
安装的时候会问到要装哪些器件系列,建议只勾选你实际用的器件系列。比如你做Zynq-7000,就勾选Zynq-7000,别图省事把所有系列都勾上。全部勾选的后果是安装体积轻松超过100GB,安装时间多出好几个小时,而且大部分空间永远用不上。我见过有人整个C盘都被Vivado装满了,后来清理起来极其痛苦。
安装过程中有个容易让人迷惑的步骤是WinPcap组件。Vivado在安装时有一个网络相关的组件依赖,很多新手在Windows上会遇到WinPcap安装失败的情况。这个问题我后面在常见问题章节里详细说,这里只强调一点:如果WinPcap安装失败,不要直接点忽略然后继续,最好先解决掉它,否则后面硬件管理器的网络调试功能可能不正常。
2.2 License配置与2037错误码的解决办法
License问题基本上是每个新手必踩的坑。Vivado 2023.2在启动时如果检测不到有效的License,会弹出错误提示,常见的有2037、301等错误码。对于个人学习和非商业用途,Vivado ML Standard本身是免费的,但它需要在Vivado安装目录下的XilinxLicense路径或者启动界面的License对话框中配置。
新手最容易犯的错误是下载了别人发的License文件,版本匹配不上,然后弹出一堆看不懂的错误码。我的建议是直接用免费版自带的License机制,在Vivado启动界面选择Obtain License,申请一个免费的Standard版license绑定到自己的账户,然后下载下来加载。这个过程不花钱,只要注册一个账号就行。
配置好License之后,如果仍然提示有问题,检查一下环境变量。有时候系统存在多个版本的License环境变量,导致Vivado抓到了错误的license路径。在Windows的环境变量中,找到名为XILINXD_LICENSE_FILE的变量,确认它指向的文件确实存在,格式是否正确。另外还需要注意,破解版license文件这种操作我不建议尝试,一方面是合规风险,另一方面是2023.2之后Xilinx对License的验证机制更严格,折腾半天不如直接申请免费版。
2.3 安装后必做的一件事:打开Vitis验证组件完整性
安装Vivado时,默认会一起安装Vitis。但如果安装时没有勾选Vitis相关的组件,后面打开Vitis时会提示找不到工具链。2023.2版本的安装包比较大,默认包含Vitis,但Vitis需要额外的磁盘空间和依赖组件,如果你在安装时选择了精简模式,可能只装了Vivado而没装Vitis。
我建议在安装Vivado时,选择标准安装模式,不要选Custom之后手动取消某些看起来不重要的组件。Vitis和Vivado是同时安装到同一个目录下的,打开Vivado安装目录,确认存在Vitis文件夹,一般位于安装目录下的Vitis子目录。如果没有,只能通过添加组件的方式重新运行安装程序补装。
另一个容易忽略的是驱动问题。连接Zynq板子需要使用USB-JTAG调试器,Windows需要安装对应的驱动。Vivado安装目录下自带驱动,通常在安装目录的数据子目录里。插上开发板之后,如果设备管理器里看到未知设备或者带感叹号的设备,手动指定驱动路径到Vivado安装目录下搜索即可。
3. 硬件工程创建与比特流生成详解
3.1 创建Zynq硬件工程的完整步骤
打开Vivado 2023.2之后,点击Create Project,创建一个新的RTL工程。这里要特别注意,很多Zynq相关教程会建议直接用Create Block Design创建硬件工程,但创建普通RTL工程之后也可以添加Block Design。两者的区别不大,关键是你需要一块空白的工程作为载体。
创建完成后,在Project Manager窗口左侧的IP Integrator工具栏中点击Create Block Design,给这个设计起个名字。然后在Diagram窗口中点击加号,搜索并添加ZYNQ7 Processing System这个IP核。添加完IP核之后,会弹出一个自动配置向导,这一步别急着跳过。
ZYNQ7 Processing System的配置是硬件工程的核心。双击IP核打开配置界面,你至少需要做以下几件事:
- 配置PS端的时钟,一般是33.333MHz的外部时钟输入,可以根据开发板的晶振频率调整
- 配置DDR类型、位宽、速度,这个必须和板子上的DDR颗粒匹配,错了会死机
- 配置串口UART,一般是UART1或UART0,对应板上的串口引脚
- 确认MIO配置,把UART的引脚分配正确
如果板卡厂商提供了Board Support Files,也就是BSP文件,导入之后Vivado会自动匹配很多配置,省去手动填参数的痛苦。没有BSP的就只能手动核对原理图了。
配置完Zynq之后,右键点击Block Design设计中的ZYNQ7 PS模块,可以选择Validate Design来验证配置是否有错误。如果验证通过,在Sources窗口右键点击设计文件,选择Create HDL Wrapper,让Vivado自动生成顶层Verilog文件,这会把你创建的Block Design包装成可综合的模块。
3.2 综合、实现与生成比特流的完整操作
完成HDL Wrapper生成之后,在Flow Navigator中点击Generate Bitstream。这一步会自动执行综合、实现和比特流生成三个阶段,中间会弹出对话框提示你运行逻辑综合,直接确认就行。
整个过程的耗时取决于电脑性能,一般十几分钟到半小时不等。如果你的工程比较简单,也可以在Flow Navigator中一步一步分别执行Run Synthesis、Run Implementation,这样能在每个阶段发现问题时及时修正,而不是等到最后一起报错。
综合阶段最常见的错误是语法错误或IP核配置错误。到时候看Vivado下面的Messages窗口,红色错误会直接告诉你哪个文件哪一行有问题。实现阶段最常见的问题是时序违例,如果看到Timing failed的警告,先确认是不是时钟约束没加对。时序问题对于Hello World这种简单工程来说几乎不会出现,但如果你的工程跑到几百兆赫兹的时钟,就要认真对待约束了。
比特流生成完成后,会有三个输出:综合后的网表、实现后的网表和最终的比特流文件。这个比特流后面要打包进BOOT.BIN,不能删。
3.3 Implement Design变红:原因分析与排查思路
搜索热词里有不少人问到Vivado Implement Design变红,也就是实现过程报错或失败。这个问题在高版本Vivado里很常见,因为实现阶段要做布局布线、时序优化、功耗优化等一大堆事情,任何一个环节出了问题都会让整个Implement过程失败。
我用过的排查思路是这样的:第一步,先看综合是否通过。如果综合都没过,实现肯定过不了,这时候要回到综合阶段把错误清理干净。第二步,如果综合通过但实现变红,打开Implementation窗口,展开具体步骤,看一下是哪一步失败了。常见的是Placement阶段失败,比如资源不够用、引脚分配冲突。
引脚分配是一个很容易出错的地方。如果你在.xdc约束文件里分配的引脚与Block Design中的引脚冲突,实现阶段会报错。比如你在Block Design中配置了UART,但又自己手动约束了同样的引脚,就可能出问题。我的习惯是Block Design里的外设让Vivado自动分配引脚,只在外部逻辑需要的地方写.xdc约束。
另外,2023.2版本的实现过程默认开启了增量编译和智能优化选项,有时候这些高级选项反而会带来问题。如果实现一直失败,可以在Project Settings里把Implementation的Strategy改成默认的Performance_Explore,关闭增量编译,很多莫名其妙的问题会消失。
3.4 导出XSA文件:硬件的“菜单”导出
比特流生成成功之后,下一个关键动作是导出XSA文件。回到Vivado主界面,点击File -> Export Hardware,在弹出的对话框中勾选Include bitstream这个选项。这一步非常关键,如果不勾选比特流,后面Vitis里虽然能写程序,但无法把硬件逻辑配置到FPGA里。
导出的XSA文件本质是一个ZIP压缩包,里面包含了硬件平台描述、驱动信息、地址映射和比特流。你可以把XSA理解成一张饭店菜单,告诉Vitis有哪些外设、用哪个地址访问、什么驱动程序可用。Vitis基于XSA创建硬件平台,然后在这个平台上开发应用程序。
导出之后建议把XSA文件拷贝到独立的文件夹里,命名规范一点,比如zcu102_base.xsa。因为这个文件后续会反复使用,而且如果你改了硬件配置,需要重新导出并替换掉旧的XSA,命名清晰能避免自己搞混。
4. Vitis里的Hello World:从平台创建到串口打印
4.1 打开Vitis并创建硬件平台
从Windows开始菜单或Vivado安装目录下启动Vitis,它会让你选择一个工作空间目录。工作空间只是Vitis存放工程文件的目录,选一个方便管理的路径就行,不一定要和Vivado工程放在一起。
Vitis启动之后,在Welcome界面点击Create Platform Project,或者通过File -> New -> Platform Project来创建硬件平台。在向导中选择XSA文件,工具会自动读取硬件信息并生成平台。平台生成过程比较耗时,因为要处理驱动库和BSP,耐心等一会儿。
创建完平台之后,Vitis会显示一个platform项目的结构,分为ps7_cortexa9_0和ps7_cortexa9_1两个处理器,在左侧的Platform视图里能看到。对Hello World来说,只用CPU0就够了。另外一个重要细节是Platform工程里可以勾选Generate or reuse a standalone BSP,这个BSP就是硬件板的板级支持包,包含了串口、DDR、中断这些外设的驱动库,后面程序里调用printf、XUartPs这些API都靠它。
4.2 新建Hello World应用程序
平台创建好之后,在Vitis主界面的菜单栏选中已创建的平台工程,右键点击,选择New -> Application Project,或者直接新建一个Application Project。向导会让你关联一个已有的平台,选择刚才创建的Platform Project,然后给应用程序起个名字。
在模板选择页面,Vitis提供了一堆模板,包括Hello World、空应用、内存测试、外设测试等。选择Hello World模板,然后点击Finish。Vitis会自动生成main.c文件,里面已经写好了最简单的打印程序。
新生成的Hello World模板默认会创建一个Hello World的线程,并且会在串口上打印信息。不同版本的模板可能略有差异,2023.2的模板代码里包含一个多线程的示例,跑起来之后还会打印多线程相关的信息。如果只想打印最简单的Hello World,可以把模板代码里多余的部分删掉,只保留初始化必要的内容。不过对新手来说,直接用模板改一改也可以。
4.3 编译与下载调试的完整实操
编译应用程序的方法是点击工具栏上的Build或直接按Ctrl+B。Vitis会在后台调用ARM编译器交叉编译代码,并把生成的可执行文件和相关依赖打包到一起。编译成功后,在Debug或Release目录下会生成扩展名为.elf的文件。
如果你想在本地用QEMU仿真验证,可以在Run Configuration里配置使用QEMU运行,但这里不推荐新手用仿真代替实际硬件。真正能确认硬件是否工作正常的方式是下载到板子上跑。
连接好开发板电源、JTAG和串口线之后,在Vitis主界面右键点击应用程序工程,选择Run As -> Launch Hardware。如果JTAG连接正常,Vitis会自动下载比特流和应用程序到板子上运行,然后在Serial Terminal里看到打印信息。这里需要额外打开一个串口终端,Vitis自带Terminal视图,也可以使用电脑上的串口助手来查看输出。
看到Hello World打印出来,恭喜你,整条流水线基本通了。但这个Hello World只是从JTAG加载到内存里运行的,断电之后程序就没了,下一步才是真正的固化。
4.4 下载调试不识别芯片的排查方法
热词里有个高频问题:Vitis下载调试的时候不识别芯片是什么情况。这个问题常发生在刚连接硬件、准备下载程序的时候,表现为Vitis报错说找不到target或者无法识别设备。
排查顺序很重要。先看硬件链路:JTAG线是否插紧、电源是否正常、开发板的模式跳线是否拨到了JTAG模式。然后看驱动:打开Windows设备管理器,查看是否存在带黄色感叹号的设备。如果驱动有问题,手动更新到Vivado安装目录下的驱动。
常见原因之一是电脑上装了多个Xilinx工具,驱动版本冲突导致Target无法识别。解决办法是在设备管理器里把所有与Xilinx或Digilent相关的设备卸载干净,重新插拔设备,让系统从最新的Vivado驱动目录安装驱动。
另一个原因是板子的PS端没有启动,导致JTAG链上检测不到设备。有些板子在纯JTAG模式下需要给PS端提供时钟和电源,板上的跳线设置不对就会出现这种情况。建议对照开发板手册检查模式跳线,确保设置为JTAG boot模式而不是QSPI或SD卡启动模式。
5. BOOT.BIN生成与固化的完整方案
5.1 为什么需要BOOT.BIN:Zynq启动流程的前世今生
Zynq和普通单片机不一样,它上电之后需要一个完整的启动引导过程。简单来说,Zynq的BootROM在芯片出厂时固化了一段代码,上电后BootROM会根据模式引脚的电平决定从哪里加载启动镜像。它可能会从SD卡、QSPI Flash、JTAG等不同的地方去找启动镜像。
启动镜像需要一个特定的格式,这个格式就是BOOT.BIN。BOOT.BIN内部通常包含三部分:FSBL、比特流、应用程序或者用户程序。FSBL是First Stage Boot Loader的缩写,它是第一个在PS端运行的代码,负责初始化DDR、加载比特流到PL端、然后把应用程序从启动介质中复制到DDR并跳转执行。
所以BOOT.BIN不是某个单一文件的改名,而是一个有固定格式的启动镜像。如果你直接把应用程序.elf文件改名为BOOT.BIN放到SD卡里,Zynq是无法执行的。理解了这一点,你就明白了Vitis里生成BOOT.BIN时为什么要按顺序添加FSBL、比特流和应用程序。
5.2 在Vitis中创建启动镜像的详细步骤
打开Vitis菜单栏的Xilinx -> Create Boot Image,在弹出的对话框中选择Create new boot image。然后在Boot image partitions这个区域,按照顺序添加三个文件:
第一个添加FSBL文件。FSBL的工程名一般带fsbl字样,比如zcu102_fsbl,编译后在Debug目录下生成fsbl.elf。如果找不到,可以在创建平台工程时,右键勾选Generate FSBL,或者在平台的BSP设置中选择生成FSBL。
第二个添加比特流文件。选择你在Vivado里生成的.bit文件。如果前面的XSA已经包含了比特流,也可以在添加分区时选择从XSA导入比特流。但建议手动指定.bit文件,避免路径混乱。
第三个添加应用程序的.elf文件。就是刚才Hello World工程编译后生成的elf文件,注意选择正确的CPU。如果是双核工程,需要指定运行在哪个核上。
加好三个文件之后,Boot image format选择BIN,输出路径填好,点击Create Image。生成的BOOT.BIN会出现在你指定的目录里。
5.3 分区顺序与参数设置的注意事项
生成BOOT.BIN时有几个容易踩坑的细节。第一个是分区顺序。FSBL必须在第一位,因为BootROM要先加载它。比特流和应用程序的顺序可以变化,但FSBL必须在最前面,而且分区表里的顺序本质上决定了它们被处理的先后顺序。实践中我总是保持FSBL、bit、elf这样的顺序,已经形成了肌肉记忆。
第二个是启动模式。在Create Boot Image对话框的BOOT Mode区域,需要根据你的实际启动介质选择。如果你打算从QSPI Flash启动,选择qspi;如果从SD卡启动,选择sd。这个参数会影响FSBL如何配置启动相关引脚,选错了会导致启动失败。
第三个是Zynq UltraScale+和Zynq-7000的差异。Zynq-7000的BOOT.BIN相对简单,而Zynq UltraScale+系列还需要额外的PMUFW固件,制作镜像时要多添加一个pmufw.elf。如果你用的是MPSOC系列的板子,别少了这一步。
另外提醒一下,fsbl.elf一般在Vitis编译生成之后就在工程的Debug目录下,如果你找不到,可以在平台的psu_cortexa53_0或ps7_cortexa9_0的BSP设置里勾选Generate boot artifacts,重新构建平台就会生成。
5.4 SD卡启动与QSPI Flash固化实战对比
生成BOOT.BIN之后,把启动介质准备好,就可以固化板卡了。常用的两种媒体是SD卡和QSPI Flash。SD卡适合开发和调试,复制文件方便,改程序只要换一张卡或覆盖文件就行。QSPI Flash固化适合最终产品的交付,程序直接焊在板子上,上电就启动,但速度比SD卡慢,而且擦写次数有限。
SD卡启动步骤:
- 准备一张FAT32格式的SD卡,最好用干净的小容量卡
- 把生成的BOOT.BIN拷贝到SD卡根目录
- 修改开发板启动模式跳线为SD卡启动
- 插卡,上电,串口终端里应该能看到启动日志和Hello World打印
QSPI Flash固化有两种常用方式。第一种是通过Vivado Hardware Manager的Hardware Session向QSPI Flash写入数据,操作方式是在Hardware Manager里右键点击器件,选择Add Configuration Memory Device,然后选择QSPI Flash型号,把BOOT.BIN写入。第二种是在Vitis的命令行里用program_flash工具,需要指定FSBL、应用程序和比特流,工具会自动打包并写入Flash。
我在首次做QSPI固化时遇到一个很典型的问题:写入明明成功,但重新上电后板子还是没反应。后来发现是把启动模式跳线拨错了,跳线还停留在JTAG模式,BootROM根本没有从QSPI加载。检查跳线以后一切正常。类似这种“明明都对了就是不工作”的问题,十有八九是模式设置的问题,建议先检查启动模式。
6. 常见报错与实战排查技巧
6.1 License相关报错速查表
Vivado的License报错花样很多,我把常见的错误码和含义整理成表格,方便你遇到问题的时候直接对号入座:
| 错误码/提示 | 含义 | 可能原因 | 解决方法 |
|---|---|---|---|
| 2037 | License文件无效或过期 | License文件格式错误、版本不匹配 | 重新申请并加载免费版Standard License |
| 301 | License不可用 | License与安装版本不匹配 | 确认安装版本和License版本一致 |
| 210 | 端口被占用 | License服务器配置问题 | 检查环境变量XILINXD_LICENSE_FILE是否存在且正确 |
| No feature | 缺少功能授权 | 使用的功能是付费功能,免费版不支持 | 确认功能是否为Standard版支持范围 |
如果你用的是自己申请的标准版License,还要注意绑定时的Host ID信息。申请的License文件会绑定到电脑的MAC地址或机器码,如果你换了电脑,需要重新申请。
6.2 WinPcap安装失败的终极解法
WinPcap在Vivado安装过程中负责网络相关的包捕获功能,特别是用于硬件调试时的以太网调试。很多人在Windows 10或Windows 11上安装WinPcap时遇到失败,表现为 installer报错、提示服务安装失败或者安装完成后仍然提示未安装。
这个问题的根源是WinPcap太老了,新版Windows对底层网络驱动安装限制变严。解决方法是先以管理员身份运行安装程序,右键选择以管理员身份运行,如果还不行,去WinPcap官网下载兼容版本手动安装,或者在设备管理器中把原有的WinPcap设备删除再重装。
如果你是做纯JTAG调试,WinPcap失败其实不影响核心功能,但为了保险起见,我还是建议把它装好。Vivado的Hardware Manager本身并不依赖WinPcap,只有使用虚拟IO或以太网相关调试功能时才需要它。如果你确定自己用不到网口调试,忽略这个组件也能顺利跑通Hello World。
6.3 生成比特流失败与Implement变红
生成比特流失败的原因很多,但新手遇到最多的是两类。第一类是综合或实现时报错,比如代码里写错了模块名、端口没对齐,这类错误根据报错信息逐条修正就行。第二类是时序违例,实现阶段工具无法满足时序收敛的要求,导致流程失败。
如果是纯Hello World工程遇到时序问题,几乎不可能是代码问题,更可能是约束文件有问题。排查方法是打开Implementation窗口,点击Timing Summary,看一下违规路径在哪里。很多情况下是因为没有给时钟添加约束,Vivado默认的时钟频率过低或过高,导致工具无法正确优化。
另外,在2023.2版本中,如果生成比特流时选择了替换原比特流或者生成了加密比特流,也容易出现奇怪的问题。对新手来说,保持默认设置就好,不要勾选那些高级选项。我之前有一次生成比特流一直失败,最后发现是在设置里误开了write_bitstream的加密选项,关掉之后一下就通过了。
6.4 JTAG连接与目标芯片识别问题
前面4.4提到过下载调试不识别芯片,这里补充几种特殊工况。第一种是Vivado Hardware Manager能识别设备,但Vitis里就是报错找不到target。这种情况多数是因为Vitis和Vivado的版本不一致,或者同时启动了两个工具抢占了同一个JTAG接口。
第二种是Target Chain里有设备但显示为Unknown,这种情况多半是FPGA没有配置成功,或者PL端的JTAG链上某个芯片状态异常。你可以尝试在Hardware Manager里先关闭回读,手动指定设备类型,也可以试试断电重新上电,让器件完全复位后再试。
第三种情况是Linux虚拟机里跑Vivado连接USB-JTAG时出现权限问题,这类环境需要把当前用户加入dialout或plugdev组。如果你是直接在Windows下操作,就不用关心这个问题。整体来说,大部分识别不到芯片的问题都能通过重新安装驱动、换USB口、重新上电这三板斧解决,别急着重装Vivado。
6.5 Vitis闪退与工程损坏的应对策略
很多新手的Vitis用着用着就闪退了,有时候是打开某个工程时闪退,有时候是编译到一半崩了。这个话题在网络上也热过一阵子。Vitis基于Eclipse框架,Eclipse系工具的通病就是工作空间里的元数据损坏会导致各种异常。
第一个应对策略是定期清理工作空间。Vitis的项目配置都存放在工作空间目录的.metadata文件夹里,这个文件夹损坏常常导致闪退。当Vitis启动异常时,先尝试清空.metadata,再重新导入工程,通常能解决启动崩溃的问题。
第二个策略是启用日志。Vitis的日志文件在安装目录或用户目录下,崩溃后去查hs_err_pid和eclipse日志,能定位到具体是哪个插件出了问题。不过对新手来说,看日志的门槛较高,我用得最多的方法还是备份工作空间、定期重建。好在这套流程里工程都很小,重建的成本很低。
第三个建议是升级到Vivado/Vitis 2023.2的后续补丁版本。Xilinx会在官方支持页发布Update版本,修复了不少Vitis的崩溃问题。如果你的版本还停留在2023.2初始发布版,建议检查一下是否有SP补丁。
6.6 固化后启动失败的常见原因
这是做完BOOT.BIN之后最容易遇到的坑:JTAG调试一切正常,固化到Flash或SD卡之后就不启动了。我总结出三个高概率原因。
第一,启动介质本身没有准备好。SD卡没有格式化成FAT32,或者QSPI Flash型号不匹配。第二,启动模式跳线没拨对。很多开发板有多个拨码开关,分别控制启动模式、JTAG使能和电压级别,一个开关拨错,整个启动就拜拜了。第三,开机之后PS端可以启动到FSBL,但FSBL找不到后续的比特流或应用程序,这通常是因为BOOT.BIN制作时分区顺序或文件路径有问题。
排查启动失败可以接串口看看打印信息。如果串口一点输出都没有,那问题大概率在硬件启动模式或电源;如果串口有BootROM的输出但没有FSBL的输出,说明BOOT.BIN的格式或分区有问题;如果FSBL已经打印但卡在加载比特流的阶段,大概率是PL端配置失败或时钟有问题。这种分阶段定位的方法,能帮你快速缩小范围,不用瞎猜。
7. 一点实操心得与扩展建议
跑通整个流程之后,我个人有几点体会比较深。
第一,这份流程里的每一步都是有用的,不要跳过任何一步。我曾经图省事试过不生成比特流直接导出XSA,结果Vitis平台创建出来之后,程序编译能过,但跑起来后FPGA部分的逻辑完全没有初始化。看似是硬件逻辑的问题,其实是当时没把bitstream包含进去。
第二,建议把工程文件整理得井井有条。Vivado工程、XSA文件、Vitis工作空间、生成的BOOT.BIN,这些文件散落各处。我现在的习惯是建立一个总目录,里面按照hardware_2023.2、software_vitis、boot_image这样的子目录分类存放,每个目录都放一个README说明当时用的版本和配置。过几个月回看项目,你会感谢当时的自己。
第三,既然已经走通了裸机Hello World,后续可以考虑往这几个方向扩展:一是移植轻量级RTOS到Zynq上,学习任务调度和驱动的写法;二是在PL端添加自定义外设或加速器,然后用AXI总线和PS端通信;三是尝试跑一个最小的Linux系统,理解u-boot、内核和设备树的启动流程。这三条路都能拓展你的能力边界,但每一路都离不开今天打下的基础。
最后分享一个关于BOOT.BIN的小技巧:生成之后,用十六进制编辑器打开文件,前几个字节应该有固定的启动头标识。如果你做完了镜像却怀疑文件格式有问题,可以先看一眼有没有这个启动头,再决定要不要怀疑软件流程。这个检查动作帮我快速确认过不少次问题到底出在镜像制作还是启动流程。