1. 为什么要在WFG100上折腾四套固件
手里这块WFG100飞控是基于STM32H743VIT6做的,480MHz主频、2MB Flash、1MB RAM,双BMI088、ICM42688、BMP388、MS5611这些传感器都焊上了,接口也拉得比较全。板子本身硬件底子是够的,但真正决定它能干什么的,是上面跑什么固件。我一开始只打算跑PX4,后来发现身边玩固定翼的、玩穿越的、玩水下机器人的朋友都在问同一块板子能不能跑他们熟悉的固件,索性就把APM、PX4、INAV、BF这四套都编译适配了一遍。
这件事的意义不在于“证明H743性能强”,而在于同一块硬件在不同固件下的资源占用、外设映射、编译工具链、参数体系差异极大。你如果只玩过其中一套,换到另一套时踩的坑会非常密集。比如BF的target配置文件里一个定时器通道写错,电机就直接不转;PX4的board config里UART映射搞反,GPS和数传就互相抢口;INAV对H743的DMA冲突比F4时代敏感得多;APM虽然老牌,但ChibiOS下的H743支持并不是“插上就能用”。
这篇内容适合三类人:一是手里有H743板子想自己刷固件的;二是做飞控硬件想验证固件兼容性的;三是已经会飞但想搞明白底层编译适配逻辑的。我会把四套固件的编译环境、board配置、外设映射、烧录验证、常见报错都拆开讲,参数和步骤尽量给到能直接抄的程度。
注意:以下所有操作基于Ubuntu 22.04 LTS物理机或WSL2环境,STM32CubeProgrammer和dfu-util版本会影响烧录结果,建议先统一工具版本。
2. 四套固件的定位差异与选型逻辑
2.1 各自的核心场景与代码体量
先把四套固件的“性格”说清楚,不然后面编译时你会不知道为什么有的要改Makefile,有的要改hwdef。
| 固件 | 主要场景 | 代码体量 | 编译系统 | H743支持成熟度 |
|---|---|---|---|---|
| APM | 多旋翼/固定翼/车/船 | 大,历史包袱重 | waf | 中等,需手动配hwdef |
| PX4 | 多旋翼/固定翼/VTOL/无人车 | 很大,模块化 | CMake+Ninja | 较好,官方有H743 board |
| INAV | 固定翼/穿越/长航时 | 中等 | Make | 较好,target机制清晰 |
| BF | 穿越/竞速 | 小,精简 | Make | 好,target文件成熟 |
APM和PX4都是“大而全”路线,但APM的ChibiOS分支对H743的时钟树配置需要自己核对,PX4则从v1.12之后对H7系列支持明显完善。INAV和BF同源但分家已久,INAV偏导航和固定翼,BF偏纯手动和竞速,两者target文件结构相似但参数体系完全不同。
2.2 为什么同一块板子要分别适配
WFG100的硬件设计里,UART和定时器分配是固定的。比如UART4接了GPS,UART7接了数传,TIM1和TIM8分别驱动两组电机。不同固件对这些外设的默认映射不一样:
- BF的target里通常把MOTOR1放TIM1_CH1,但WFG100实际焊的是TIM8_CH1,不改target电机不转。
- PX4的board config里UART7默认可能是作为TELEM2,但WFG100的TELEM2实际走UART2,需要改
default.px4board。 - INAV的target.c里需要显式声明
TIM_USE_MOTOR和TIM_USE_LED,否则LED和蜂鸣器冲突。 - APM的hwdef.dat里要手动写
PE8 TIM1_CH1OUT这类引脚定义,写错一个就是“无输出”。
所以适配的本质是把硬件真实连接翻译成各固件能识别的配置语言,而不是简单“编译通过就行”。
2.3 选型建议:先问自己飞什么
如果你飞穿越机,直接BF,别折腾PX4,代码体量和调参逻辑完全不适合。如果你飞固定翼做长航时,INAV的导航和OSD更顺手。如果你要做多旋翼编队或避障,PX4的模块化和MAVLink生态更完整。APM适合已经有一套APM参数体系、不想迁移的老玩家。WFG100这块板子四套都能跑,但没必要都跑,选一套深入即可。
3. 编译环境搭建与工具链统一
3.1 Ubuntu 22.04基础依赖
四套固件对工具链版本要求不同,但可以共存。我习惯先装一套通用依赖:
sudo apt update sudo apt install -y git make cmake ninja-build gcc-arm-none-eabi \ binutils-arm-none-eabi libnewlib-arm-none-eabi \ python3 python3-pip python3-venv dfu-util这里有个坑:Ubuntu 22.04自带的gcc-arm-none-eabi是10.3版本,PX4 v1.14要求至少10.3,BF和INAV用9-10都能编,APM的waf脚本对12以上版本反而会报错。所以不要盲目升级到最新ARM GCC,10.3是四套固件的最大公约数。
3.2 各固件独立环境隔离
我建议用不同的目录和Python虚拟环境隔离,避免pip包冲突:
mkdir -p ~/fw && cd ~/fw git clone https://github.com/ArduPilot/ardupilot.git apm git clone https://github.com/PX4/PX4-Autopilot.git px4 git clone https://github.com/iNavFlight/inav.git inav git clone https://github.com/betaflight/betaflight.git bfPX4需要额外装pip install -r Tools/setup/requirements.txt,APM需要pip install -r requirements.txt,INAV和BF基本只用make,Python依赖少。
3.3 串口权限与烧录工具
H743通常用DFU或串口烧录。DFU模式下lsusb能看到0483:df11,如果看不到,检查BOOT0是否拉高。串口烧录需要把用户加入dialout组:
sudo usermod -aG dialout $USER然后重新登录。烧录工具我统一用dfu-util,版本0.11以上对H7支持稳定。STM32CubeProgrammer也可以,但它的CLI在WSL下有时识别不到USB,物理机更稳。
提示:WSL2的USB直通需要usbipd,配置麻烦且容易断,烧录环节建议在物理Ubuntu或Windows下用STM32CubeProgrammer完成。
4. BF固件在WFG100上的编译与target适配
4.1 target文件结构解析
BF的target文件在src/main/target/WFG100/下,核心是target.h和target.c。target.h定义引脚和定时器,target.c定义定时器通道用途。WFG100的电机输出实际接在TIM8的CH1-CH4,所以:
#define MOTOR1_PIN PE8 // TIM8_CH1 #define MOTOR2_PIN PE9 // TIM8_CH2 #define MOTOR3_PIN PE10 // TIM8_CH3 #define MOTOR4_PIN PE11 // TIM8_CH4如果你直接抄别的H743 target,很可能写成TIM1,编译能过但电机不动。target.c里要加:
timerHardware_t timerHardware[] = { DEF_TIM(TIM8, CH1, PE8, TIM_USE_MOTOR, 0, 0), DEF_TIM(TIM8, CH2, PE9, TIM_USE_MOTOR, 0, 0), DEF_TIM(TIM8, CH3, PE10, TIM_USE_MOTOR, 0, 0), DEF_TIM(TIM8, CH4, PE11, TIM_USE_MOTOR, 0, 0), };4.2 编译命令与常见报错
cd ~/fw/bf make WFG100如果报undefined reference to 'timerHardware',说明target.c没被包含进Makefile,检查src/main/target/WFG100/下是否有CMakeLists.txt或Makefile引用。BF 4.4之后用CMake,需要:
mkdir build && cd build cmake .. -DTARGET=WFG100 make -j8常见报错还有region FLASH overflowed,说明功能开太多,关掉USE_GPS或USE_MAG再试。
4.3 烧录与验证
生成的betaflight_4.4.x_WFG100.hex用dfu-util烧:
dfu-util -a 0 -s 0x08000000:leave -D betaflight_4.4.x_WFG100.hex烧完接BF Configurator,看传感器是否全部识别。如果陀螺仪数据不动,检查SPI引脚定义;如果电机测试不转,回查TIM8映射。
实操心得:BF的target文件里
TIM_USE_MOTOR的最后一个参数是DMA选项,H743的DMA冲突比F4多,如果电机和LED同时用TIM8,需要错开DMA stream,否则编译不报错但运行异常。
5. INAV固件的target配置与编译
5.1 INAV target与BF的异同
INAV的target也在src/main/target/下,但多了一个target.c里的timerHardware和target.h里的BOARD_HAS_*宏。WFG100的INAV target需要定义:
#define BOARD_HAS_BARO #define BOARD_HAS_MAG #define BOARD_HAS_SDCARD #define USE_UART4 #define USE_UART7INAV对H743的DMA要求更严格,timerHardware里要显式指定DMA:
DEF_TIM(TIM8, CH1, PE8, TIM_USE_MOTOR, 0, 0),最后一个0是DMA option,如果和SDIO冲突,SD卡会初始化失败。
5.2 编译与固件生成
cd ~/fw/inav make WFG100INAV的Makefile会自动找src/main/target/WFG100/。如果报No such file or directory: target.mk,说明target目录名大小写不对,INAV要求全大写。
生成的inav_7.x.x_WFG100.hex烧录方式和BF一样。烧完接INAV Configurator,重点看GPS和磁罗盘。如果GPS不识别,检查UART4的TX/RX是否在target.h里定义反了。
5.3 参数迁移注意
INAV和BF的参数不通用,但遥控通道映射逻辑相似。从BF转INAV时,rxConfig和motorConfig要重设。INAV的mixer默认是MIXER_FLYING_WING,多旋翼要改成MIXER_QUADX。
注意:INAV 7.x对H743的Flash分区有要求,如果开了Blackbox,
FLASH区域可能不够,建议用SD卡存日志。
6. PX4固件的board config与编译
6.1 PX4的board目录结构
PX4的board在boards/下,WFG100需要新建boards/wfg/wfg100/,包含:
default.px4board:定义UART、SPI、I2C映射board_config.h:定义GPIO和电源init/rc.board_defaults:启动脚本
default.px4board里关键行:
CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS0" CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS3" CONFIG_DRIVERS_GPS=y CONFIG_DRIVERS_IMU_BMI088=y这里ttyS0对应UART4,ttyS3对应UART7,写错就找不到设备。
6.2 编译命令与依赖
cd ~/fw/px4 make wfg_wfg100_defaultPX4 v1.14用CMake+Ninja,第一次编译会下载很多子模块,建议先git submodule update --init --recursive。如果报python3 -m pip install kconfiglib失败,手动装:
pip3 install kconfiglib编译产物在build/wfg_wfg100_default/下,px4_fmu-v6x_default.px4类似文件用QGC烧录。
6.3 外设映射验证
PX4烧完后接QGC,看mavlink status。如果GPS不亮,检查/dev/ttyS3是否存在。H743的UART7默认引脚是PE8/PE9,但WFG100可能用了PF6/PF7,需要在board_config.h里重映射:
#define GPIO_USART7_TX GPIO_PF7 #define GPIO_USART7_RX GPIO_PF6实操心得:PX4的board config里
CONFIG_BOARD_SERIAL_*的顺序决定了/dev/ttyS*编号,不是按物理UART编号来的,第一次配很容易搞反,建议画个映射表再写。
7. APM固件的hwdef配置与编译
7.1 hwdef.dat编写要点
APM的hwdef在libraries/AP_HAL_ChibiOS/hwdef/WFG100/下,核心是hwdef.dat:
MCU STM32H743xx APJ_BOARD_ID 1234 FLASH_SIZE_KB 2048 RAM_SIZE_KB 1024 PA0 UART4_TX PA1 UART4_RX PE8 TIM1_CH1OUT注意APM的定时器命名是TIM1_CH1OUT,不是TIM8_CH1。如果WFG100电机接TIM8,要写PE8 TIM8_CH1OUT。写错编译能过,但motors测试无输出。
7.2 编译命令
cd ~/fw/apm ./waf configure --board WFG100 ./waf copterAPM的waf对Python版本敏感,建议用Python 3.8-3.10。如果报ImportError: cannot import name 'collections',是Python 3.10+的兼容问题,装python3.9再试。
7.3 烧录与参数
生成的arducopter.apj用Mission Planner烧。APM的参数体系和PX4完全不同,SERIAL4_PROTOCOL对应UART4,SERIAL7_PROTOCOL对应UART7。如果数传不通信,检查SERIAL7_BAUD是否和数传波特率一致。
注意:APM的H743支持在ChibiOS 21.11之后才稳定,老版本编译可能卡在
chibios子模块,建议用最新master。
8. 四套固件编译适配对比与排查速查
8.1 关键差异对照表
| 项目 | BF | INAV | PX4 | APM |
|---|---|---|---|---|
| 编译系统 | Make/CMake | Make | CMake+Ninja | waf |
| target文件 | target.h/c | target.h/c | default.px4board | hwdef.dat |
| 定时器命名 | TIM8_CH1 | TIM8_CH1 | TIM8_CH1 | TIM8_CH1OUT |
| UART映射 | 宏定义 | 宏定义 | CONFIG_BOARD_SERIAL | SERIALx_PROTOCOL |
| 烧录工具 | dfu-util | dfu-util | QGC | Mission Planner |
| H743 DMA敏感度 | 中 | 高 | 中 | 低 |
8.2 常见问题速查
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 编译通过但电机不转 | 定时器映射错 | 查target/hwdef的TIM通道 |
| GPS不识别 | UART TX/RX反 | 对调引脚定义 |
| 陀螺仪数据不动 | SPI片选错 | 查SPI CS引脚 |
| 烧录后无启动 | BOOT0未拉低 | 检查BOOT0电平 |
| Flash溢出 | 功能开太多 | 关GPS/MAG/Blackbox |
8.3 独家避坑技巧
第一,先编BF再编INAV,因为BF的target最简单,能快速验证硬件基本通路。第二,PX4的board config改完后先make clean,否则旧配置缓存会导致外设映射不生效。第三,APM的hwdef.dat里引脚定义顺序不重要,但定时器通道必须和物理连接一致,我见过有人把TIM8写成TIM1,结果电机测试时只有一路抖。第四,H743的DMA冲突在INAV上最明显,如果SD卡和电机同时用DMA,优先给电机分配独立stream。
9. 烧录验证与首飞前检查
四套固件烧完后,首飞前必须做三件事:传感器校准、电机方向测试、失控保护测试。BF和INAV在Configurator里直接校准,PX4用QGC的Sensors页,APM用Mission Planner的Initial Setup。电机方向测试时,不要装桨,用motor test逐个转,确认编号和转向。失控保护测试把遥控关掉,看飞控是否进入failsafe模式。
提示:H743的USB和UART同时使用时,如果USB枚举失败,检查
VBUS检测引脚是否配置正确,WFG100上可能是PA9。
10. 我个人在实际适配中的体会
四套固件里,BF和INAV的适配最快,因为target机制直观,改完编译烧录就能验证。PX4的board config最繁琐,但一旦配好,后续二次开发最舒服。APM的hwdef.dat写起来最像“手写汇编”,但它的参数体系对老玩家最友好。WFG100这块板子硬件底子好,四套都能跑,但没必要都跑。我的建议是:穿越选BF,固定翼选INAV,多旋翼编队选PX4,老APM用户继续APM。编译适配的核心不是“让代码跑起来”,而是“让硬件真实连接和固件配置一一对应”。每次改完target或hwdef,先画一张引脚映射表,比反复烧录试错快得多。