做FPGA固件升级这些年,Multiboot一直是我认为最值得花时间啃透的功能之一。手里一批板卡已经部署到现场,升级固件不可能每次都拆机箱、焊下载器,远程通过SPI Flash引导多镜像的方案就成了刚需。Vivado的Multiboot功能正好解决这个问题:它允许把两个甚至多个配置镜像放在同一条SPI Flash里,系统启动时先加载一个最稳妥的Golden镜像,正常运行后再加载功能完整的Update镜像,万一Update镜像有问题,还能自动回退到Golden镜像,板子不至于变砖。
这篇文章就围绕一套我实际跑通的流程来写:从Flash分区设计、Vivado工程配置、镜像生成,到MCU/软核触发Multiboot跳转,最后到常见故障的排查思路。适合正在做FPGA远程升级、或者准备在SPI Flash上做多镜像启动的工程师参考,一些细节是我踩过坑之后整理出来的,应该能帮你少走弯路。
1. 为什么需要Multiboot:远程更新方案的整体设计思路
FPGA远程更新本质上是“把新比特流写入配置存储介质,然后让FPGA重新加载新配置”。但这个过程有个核心矛盾:配置存储介质(比如SPI Flash)本身只有一个,如果直接把新镜像覆盖掉旧镜像,而新镜像写坏了、下电时序不对、或者本身就有Bug,那FPGA重新上电后就可能加载失败,整块板变砖。这就是Multiboot存在的意义。
1.1 双镜像架构:Golden镜像与Update镜像的分工
Multiboot方案在SPI Flash里放两个镜像。第一个是Golden镜像,也就是“工厂镜像”,存放在Flash最开始的地址,通常包含最基础的固件逻辑,功能上不必太完整,但必须保证能正常加载、能执行最基本的操作(比如活下去、能响应简单的升级命令)。第二个是Update镜像,存放在Golden镜像之后的地址,存放真正完整的功能逻辑。
这两者的关系,我习惯用一个比喻:Golden镜像类似于电脑的BIOS恢复分区,Update镜像类似于主系统。正常情况下系统从主分区启动,大部分时间在跑主系统;但主系统坏了,Reset之后还能从恢复分区重新起来,机器不会彻底瘫掉。Multiboot的Fallback机制就是这个道理——上电默认从Flash地址0x0加载Golden,加载成功后在软件里通过IPROG命令跳到Update镜像的地址重新配置;如果Update镜像加载失败,FPGA会自动回退到Golden镜像继续运行。
这里有一个值得注意的点:Golden镜像不一定要和Update镜像完全独立,它可以是Update镜像的一个子集。比如Update镜像里做了DDR读写测试、网络通信、算法加速等全部功能,而Golden镜像里只保留最简的串口打印和GPIO控制,用来确认“板子还活着、还能进升级模式”。这样做的好处是Golden镜像体积小,编译时间短,出错的概率也低,更稳妥。
1.2 Multiboot的工作机制:WBSTAR寄存器与IPROG命令
要把“跳到哪个地址启动”这件事落实,关键在两个东西:WBSTAR寄存器(Warm Boot Start Address Register)和IPROG命令(Internal PROGRAM_B)。
WBSTAR寄存器在7系列和UltraScale系列里都存在,它保存的是“下一次内部重配置时要从Flash的哪个地址开始加载”这一信息。注意它是一个16位的寄存器,保存的是地址的高16位,也就是说地址必须按64KB对齐。比如Update镜像放在0x0080_0000,那WBSTAR里写入的就是0x0080。如果地址不按64KB对齐,FPGA在回跳的时候会直接按对齐后的地址去找镜像,容易落空。
IPROG命令则是一个触发信号,软件里向ICAP(Internal Configuration Access Port)或者通过MCU控制FPGA的PROGRAM_B引脚拉低再拉高,让FPGA重新进入配置流程。但Multiboot选的是IPROG,因为它可以在不需要外部引脚动作的情况下,直接从内部触发重配置,而且会读取WBSTAR里预设的地址,把新地址作为本次重配置的首选加载位置。
流程笼统说就是这样:
- 板卡上电,配置逻辑先从Flash地址0x0加载Golden镜像,构建起最小系统。
- 软件(MCU或者软核)决定进入升级模式,向WBSTAR写入Update镜像的起始地址。
- 软件向ICAP发送IPROG命令,FPGA内部触发重配置。
- FPGA配置逻辑转向WBSTAR指定的地址,加载Update镜像。
- Update镜像加载中如果CRC校验失败、IDCODE不匹配、或者同步字收不到,配置逻辑自动清空WBSTAR,回退到Flash地址0x0重新加载Golden镜像。
这个回退机制是Xilinx在硅片层面做了硬件支持的,不需要额外的外部逻辑参与。前提是Update镜像必须在同一片SPI Flash里,且Golden镜像所在区域不能被擦除。如果设计上把Flash分成两个独立分区,那就必须从设计规范上保证任何升级命令都不能触碰Golden分区,这是预防变砖的第一道闸门。
1.3 为什么用SPI Flash而不是其他介质
FPGA配置介质的选择其实很宽泛:有BPI(Parallel NOR Flash)、SPI Flash、SD卡、QSPI Flash等。我最终选SPI/QSPI Flash,理由很直接:
- 引脚占用极少,通常只需要4根或6根信号线(CS、CLK、MOSI、MISO,QSPI再加IO2、IO3)。
- 单芯片容量可以做到64MB甚至更大,一个镜像几十MB完全放得下,还可以放多个镜像、文件系统、日志区。
- SPI Flash几乎每家FPGA板卡都标配,量产和采购都很成熟。
但要注意,SPI Flash的读速度天然比BPI NOR Flash慢。不过对于配置这种“一次性加载、之后不再访问”的场景,慢一点完全没关系。真正需要在意的是SPI Flash的型号规格(容量、电压、是否支持Quad/Dual Read)要和Vivado里设置匹配,不然生成MCS文件时地址映射会出错。
2. 硬件准备与Vivado工程设置:动手前的关键配置
Multiboot不只是一个软件配置功能,它和硬件设计强相关。如果板卡上FPGA的配置引脚没有预留正确,或者SPI Flash的位置摆放不对,后续做远程升级基本就无从谈起。这块我在多个项目里吃过亏,拿出来讲一讲。
2.1 SPI Flash容量规划与分区设计
先算容量。一个普通的7系列FPGA(比如Artix-7 200T)的比特流文件大小通常在10MB到40MB之间——取决于资源利用率、压缩设置、配置位流等。如果开启比特流压缩(set_property BITSTREAM.GENERAL.COMPRESS TRUE),文件能缩小到原来的1/2甚至1/3,这对远程升级的传输时间很有价值。UltraScale系列的比特流体积会更大,部分器件接近70MB,此时Flash容量选64MB甚至128MB更稳妥。
分区建议这样规划:
| 分区 | 起始地址 | 大小建议 | 存放内容 |
|---|---|---|---|
| Golden | 0x000000 | 8MB~32MB | 工厂镜像、最小引导逻辑 |
| Update | 0x00800000起 | 按需 | 功能完整镜像 |
| 标志区/升级包缓存区 | 末尾 | 4MB~8MB | 软件标志位、升级包暂存、日志 |
地址的颜色块怎么分,很考验经验。我建议Golden分区留足余量,不差这1-2MB。考虑极端情况,一个增强版Golden镜像可能需要升级到更大的资源和更多的IP,Flash太小就变成硬约束,改Flash封装是板级灾难。
另外要考虑Flash擦除块大小的对齐。W25Q256(Winbond 256Mbit)这类Flash的扇区一般是4KB,块是64KB。分区的起始地址最好按64KB对齐,这既和WBSTAR的对齐要求一致,也方便擦写。不然软件擦写的时候,一个升级包可能横跨两个块,擦除或写入稍有不慎就可能破坏相邻分区的数据。
2.2 Vivado里配置SPI Flash相关的关键参数
在Vivado里生成比特流之前,有几个属性必须设好。在综合、布局布线完成后,打开Edit Device Properties或者在约束里添加:
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design] set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.SPI_FALLBACK Yes [current_design] set_property BITSTREAM.CONFIG.OVERTEMPPOWERUP_DISABLE TRUE [current_design]第一行是配置时钟速率,默认可能只有20MHz或者更慢,为了可靠可以配到50MHz左右。如果SPI Flash支持更高读时钟,也可以适当提高,但不建议一上来就冲极限,先稳定跑通,再提速度。
第二行是SPI数据位宽。Master SPI模式下通常支持1-bit、2-bit、4-bit。QSPI Flash肯定走4-bit,加载速度能快很多。这里要注意:如果Flash不支持Quad Read命令,却配了4-bit,加载会失败。所以要么确认Flash型号支持,要么直接配1-bit先跑通,后面再优化。
第三行是Fallback使能。Multiboot的自动回退机制必须在比特流里显式打开,如果不设置,Update镜像加载失败后就静止在失败状态,不会自动跳回Golden。这个属性极重要,我见过好几个项目就是漏了这个,现场设备升级失败后需要人为重新上电才能恢复,非常被动。
第四行是温度相关,不是Multiboot必需,但我习惯加上,确保因为过温导致的配置失败不让系统误判为Multiboot问题。
此外还有一个需要注意的属性:
set_property BITSTREAM.CONFIG.NEXT_CONFIG_ADDR 0x00800000 [current_design]这一条是为了生成支持“双镜像启动流程”的比特流而配置的。但对于Update镜像本身,这个属性配不配都没有关系,因为在运行时是由MCU/软核显式写WBSTAR的。如果你用的是Vivado自带的“Program Flash”向导,在生成MCS时它会让你选“Golden Image”和“Next Image”,本质上也等价于替你把NEXT_CONFIG_ADDR这种属性加进去。
2.3 管脚分配与硬件电气注意点
SPI Flash在板上和FPGA的连接,建议尽量靠近,走线短。这与信号完整性有关,但更高频的场景是板子在现场,环境恶劣,SPI Flash虚焊或者连接器松动,就会导致配置加载间歇性失败。远程升级设计里要额外考虑这些,因为现场人员不可能去动烙铁。
FPGA的配置模式引脚M[1:0]需要设置为Master SPI模式(通常M[1:0]=0b10,具体见器件手册),这个在硬件设计时就要固定拉好。不要在软件里指望能改——配置模式是硬件决定的。如果这几个引脚悬空或者被拉成从模式,FPGA上电就等外部主机来配置,不会主动去读SPI Flash,Multiboot自然无从谈起。
另外SPI Flash的WP#(写保护)引脚和HOLD#引脚千万不要悬空,要么接上拉电阻,要么由FPGA控制。HOLD#悬空时可能因为噪声导致Flash误进入Hold状态,读数据卡死。WP#悬空时如果Flash内部寄存器被意外写保护,远程写Flash就会失败,并且排错起来极其痛苦。这两根引脚我在PCB Layout检查里必查。
3. 镜像生成与SPI Flash烧写:从BIT到MCS的完整链路
Vivado本身提供了一条龙工具链:从综合、实现、生成比特流,到直接烧写SPI Flash。但Multiboot场景需要两个镜像合并成一条MCS,或者分两次写入Flash,流程上有些细节需要掰开说清楚。
3.1 生成Golden与Update两张镜像
开发环境中,我们需要各自独立综合、实现两个工程。这很关键:一张BIT对应一个FPGA设计,Golden和Update的硬件配置可能不同,但必须都在同一个FPGA型号下编译。
一个常见做法是使用同一份RTL,但通过宏定义区分:
`ifdef GOLDEN_IMAGE // 极简逻辑:串口打印、GPIO控制、升级命令响应 `else // 完整功能逻辑 `endif综合时给不同的Vivado工程设置不同的宏即可。这样做的好处是降低了双工程维护成本,也便于确保Golden镜像的硬件约束(比如引脚分配)和Update完全一致——尤其是SPI Flash、时钟、复位这些引脚,如果两张镜像用的引脚不一致,Multiboot跳转后外设会复位到不确定状态,后患无穷。
在生成比特流前,务必再检查一次参数,重点确认:
- 配置模式已经是Master SPI。
- SPI_BUSWIDTH设置与Flash能力匹配。
- SPI_FALLBACK已打开。
- 时钟约束正确,比特流生成不报错。
两张镜像生成后,可以分别在本地先用JTAG下载到FPGA验证功能,确认无误后再做MCS合并。
3.2 合并镜像:生成包含Golden和Update的单一MCS文件
合并镜像的方式有很多,我推荐直接用Vivado硬件管理器里的“Add Configuration Memory Device”流程。具体步骤如下:
- 进入Vivado Hardware Manager,连接开发板。
- 右键FPGA设备,选择“Add Configuration Memory Device”。
- 在弹出的窗口里选择对应的SPI Flash型号(比如W25Q256)。
- 在“Configuration Memory Part”窗口下面,有一个“Address”设置,默认是0x0,我们先烧Golden镜像,所以这里填0x0,加载Golden的BIT文件。
- 烧写成功后,不要断开,再次执行“Add Configuration Memory Device”,这次在Address里填Update分区的起始地址,比如0x00800000,加载Update的BIT文件。
- 下载完成后,Flash里就有了两个镜像,重新上电会先加载Golden,之后如果想验证Multiboot跳转,再在软件里执行跳转命令。
如果不想每次都进硬件管理器手动烧,也可以先把Golden和Update的BIT转换成一个MCS文件,一次性烧写。在Tcl Console里可以这样操作:
write_cfgmem -format mcs -size 64 -interface spix4 \ -loadbit "up 0x0 golden.bit" \ -loadbit "up 0x00800000 update.bit" \ -file combined.mcs这个命令把两个bit文件打包成一个MCS。参数里-up表示该bit作为image文件烧写,-size要选择实际Flash容量(单位MB),-interface要和SPI_BUSWIDTH一致(spix4对应4-bit)。
生成的MCS可以直接用Vivado Hardware Manager烧录。也可以让产线使用第三方的Flash烧录器(如DediProg、BPMicro等)先把MCS文件烧录到Flash芯片里,再贴片。两种方式都行,但第三方烧录器对MCS格式的支持各有不同,建议产线用的烧录器提前试一下,确认它能识别这个文件。
3.3 用Vivado直接固化:从BIT到Flash的另一种方式
有的工程师习惯在连接硬件的情况下直接生成固化文件。这其实就是在Hardware Manager里操作,但要注意一个细节:如果你打开Hardware Manager后选择的不是对应的FPGA型号,而是用“Open Target”自动探测,程序返回的JTAG ID可能和开发板上的标准ID不同,可能导致无法识别到Flash。这时需要手动指定FPGA型号,或者在Vivado工程里先做“Add Configuration Memory Device”再连接。
另外一个坑:如果开发板上FPGA的模式引脚M[1:0]没有正确设置成Master SPI,Hardware Manager虽然能识别到FPGA,但烧写Flash后重新上电,FPGA不会自动去读Flash,看起来像是“烧写没有生效”。排错时先查配置模式引脚,再查Flash的CS/CLK信号是否有正常活动。
4. 远程更新的核心引擎:触发Multiboot跳转的软件实现
镜像和Flash都准备好了,现在要解决的是“如何让FPGA从Golden跳到Update”的问题。这个环节一般由板载MCU、软核处理器(MicroBlaze)、或者一段状态机逻辑来完成。
4.1 方式一:外部MCU/ARM通过GPIO控制PROGRAM_B和SPI Flash
如果你的板子上有一颗MCU(比如STM32、Zynq的PS侧),最直接的控制方式是:
- MCU通过GPIO拉低FPGA的PROGRAM_B引脚,保持至少几百纳秒。
- MCU再拉高PROGRAM_B,FPGA进入重新配置流程。
- 在FPGA重新配置前,MCU需要先把WBSTAR的值写入FPGA。
但这里有个难点:WBSTAR寄存器不在外部总线空间里,用GPIO控制PROGRAM_B无法直接写WBSTAR。如果完全靠外部引脚触发重配置,FPGA会按黄金启动流程回0x0。所以外部MCU控制方式真正要做的,是MCU向FPGA发送一段特殊的配置序列,这段配置序列里包含“设置WBSTAR + 触发IPROG”的指令。
其实更常见的工程方案是:MCU预先通过SPI接口把Update镜像写入Flash,然后在特定寄存器(比如用户自定义的软寄存器)里写一个“upgrade”标志,再触发FPGA复位。FPGA复位加载的是Golden镜像,Golden镜像启动后第一件事就是检查升级标志,如果存在,就主动执行Multiboot跳转。
这种方式的好处是职责分离:MCU管“写Flash”,FPGA管“重配置”。但要特别注意,MCU写Flash的时候必须关掉FPGA对Flash的访问——因为FPGA配置完成后一般不会再读Flash,但这不代表时序上不会冲突。稳妥做法是MCU在写Flash前把FPGA复位住(保持PROGRAM_B拉低),写完Flash后再释放。
4.2 方式二:FPGA内部软核/逻辑通过ICAP触发Multiboot
如果FPGA设计里本身就有MicroBlaze或者一段状态机,那就不需要外部MCU参与了,直接使用ICAP原语。
ICAP原语在7系列里叫ICAPE2,在UltraScale里叫ICAPE3。通过它,软核可以向FPGA内部配置逻辑发送IPROG命令。下面这段代码演示如何用AXI接口封装一个简单的ICAP控制器,实现WBSTAR写入和IPROG触发:
module icap_warm_boot #( parameter NEXT_IMAGE_ADDR = 32'h00800000 )( input wire clk, input wire rst, input wire trigger, output reg done ); localparam CMD_WBSTAR = 32'h30020001; // Write WBSTAR localparam CMD_IPROG = 32'h30008001; // IPROG command localparam CMD_NOP = 32'h20000000; // NOP localparam WBSTAR_VALUE = {16'h0000, NEXT_IMAGE_ADDR[23:8]}; // 地址高16位 reg [63:0] shifter; reg [3:0] state; reg [1:0] cmd_index; always @(posedge clk or posedge rst) begin if (rst) begin state <= 0; done <= 0; end else begin case (state) 0: begin done <= 0; if (trigger) begin state <= 1; cmd_index <= 0; end end 1: begin if (cmd_index == 0) shifter <= {CMD_WBSTAR, WBSTAR_VALUE}; else if (cmd_index == 1) shifter <= {CMD_IPROG, CMD_NOP}; state <= 2; end 2: begin // 实际ICAP接口是32bit宽,需要按字节/半字发送,此处简化为状态推进 if (cmd_index < 2) begin cmd_index <= cmd_index + 1; state <= 1; end else begin state <= 3; end end 3: begin done <= 1; state <= 0; end endcase end end endmodule这段代码把关键命令简化成了状态机的推进,核心意图是让你理解命令序列的构成:先写WBSTAR,再发IPROG,中间用NOP填充32位对齐。这里有个细节:WBSTAR_VALUE提取的是地址的高16位,也就是NEXT_IMAGE_ADDR[23:8]。比如Update镜像放在0x00800000,高16位就是0x0080,写进WBSTAR后FPGA重新配置时就会从这个地址开始找镜像数据。
如果觉得手写状态机麻烦,也可以直接用Xilinx提供的AXI Hard IP:AXI QSPI或者AXI Configuration。MicroBlaze中使用AXI CDMA(Central DMA)把Update镜像从网络或SD卡搬到Flash,再写出WBSTAR和IPROG命令,整个过程就完整了。
4.3 远程更新的业务逻辑闭环
抛开底层时序,设计和“业务”相关的状态机时,我建议想清楚下面几条:
- 版本管理:Flash里要记录当前镜像的版本号,Update镜像自身也要带一个版本标识。软件在触发跳转前要检查更新包版本是否高于当前版本,避免旧包覆盖新包。
- 升级包完整性校验:在写Flash之前,MCU/软核先对整个升级包做CRC32或者SHA256校验,确认完整再写。不要为了省时间跳过这一步,远程升级最怕“传一半断掉”。
- 超时回退:设置一个看门狗,如果在指定时间内(比如10秒)没有成功跳转到Update镜像,强制触发Fallback回到Golden。这一步在Xilinx的硬件机制里是自动的,但如果升级流程是你自己控制的,仍然建议在MCU侧做一层超时保护。
实际项目中,我见过一个有效的做法是:Update镜像在启动后不久会主动向MCU发送一个“i am alive”的统一报文。MCU收到这个报文后,才认为升级成功,并把当前工作版本号更新到Flash的另一个区域。如果没收到,MCU就认为Update镜像有问题,主动复位FPGA触发Fallback。这套机制写起来不复杂,但对现场运维的帮助非常大。
5. 实战踩坑与排查:最容易翻车的几个环节
Multiboot本身在Xilinx文档里写得挺清楚,但实操起来问题层出不穷,而且很多问题不直接报错,需要结合波形、时序、日志去定位。我梳理了几个高频问题,几乎每个项目都会踩到一两个。
5.1 当配置逻辑卡死,无法Fallback到Golden镜像
有一个搜索热度挺高的说法叫“when configuration logic is stuck and unable to fallback when multiboot image”。我在现场真的遇到过这种状态:Update镜像加载失败后,FPGA既没有回退到Golden,也没有任何输出,看起来像死机了。
排查这类问题,第一步是确认Fallback在比特流里真的打开了。有些工程师在Golden镜像里开了Fallback,但Update镜像里没有开——这会导致模板误导。因为Fallback行为本质上是由“正在尝试加载的那个镜像”的配置头决定的,如果Update镜像的头里没有做允许Fallback的设置,配置引擎可能就停在错误状态不再动作了。
第二步是检查Update镜像的地址是否对齐。WBSTAR只认高16位地址,如果你的Update镜像起始地址是0x00800001(这显然不现实,但可能是转换脚本里粗心设置了偏移),FPGA会试图在0x00800000读取,结果出来的全是垃圾数据,配置必然失败。
第三步是检查ICAP命令时序。IPROG命令必须严格按照Xilinx文档中的32位对齐方式来发,否则FPGA会忽略这条命令。这里特别提醒,很多以“用MCU模拟ICAP时序”实现的项目,把命令拼装和位宽搞错了。ICAPE2的接口是32bit位宽,但一次配置操作中,IPROG命令需要连续写两个32bit字(命令字+参数),不能中间插入别的操作。
5.2 MCS烧录成功但上电不启动的排查思路
这种情况我遇到得最多。排查顺序是这样的:
- 确认模式引脚:M[1:0]是否已经固定为Master SPI模式,可以用万用表直接量引脚电平。
- 确认CS信号:上电瞬间用示波器抓FPGA连接SPI Flash的CS引脚,应该能看到一个低脉冲。如果CS完全没动作,说明FPGA没去访问Flash,大概率是模式引脚或配置时钟的问题。
- 确认Flash信号:用示波器抓CLK和MOSI,如果CS有活动但CLK没波形,大概率是配置时钟没起来或者配置模式不对。
- 确认Flash内容:用SPI Flash编程器读出Flash内容,检查0x0地址的镜像头是否正常,或者用Vivado的Verify功能对比Flash内容和BIT是否一致。
这里有一个笔者踩过的坑:某个项目里SPI Flash的HOLD#引脚在PCB Layout时被接到了一个FPGA的普通IO,而且默认状态是低。结果就是Flash一直处于Hold状态,FPGA读不到任何数据。排查了好几个小时才发现是HOLD#引脚的问题。所以,原理图阶段就一定要把HOLD#、WP#引脚的连接方式定好,这俩引脚绝不能简单悬空。
5.3 常见问题速查表
| 现象 | 可能原因 | 解决措施 |
|---|---|---|
| 上电后FPGA无任何加载动作 | 配置模式引脚M[1:0]不对 | 调整为Master SPI模式 |
| CS有信号,但CLK没波形 | 配置时钟没有起来 | 检查CCLK引脚连接,确认晶振/时钟源正常 |
| 加载到一半失败 | SPI_BUSWIDTH设置与Flash能力不符 | 将SPI_BUSWIDTH改为1或2,先跑通再优化 |
| 能加载Golden,但跳转后死机 | WBSTAR地址不对或Update镜像损坏 | 检查WBSTAR写入值,重新烧写Update |
| 跳转后不作任何动作,过一段时间自动回退 | Update镜像的头配置没有允许Fallback | 在Update镜像里也打开SPI_FALLBACK |
| 远程写Flash成功,但校验失败 | 写Flash时WP#没拉高或Flash被保护 | 检查WP#控制,关闭Flash写保护 |
| 跳转时同步字错误 | Flash读时序不满足 | 降低CONFIGRATE,或调整Flash读命令 |
5.4 一些实操上的经验和建议
我在多个项目上跑完Multiboot之后,有几点体会很强烈。
第一,Flash的分区规划一定要在项目一开始就确定,不要等到快量产了才回头改。分区地址一旦定下来,Golden镜像、Update镜像、软件升级脚本、产线烧录文件全都要跟着改,牵一发动全身。
第二,在本地调试时,不要每次都用整片擦除的方式重烧Flash。开发阶段建议只擦除Update分区,保留Golden不动。这样每次验证远程升级,只需要覆盖Update区域,能快速迭代。但要注意:如果你的MCS文件是双镜像合并的,烧写时小心不要把Golden分区也覆盖了。
第三,远程升级一定要有“断点续传”和“失败重传”的考虑。网络环境再好,现场也可能出现几百K的文件传输到一半断掉的情况。如果Update镜像比较大,建议在Flash里开辟一个“下载暂存区”,先把升级包完整下载并校验,再一次性写入Update分区。虽然占用了一部分Flash空间,但安全系数大幅提升。
第四,尽可能在Update镜像里加一个看门狗功能。FPGA内部逻辑如果跑飞了,至少能触发内部复位,不至于整个系统完全失控。看门狗超时时间不宜太短,一些复杂的初始化流程可能超过几百毫秒,需要预留足够余量。
最后再补一个我个人的习惯:拿到一块新板子,第一件事就是验证Multiboot的回退功能。方法很简单,Golden镜像里写一个LED闪烁程序,Update镜像里故意写一个坏BIT(比如从别的型号复制一个BIT过来),然后运行跳转,看它是否能在几秒内自动回退到Golden。能回退,说明硬件链路和配置架构是健康的,之后再做真实升级包才有底气。
这套流程跑通之后,远程固件升级就不再是让人提心吊胆的操作了。整个体系的关键就是“硬件上把引脚和Flash电路设计稳、Vivado里把配置属性设对、软件上把WBSTAR/IPROG时序搞清楚、流程上把回退机制验证到位”。做到这四点,不管板卡部署在什么地方,升级固件只需要在办公室里点一下按钮就行,这才是Multiboot带来的最大价值。