- 硬件开发
- 嵌入式
- 科研
【免费下载链接】LibreVNA
100kHz to 6GHz 2 port USB based VNA
LibreVNA 由 PC 端 C++/Qt 应用和嵌入式端固件(STM32 MCU 固件 + Spartan 6 FPGA 比特流)三部分组成,三者必须协同构建、打包为统一的combined.vnafw镜像后才能完成设备升级。本文基于官方构建文档 BuildAndFlash.md 逐环节展开,并结合仓库中的打包脚本、MCU 固件校验代码与 GUI 升级对话框源码,讲清每个产物的生成位置、镜像格式与 USB 升级流程的底层机制,读完即可独立完成从源码编译到新板卡上电点亮的全过程。
1. 构建产物全景:为什么要分三步构建
LibreVNA 的固件体系可以概括为三个独立产物:
| 产物 | 代码位置 | 构建工具 | 输出文件 |
|---|---|---|---|
| PC 应用 | Software/PC_Application/LibreVNA-GUI/ | Qt + qmake + libusb-1.0 | librevna可执行文件 |
| MCU 固件 | Software/VNA_embedded/ | STM32CubeIDE(或 arm-none-eabi Makefile) | VNA_embedded.bin |
| FPGA 比特流 | FPGA/VNA/ | Xilinx ISE(Spartan 6 支持) | top.bin |
其中 MCU 固件在 B 版硬件上只作为“引导程序”使用:它启动后通过板载 SPI Flash 读取 FPGA 比特流并配置 FPGA,同时可以接收 USB 侧发来的新固件,将其写入外部 Flash,再自擦除、自复制内部 Flash 后重启。这正是“新硬件只需烧写一次 MCU 固件,之后均可通过 USB 升级”这一设计的关键。
2. 构建环境准备
按官方文档给出的工具清单:
- 构建 PC 应用:
- Qt Creator(文档要求至少 Qt 5.9,当前代码已按 Qt6 组织,安装命令使用 Qt6 包)
- libusb-1.0 开发库
- 构建 MCU 固件:
- STM32CubeIDE:STM32 微控制器的代码生成器与 IDE
- 生成 FPGA 比特流:
- Xilinx ISE(需包含 Spartan 6 支持)
PC 端依赖可以直接用 apt 安装(文档原文命令):
sudo apt-get install libusb-1.0-0-dev qt6-tools-dev qt6-base-dev3. 构建 PC 应用
3.1 命令行构建
cd Software/PC_Application/LibreVNA-GUI qmake6 make3.2 使用 Qt Creator 构建
另一种方式是直接用 Qt Creator 打开 LibreVNA-GUI.pro 工程文件并 Build,文档推荐此方式用于交互式开发。
从工程文件可以确认构建所需的全部依赖:
QT += widgets network svg LIBS += -lusb-1.0 CONFIG += c++17 DEFINES += FW_MAJOR=1 FW_MINOR=6 FW_PATCH=5 FW_SUFFIX=""widgets network svg对应界面、TCP/SCPI 服务与矢量图标;-lusb-1.0是设备通信的基础,Linux 下配合仓库自带的 51-vna.rules udev 规则可免 root 访问设备;- macOS 下工程额外通过
pkg-config链接 libusb,工程文件内已内置相应规则; FW_MAJOR/FW_MINOR/FW_PATCH宏是 GUI 侧定义的固件版本常量,用于固件更新等场景的版本判断。
值得注意的是,该工程还把 MCU 端通信协议的源文件(Protocol.cpp、Protocol.hpp、PacketConstants.h)直接编入了 PC 应用,保证两端协议解析逻辑同源一致。
4. 构建 MCU 固件
4.1 STM32CubeIDE 流程(官方文档步骤)
- 导入工程(仅需一次):以
Software/作为工作区打开 STM32CubeIDE,然后 File > Import... > General > Exisiting Projects into Workspace,在 Root directory(此时应已指向Software/)中选择 “VNA_embedded” 工程,Finish。 - 构建:Project > Build Project。
- 烧录/调试(新硬件或调试时各一次):
- 若没有运行配置:Run > Run configurations > 新建 “STM32 Cortex-M C/C++ Application”,在 Main 标签页选择编译出的
.elf文件; - 用 ST-Link 连接 PCB 上的 SWD 焊盘(需要先拆下铝合金外壳);
- Run > Run 烧录,或 Run > Debug 进入调试。
- 若没有运行配置:Run > Run configurations > 新建 “STM32 Cortex-M C/C++ Application”,在 Main 标签页选择编译出的
4.2 仓库中的 Makefile 交叉编译路线
从源码结构看,Software/VNA_embedded/下还附带了一份可直接使用的 GNU Make 构建脚本 Makefile,它完整对应 STM32G431CBU 目标:
- 工具链:
arm-none-eabi-前缀的 gcc/g++/objcopy(PREFIX = arm-none-eabi-); - CPU 参数:Cortex-M4、Thumb、FPU
fpv4-sp-d16、硬浮点(-mfloat-abi=hard); - 关键宏:
-DHW_REVISION="'B'"、-DSTM32G431xx、-DUSE_HAL_DRIVER等,定义了当前针对 B 版硬件构建; - 链接脚本为 STM32G431CBUX_FLASH.ld,启动文件为 startup_stm32g431cbux.s;
- 默认目标
all会同时产出build/VNA_embedded.elf、.hex和.bin,其中.bin正是后续固件打包需要的二进制。
即在安装了arm-none-eabi工具链的机器上,进入该目录执行make即可得到与 CubeIDE 等价的VNA_embedded.bin(输出到build/子目录)。两种构建方式产出的文件名一致,后续打包步骤完全相同。
5. 生成 FPGA 比特流
文档给出的 Xilinx ISE 操作只有三步,但对 FPGA 部分必不可少:
- 用 Xilinx ISE 打开 FPGA/VNA/VNA.xise;
- 在 Design 标签页选择 implementation view,然后选中 “top - Behavioral”;
- 在 Processes 标签页双击 “Generate Programming File”,等待数分钟完成。
成功后会在FPGA/VNA/目录生成top.bin(仓库中已包含一份示例比特流 top.bin)。MCU 固件在启动时会从外部 Flash 中把这份比特流以 256 字节为单位经 SPI 流式写入 FPGA 的配置引脚,该过程由 FPGA.cpp 中的FPGA::Configure()实现,并在配置完成后检查INIT_B/DONE信号以判断是否发生 CRC 错误或配置失败。
6. 组装 combined.vnafw 组合固件
只有全新硬件上的空白 MCU 需要直接烧录一次 MCU 固件,之后的更新都可以走 USB。而 USB 升级要求使用同时包含FPGA 比特流 + MCU 固件 + 头部数据的组合镜像。
6.1 前置检查与执行
- 确认 MCU 固件已编译:在
Software/VNA_embedded/的Debug/或Release/目录下应有VNA_embedded.bin(Makefile 方式则在build/目录); - 确认 FPGA 比特流已生成:
FPGA/VNA/目录下应有top.bin; - 在仓库根目录执行打包脚本:
python3 AssembleFirmware.py脚本 AssembleFirmware.py 会输出实际使用的 MCU 固件路径、两部分尺寸、CRC32 值以及最终镜像大小:
Using Software/VNA_embedded/Debug/VNA_embedded.bin as MCU firmware Got FPGA bitstream of size 341712 Got MCU firmware of size 130240 Calculating CRC...:0x9e6b1c2a Created combined firmware file of size 4748806.2 镜像格式解析(源码级印证)
脚本生成的combined.vnafw布局为:4 字节魔术字 + 20 字节头部 + 比特流 + MCU 固件 + 256 字节对齐填充。头部结构(小端序,HEADER_SIZE = 24字节整体):
| 偏移 | 字段 | 含义 | 取值来源 |
|---|---|---|---|
| 0 | magic[4] | 魔术字VNA! | 固定 |
| 4 | FPGA_start | 比特流起始地址 | 24(HEADER_SIZE) |
| 8 | FPGA_size | 比特流大小 | top.bin文件长度 |
| 12 | CPU_start | MCU 固件起始地址 | 24 +FPGA_size |
| 16 | CPU_size | MCU 固件大小 | VNA_embedded.bin文件长度 |
| 20 | crc | 全镜像 CRC32 | 以0xFFFFFFFF为初值对比特流、再对 MCU 固件链式计算 |
这个格式与 MCU 端 Firmware.cpp 中的校验逻辑严格对应:GetFlashContentInfo()读取外部 Flash 前 24 字节,逐字段检查 magic 是否为"VNA!"、FPGA_size是否超过FPGA_MAXSIZE(512000 字节)、CPU_size是否超过CPU_MAXSIZE(131072 字节,即 128 KiB),并按同样的链式 CRC32 重新计算比对;若 CRC 或 magic 不通过即判定 Flash 无效。这也解释了打包脚本末尾为何要把总长度填充到 256 的整数倍——与协议常量FW_CHUNK_SIZE = 256(见 PacketConstants.h)一致,使镜像可以按固定块通过 USB 传输。
此外脚本会在Debug/、Release/、build/三个候选路径中自动选择修改时间最新的VNA_embedded.bin,三者都不存在时报错退出;头部长度若与假设的 24 字节不符也会自检失败退出,避免产出不合法镜像。
7. 通过 PC 应用执行固件更新
combined.vnafw生成后,升级通过 PC 应用完成。GUI 侧实现位于 firmwareupdatedialog.cpp,其状态机与状态日志逐行对应上文截图:
- 校验文件:要求文件总长度为 256 的整数倍(
Invalid file size),并读取 24 字节头部与设备期望的魔术字比对;魔术字不符且设备协议版本不匹配时会弹出确认框,由用户决定是否继续; ClearFlash:向设备发送擦除命令,MCU 侧对Firmware::maxSize范围执行整片擦除,等待 20 秒超时保护;FirmwarePacket分块传输:按 256 字节/包逐块写入外部 Flash,每包携带目标地址,GUI 更新进度条;PerformFirmwareUpdate:全部传完后触发设备更新。MCU 端 App.cpp 收到该包后再次执行Firmware::GetFlashContentInfo()校验,然后Firmware::PerformUpdate()在 RAM 中运行copy_flash():先擦除内部 MCU Flash,再从外部 Flash 经 SPI 读回新固件逐字写入内部 Flash,最后触发软复位——由于返回地址可能落在新固件任意位置,该函数刻意不返回;- 等待重新枚举:GUI 断开连接后轮询设备列表,待设备以相同序列号重新出现,等待 3 秒后重新连接,标记更新成功。
若 MCU 在擦除阶段返回 Nack,对话框会提示 “device does not support firmware update”,说明当前运行的固件/硬件不支持 USB 升级路径(例如旧硬件无外部 Flash)。
8. Booting LED 错误码速查
新板卡上电后,"Booting" LED 的闪烁次数用于指示错误码,具体语义可直接从 App.cpp 的启动序列得到印证(LED 闪烁逻辑见 Led.cpp 的LED::Error(code),以“闪烁 N 次”显示代码 N):
| 代码 | 日志(源码原文) | 含义 |
|---|---|---|
| 1 | Failed to detect onboard FLASH | 未检测到板载 SPI Flash 芯片 |
| 2 | Invalid bitstream/firmware, not configuring FPGA | 外部 Flash 内容为空或校验失败(新板卡首次上电即为该状态,属正常) |
| 3 | FPGA configuration failed | 比特流已加载但 FPGA 配置失败 |
| 4 | Initialization failed, unable to start | 硬件初始化失败 |
官方文档特别强调:错误码 2 指的是板载外部 Flash内容为空,而非 MCU 内部 Flash——因此新板卡刷入 MCU 固件后看到两次闪烁完全正常,下一步就是走 USB 固件更新。
9. 新板卡上线四步法(Getting a new board running)
将文档流程与上文的源码证据对齐,新硬件的完整上线路径为:
- 直接烧录 MCU 固件:用 ST-Link 连接板卡 SWD 焊盘,通过 OpenOCD、STM32 ST-Link Utility 等工具烧录编译好的 MCU 固件(这一步之后永远不再需要拆机);
- 确认状态:Booting LED 显示错误码 2(外部 Flash 空)——这是预期的;
- 通过 PC 应用执行固件更新:
- 打开编译好的 PC 应用;
- 若未连接设备:Device > Update Device List,再 Device > Connect to > 选择你的设备序列号;
- 执行更新:Device > Firmware Update,选择
combined.vnafw,点击 Start(过程如第 7 节所述:擦除 → 传输 → 触发 → 重启重连);
- 确认成功:板卡重启后不再报告错误(仅 "Ready" 和 "Power" LED 点亮)。
10. 产物核对清单
完成全部构建与打包后,按路径核对关键文件即可判断流程是否走通:
| 检查项 | 预期路径 |
|---|---|
| PC 应用可执行文件 | Software/PC_Application/LibreVNA-GUI/构建输出 |
| MCU 固件二进制 | Software/VNA_embedded/Debug/(或Release/、build/)下的VNA_embedded.bin |
| FPGA 比特流 | FPGA/VNA/top.bin |
| 组合固件镜像 | 仓库根目录下生成的combined.vnafw(24 字节头 + 比特流 + MCU 固件 + 256 对齐填充) |
需要提醒的限制:Xilinx ISE 仅对 Spartan 6 提供相应支持,FPGA 部分无法用 Vivado 替代;PC 端安装命令基于 Debian/Ubuntu 系包管理(apt),其他发行版或 Windows/macOS 需按文档说明安装 Qt 与 libusb-1.0 的对应包;USB 升级依赖 B 版硬件的 MCU 可控外部 Flash 设计(源码中以HAS_FLASH条件编译标识),更早的硬件版本不具备该更新路径。
- 硬件开发
- 嵌入式
- 科研
【免费下载链接】LibreVNA
100kHz to 6GHz 2 port USB based VNA
相关推荐
LibreVNA设备固件更新失败后的恢复方法
LibreVNA设备固件更新失败后的恢复方法 问题背景 在使用LibreVNA矢量网络分析仪时,用户可能会遇到固件更新失败导致设备无法正常启动的情况。典型表现为
硬件开发嵌入式科研PX4 Autopilot 固件加载完全指南:使用 QGroundControl 安装、升级固件与更新 Bootloader
PX4 Autopilot 固件加载完全指南:使用 QGroundControl 安装、升级固件与更新 Bootloader 本文以 PX4 Autopilot
嵌入式物联网机器人自动驾驶智能硬件Embassy STM32WL Bootloader 固件更新示例指南:DFU 双分区架构与完整刷写流程
Embassy STM32WL Bootloader 固件更新示例指南:DFU 双分区架构与完整刷写流程 本文以 Embassy 仓库中 examples/bo
嵌入式物联网异步编程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考