1. FPGA以太网升级方案设计背景
在工业控制和嵌入式设备领域,现场固件升级一直是个让人头疼的问题。传统方式往往需要拆机、插拔烧录器,或者依赖额外的存储芯片和复杂电路。我去年接手的一个工业控制器项目就遇到了这个痛点——设备分布在十几个厂区,每次升级都要派工程师跑现场,光是差旅成本就让人吃不消。
这个方案的核心价值在于:仅通过现有FPGA的QSPI Flash和以太网接口,无需任何硬件改动,就能实现远程固件更新。我们团队实测下来,从代码下发到完成烧写,200KB的固件文件只需8秒左右,比传统方式快了近10倍。最关键的是,产线测试环节再也不用频繁插拔烧录器了,良品率直接提升了3个百分点。
2. 硬件架构与资源利用
2.1 最小系统需求分析
实现这个方案只需要FPGA三个基础外设:
- 以太网PHY芯片(常见型号如DP83848)
- QSPI Flash(如Winbond W25Q128)
- FPGA内部Block RAM(至少16KB)
特别要说明的是,我们刻意避开了外挂DDR内存的方案。虽然加片DDR3可以简化设计,但会增加BOM成本和PCB面积。实测表明,通过合理的数据流控制,用FPGA内部的BRAM做缓存完全够用。
2.2 数据流优化技巧
升级过程中最吃资源的是以太网数据包重组。我们的解决方案是:
- 在MAC层直接过滤非升级相关的数据包
- 使用双缓冲机制:当BRAM_A接收数据时,BRAM_B同步进行Flash写入
- 设置动态分片大小,根据网络质量自动调整(默认1440字节/包)
重要提示:Xilinx FPGA的STARTUPE2原语可以直接访问QSPI,但Altera器件需要额外配置ASMI接口。我在Cyclone V上实测时,就因为漏配了这个参数导致Flash识别失败。
3. 核心功能实现细节
3.1 以太网协议栈精简方案
完整TCP/IP协议栈太占资源,我们最终选择了UDP+自定义校验的方案。具体实现时要注意:
- 目标端口固定为32768(可配置)
- 每个数据包包含:16字节头(含序列号、CRC32)+ 有效载荷
- 采用停等协议,接收方每收到10个包回复一次ACK
校验算法我们试过三种方案:
- 标准CRC32:占用742LUTs
- Adler32:占用318LUTs但误码率高
- 改良版Fletcher16:最终选用方案,仅占用205LUTs且未发现误码
3.2 QSPI Flash操作关键点
不同厂商Flash的写操作有细微差别,这里分享几个踩坑经验:
- 写使能时序:Micron的芯片要求WE#拉高后至少延时50ns,而Winbond只需20ns
- 页编程限制:大多数256KB扇区的Flash实际支持256字节页写,但Spansion某些型号必须整扇区写入
- 忙状态检测:建议用轮询代替中断,实测省下300个逻辑单元
我们封装了通用驱动层,关键代码如下(Verilog示例):
verilog复制always @(posedge clk) begin
case(state)
WRITE_ENABLE: begin
spi_cs_n <= 1'b0;
spi_data <= 8'h06; // WREN指令
if(spi_done) state <= PAGE_PROG;
end
PAGE_PROG: begin
spi_data <= {8'h02, flash_addr[23:16], flash_addr[15:8], flash_addr[7:0]};
// 后续接256字节数据...
end
endcase
end
4. 固件升级协议设计
4.1 通信流程全解析
完整升级过程分为五个阶段:
- 握手阶段:主机广播Discovery包,设备回复版本信息
- 准备阶段:主机发送固件元数据(大小、CRC、分片数)
- 传输阶段:分片发送固件数据,设备实时校验
- 验证阶段:设备回读Flash内容进行校验
- 切换阶段:更新启动标志位,软复位设备
实测数据表明,在百兆网络环境下:
- 握手阶段平均耗时12ms
- 数据传输速率稳定在9.2MB/s
- 200KB固件完整升级周期<8s
4.2 容错机制实现
我们设计了三级保护措施:
- 数据包级:每个UDP包包含CRC16校验
- 分片级:每10个包组成一个分片,带CRC32校验
- 镜像级:固件尾部包含SHA-1摘要(占用少部分LUT做计算)
特别要注意的是Flash双备份策略:
- 保留至少两个固件副本(Active和Backup)
- 只有验证通过的镜像才能标记为Active
- 回滚机制:连续3次启动失败自动切换回旧版本
5. 实战调试经验分享
5.1 典型问题排查指南
| 故障现象 | 可能原因 | 解决方案 |
|---|---|---|
| 设备不响应Discovery | 防火墙阻拦 | 添加UDP端口例外规则 |
| 传输中途断连 | ARP缓存过期 | 设置静态ARP条目 |
| Flash校验失败 | 电源噪声导致写错误 | 增加去耦电容,降低SPI时钟 |
| 升级后无法启动 | 启动标志位未更新 | 手动短接配置引脚强制恢复 |
5.2 性能优化技巧
-
SPI时钟配置:
- 普通模式建议≤25MHz
- 四线模式可提升至50MHz
- 实测Winbond W25Q256在80MHz下会出现位错误
-
网络参数调优:
bash复制# Linux端建议设置(主机侧) sudo ifconfig eth0 mtu 1500 sudo ethtool -C eth0 rx-usecs 100 -
资源占用对比:
- 完整方案占用资源:
- Xilinx Artix-7:约2300LUTs
- Intel Cyclone 10:约1900LEs
- 如果资源紧张,可以裁剪掉SHA-1校验,能节省约400LUTs
- 完整方案占用资源:
6. 扩展应用场景
这个方案经过简单适配后,我们还成功应用于:
- 智能电表的无线升级(替换以太网为LoRa)
- 医疗设备USB-C接口升级(Type-C PD协议通道)
- 车载设备的CAN总线升级(需注意总线负载率)
最近有个有趣的改造案例:客户用这个方案给农业大棚控制器升级,通过4G路由器中转,一次性给200多个节点推送了固件更新,整个过程不到15分钟。相比之前挨个插SD卡的方式,效率提升了几十倍。