3、PX4固件烧录:从地面站到命令行,再到安全签名
固件烧录,说白了就是把编译好的二进制文件写进飞控的Flash里。这一步看似简单,但坑不少。我见过不少开发者在地面站里点一下“烧录”就完事了,结果飞控死活连不上,或者飞着飞着突然重启——嗯,多半是Bootloader出了问题。
这一章,我会把PX4固件烧录的几种主流方式都过一遍。从最常用的QGroundControl图形化烧录,到命令行下的J-Link/SWD调试器烧录,再到Bootloader的原理和升级,最后聊聊固件签名与安全。这些都是我在实际项目中踩过坑、填过土的经验。
核心要点:烧录不是简单的“复制粘贴”,它涉及Bootloader、硬件接口、协议栈和签名验证。任何一个环节出问题,飞控都可能变砖。
3.1 QGroundControl地面站烧录
QGroundControl(简称QGC)是PX4官方推荐的地面站软件。它集成了固件烧录功能,操作起来非常直观。我个人习惯在原型验证阶段用QGC烧录,因为快,而且能看到实时日志。
3.1.1 准备工作
- 硬件:飞控板(如Pixhawk 4、CUAV V5+)、USB数据线(注意:有些飞控需要Micro USB,有些是USB-C)
- 软件:QGC最新版(Windows/macOS/Linux均可)
- 固件:PX4编译好的二进制文件(.px4或.bin格式)
3.1.2 烧录步骤
- 用USB线连接飞控和电脑。飞控上的LED灯应该会亮起。
- 打开QGC,点击左上角的“Q”图标,进入应用设置。
- 选择“固件”选项卡。QGC会自动检测飞控型号。
- 点击“高级设置”,勾选“自定义固件文件”。
- 选择你编译好的.px4文件,点击“烧录”。
- 等待进度条走完。飞控会自动重启。
小技巧:如果QGC检测不到飞控,试试换一根USB线。我曾经被一根劣质线坑了整整一下午——飞控供电不稳,烧录到一半就断连。
3.1.3 常见问题
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 飞控无法识别 | 驱动未安装或USB线有问题 | 安装驱动(Windows需装WinUSB驱动),换线 |
| 烧录中途失败 | 供电不足或USB带宽不够 | 使用独立供电的USB Hub |
| 烧录后飞控无反应 | 固件版本不匹配或Bootloader损坏 | 重新烧录Bootloader |
3.2 命令行烧录:J-Link/SWD
QGC虽然方便,但在批量生产或调试底层时,命令行烧录才是王道。你想想看,生产线上一百块飞控,总不能一块一块地插USB点鼠标吧?
J-Link是SEGGER公司的调试器,支持SWD(Serial Wire Debug)接口。SWD只需要两根线(SWDIO和SWCLK),比传统的JTAG少很多引脚,非常适合飞控这种小尺寸板子。
3.2.1 硬件连接
把J-Link的SWD接口连接到飞控的调试端口。以Pixhawk 4为例,调试端口定义如下:
| 引脚 | 信号 | 说明 |
|---|---|---|
| 1 | VCC (3.3V) | 目标板供电(可选) |
| 2 | SWDIO | 数据线 |
| 3 | SWCLK | 时钟线 |
| 4 | GND | 地线 |
警告:千万不要接反VCC和GND!我见过有人把3.3V接到GND上,飞控直接冒烟。嗯,那块板子后来成了我们的“教学标本”。
3.2.2 使用J-Link Commander烧录
J-Link Commander是SEGGER提供的命令行工具。以下是一个典型的烧录脚本:
# 连接J-Link
JLinkExe -device STM32F765 -if SWD -speed 4000 -autoconnect 1
# 解锁Flash(如果之前锁了)
unlock Kinetics
# 擦除整个Flash
erase
# 加载固件到Flash
loadfile px4_fmu-v5_default.px4
# 重置并运行
r
g
# 退出
exit
这里要注意:-device参数必须指定正确的芯片型号。PX4常用的芯片有STM32F427、STM32F765、STM32H743等。搞错了型号,烧录会失败。
3.2.3 使用OpenOCD烧录
如果你不想用SEGGER的收费工具,OpenOCD是个不错的开源替代。我个人在Linux下用得比较多:
# 启动OpenOCD,连接ST-Link(兼容SWD)
openocd -f interface/stlink.cfg -f target/stm32f7x.cfg
# 在另一个终端中,通过telnet连接
telnet localhost 4444
# 烧录命令
reset halt
flash write_image erase px4_fmu-v5_default.px4 0x08000000
reset run
避坑指南:我曾经在烧录时忘记指定起始地址0x08000000,结果固件写到了错误的位置,飞控直接变砖。后来我养成了一个习惯:每次烧录前都先读一下芯片的Flash起始地址。
3.3 Bootloader原理与升级
Bootloader是飞控上电后第一个运行的程序。它的职责很简单:检查Flash里有没有有效的固件,有就跳转过去执行,没有就进入烧录模式等待新固件。
PX4的Bootloader通常放在Flash的起始扇区(0x08000000 ~ 0x0800FFFF,共64KB)。应用程序则从0x08010000开始。
3.3.1 Bootloader的工作流程
我画了一张流程图,帮你理清Bootloader的执行逻辑:
3.3.2 升级Bootloader
有时候,飞控出厂自带的Bootloader版本太旧,不支持新固件的签名算法。这时候就需要升级Bootloader。
升级方法有两种:
- 通过J-Link直接烧录:把Bootloader的二进制文件(如
px4_bootloader.bin)烧录到0x08000000地址。 - 通过应用程序升级:有些飞控支持在应用程序中触发Bootloader升级。这需要固件本身支持。
警告:升级Bootloader有风险。如果中途断电或烧录错误,飞控将无法启动。我建议你在升级前先备份原版Bootloader。
3.4 固件签名与安全
为什么需要固件签名?你想想看,如果一架无人机飞在天上,突然被人注入了恶意固件,后果不堪设想。固件签名就是为了防止这种情况。
PX4从v1.11版本开始引入了固件签名机制。Bootloader在启动时会验证固件的数字签名,只有签名合法的固件才会被执行。
3.4.1 签名原理
签名过程其实不复杂:
- 开发者用私钥对固件哈希值进行加密,生成签名。
- 签名被附加在固件文件的末尾。
- Bootloader用公钥解密签名,得到哈希值A。
- Bootloader计算固件本身的哈希值B。
- 如果A == B,说明固件未被篡改,签名有效。
3.4.2 生成密钥对
你可以使用OpenSSL生成RSA密钥对:
# 生成私钥
openssl genrsa -out px4_private.pem 2048
# 提取公钥
openssl rsa -in px4_private.pem -pubout -out px4_public.pem
3.4.3 对固件签名
PX4提供了签名工具px4_sign:
# 对固件签名
python3 px4_sign.py --private-key px4_private.pem --firmware px4_fmu-v5_default.px4
签名后的固件文件会变大,因为末尾多了一段签名数据。
3.4.4 将公钥烧录到Bootloader
公钥需要提前烧录到Bootloader的特定位置。PX4的Bootloader源码中有一个public_keys.c文件,你需要把公钥放进去,然后重新编译Bootloader。
// public_keys.c 示例
const uint8_t public_key[] = {
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
// ... 公钥数据
};
避坑指南:我曾经在生成密钥对时忘了保存私钥,结果签名后的固件无法被验证。嗯,那次我不得不重新编译Bootloader,把新的公钥烧进去。所以,私钥一定要妥善保管!
3.4.5 安全建议
| 建议 | 说明 |
|---|---|
| 私钥离线存储 | 不要将私钥放在联网的电脑上,使用离线机器或硬件安全模块(HSM) |
| 定期更换密钥 | 建议每6个月更换一次密钥对,旧密钥用于兼容旧固件 |
| 多级签名 | 对于高安全场景,可以使用多级签名(如Bootloader签名、应用程序签名) |
| 禁用不安全接口 | 量产时禁用SWD/JTAG接口,防止物理攻击 |
3.5 本章小结
固件烧录是PX4部署的第一步,也是最重要的一步。从QGC的图形化操作,到命令行的精确控制,再到Bootloader的原理和签名安全,每一步都有它的门道。
我个人建议:在开发阶段用QGC烧录,方便快捷;在批量生产或调试底层时,用命令行烧录,可控性强;在安全敏感场景下,一定要启用固件签名。
嗯,这一章的内容就到这里。记住:烧录不是终点,安全才是。