MCU背景开发者咨询FPGA与CPLD Bootloader固件更新及异常处理方案
作为有多年MCU Bootloader开发经验的同行,我来聊聊FPGA和CPLD的固件更新逻辑,以及你关心的容错和备份问题——
FPGA 固件更新的基础流程
没错,绝大多数主流FPGA(比如Xilinx 7系列、Intel Cyclone这类SRAM架构的)本身是易失性的,配置固件都存在外部非易失性Flash里。每次上电时,FPGA会自动从外部Flash加载比特流镜像完成配置。所以常规的更新流程确实是:把新的FPGA比特流写入外部Flash,重启设备后FPGA就会加载新固件,完成更新。
更新故障的应对与备份机制
这部分是FPGA更新最容易踩坑的地方,和MCU的Bootloader逻辑有共通但也有差异:
- 更新中断/文件损坏的后果与应对:如果更新时出现文件损坏、连接中断,写入Flash的是不完整或错误的镜像,那么FPGA重启后加载这个坏镜像,大概率会配置失败——要么卡在启动阶段,要么功能完全异常。这时候就需要像MCU那样的“安全兜底”机制,但FPGA本身的配置过程是硬件主导的,没法像MCU那样靠固化的Bootloader直接接管,得靠提前设计的软件/硬件逻辑来规避变砖风险。
- 默认备份机制?没有,得自己设计:几乎所有FPGA原厂都不会在外部Flash里默认划分备份分区,需要你在系统设计阶段就规划好Flash的分区结构:
- 一般建议分成三个区域:主镜像区(存放正常运行的固件)、备份镜像区(存放备用固件,比如旧版本或最小化恢复固件)、状态标记区(用几个字节记录当前应该加载哪个分区的镜像)。
- 正常启动流程:FPGA先读取状态标记区,根据标记加载主镜像;
- 更新流程:先把新镜像写入备份区,写完后做完整性校验(比如CRC32、MD5),校验通过后再更新状态标记区,下次启动就切换到新的主镜像;
- 如果更新中途中断,状态标记还是指向旧的主镜像,重启后依然能正常启动,不会变砖。
- 还有一种更可靠的硬件冗余方案:用两片独立的配置Flash,一片做主、一片做备,FPGA通过一个GPIO引脚选择从哪片加载。更新时先写备份Flash,验证没问题后切换GPIO引脚,这种方式就算一片Flash损坏,另一片依然能兜底。
和MCU Bootloader的核心差异
你提到MCU里Bootloader永远不会被覆盖,这一点在FPGA里的逻辑是类似的,但实现方式不同:FPGA本身没有固化在片内的“Bootloader”(少数带片内Flash的型号除外,比如Xilinx Spartan-7的部分型号),所以我们需要把“恢复逻辑”提前写入备份镜像区——比如备份区里放一个最小化的FPGA镜像,这个镜像只保留最基础的通信功能(比如UART、以太网),用来接收新的固件并重新更新主镜像。就算主镜像完全损坏,FPGA启动后加载这个“恢复镜像”,就能进入安全更新模式,相当于MCU里的Bootloader角色。
CPLD的固件更新补充
最后说下CPLD的情况,和FPGA差异不小:
- 大部分CPLD分两种类型:一次性可编程(OTP)和内置非易失性Flash;
- OTP型CPLD一旦烧写就没法更新,适合不需要升级的固定功能场景;
- 内置Flash的CPLD支持在线编程(ISP),更新时是直接把镜像写入片内Flash。但如果更新中途中断,可能会导致CPLD变砖,这时候通常需要用厂商提供的JTAG工具强制擦除并重新烧写,部分厂商也支持在设计时加入备份逻辑,但相比FPGA来说可选方案更少。
内容的提问来源于stack exchange,提问作者guitardenver




