完全指南:构建、硬件配置与 PX4 兼容刷写协议解析)
ArduPilot STM32 引导加载程序AP_Bootloader完全指南构建、硬件配置与 PX4 兼容刷写协议解析【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot导读AP_Bootloader 是 ArduPilot 官方为所有基于 STM32 的飞控板ArduCopter、ArduPlane、ArduRover、ArduSub、AP_Periph 等固件的载体提供的二级引导加载程序负责在上电后校验并跳转主固件、以及在 USB/UART/CAN/以太网等通道上接收主机刷写指令。本文以仓库中的 Tools/AP_Bootloader/README.md 为骨架结合wscript、bl_protocol.cpp、support.cpp、hwdef-bl.dat等源码级证据带你掌握引导加载程序的完整构建流程、板卡级硬件配置文件语法、板卡 ID 分配机制以及底层刷写协议的命令帧格式使你能独立为一块自定义 STM32 飞控板编译并部署 Bootloader。一、AP_Bootloader 是什么AP_Bootloader 是 ArduPilot 用于STM32 系列飞控板的引导加载程序源码位于仓库的 Tools/AP_Bootloader 目录。它的职责是在飞控上电后校验 Flash 中的应用固件完整性CRC 与向量表决定是直接跳转运行主固件还是停留在 Bootloader 中等待刷写接收上位机如 Mission Planner、QGroundControl通过USB 或 UART 串口下发的固件数据将其写入 Flash完成固件升级从源码实现看它还支持CAN 总线、以太网Network与 SD 卡三种额外的固件加载途径。关于代码的体积约束AP_Bootloader.cpp 的头部注释给出了一个关键设计决策It does not use the full AP_HAL API in order to keep the firmware size below the maximum of 16kByte required for F4 based boards. Instead it uses the ChibiOS APIs directly——为了把体积控制在 F4 平台要求的 16KB 以内Bootloader不依赖完整的 AP_HAL 抽象层而是直接使用 ChibiOS 的ch.h、hal.h等底层 API。这一点解释了为什么 Bootloader 需要单独构建、并拥有自己独立的硬件配置文件。二、构建 Bootloaderwaf 两条命令README 给出了最核心的构建方法只需要两条命令./waf configure --board BOARDNAME --bootloader ./waf bootloader其中--board BOARDNAME指定目标飞控板的板卡名例如Pixhawk1、CubeOrange--bootloader告诉 waf本次配置的目标是Bootloader 固件而不是主飞行固件./waf bootloader执行实际的编译动作。从 Tools/AP_Bootloader/wscript 的源码可以看到waf 构建系统只有在bld.env.BOOTLOADER标志被设置时才会真正构建该目录并且会把AP_Math、AP_CheckFirmware、AP_Networking、AP_ROMFS、AP_Common等精简后的库链入同时编译 DroneCAN 的libcanardCAN 刷写协议依赖最终通过bld.ap_program(..., program_groupsbootloader)产出可执行文件。构建产物位置编译完成后产物位于build/BOARDNAME/bin目录产物路径用途.binbuild/BOARDNAME/bin/二进制镜像配合 DFU 工具上传.hexbuild/BOARDNAME/bin/Intel HEX 格式镜像仅在主机安装了 intelhex Python 模块时生成同样通过 DFU 上传.elfbuild/BOARDNAME/AP_Bootloader带符号的可执行文件用于配合gdb调试 Bootloader 本身README 特别强调bin 和 hex 通常都用 DFUDevice Firmware Upgrade方式上传。对大多数飞控板而言进入 DFU 模式后主机端使用dfu-util即可刷写dfu-util -a 0 -d 0483:df11 -s 0x08000000:leave -D build/BOARDNAME/bin/AP_Bootloader.bin0483:df11是 STM32 系统 Bootloader 的常见 USB VID:PID实际以板卡为准-s ...:leave表示刷写完成后跳转运行。三、--bootloader背后的硬件配置机制hwdef-bl.dat--bootloader选项的关键作用是让 waf 从hwdef-bl.dat文件读取硬件配置。README 明确指出其查找路径为libraries/AP_HAL_CHibiOS/hwdef/BOARDNAME/hwdef-bl.dat注意仓库中实际目录名为libraries/AP_HAL_ChibiOS/hwdef/BOARDNAME/hwdef-bl.dat。例如 Pixhawk1 的 Bootloader 配置直接包含 FMUv3 的配置# libraries/AP_HAL_ChibiOS/hwdef/Pixhawk1/hwdef-bl.dat include ../fmuv3/hwdef-bl.dat让我们以 fmuv3/hwdef-bl.dat 为例逐行解读 Bootloader 硬件配置的关键语法# MCU class and specific type MCU STM32F4xx STM32F427xx # board ID. See Tools/AP_Bootloader/board_types.txt APJ_BOARD_ID TARGET_HW_CUBE_F4 # crystal frequency OSCILLATOR_HZ 24000000 # ChibiOS system timer STM32_ST_USE_TIMER 5 # flash size FLASH_SIZE_KB 2048 # location of application code FLASH_BOOTLOADER_LOAD_KB 16 # bootloader loads at start of flash FLASH_RESERVE_START_KB 0 # baudrate to run bootloader at on uarts define BOOTLOADER_BAUDRATE 115200 # uarts and USB to run bootloader protocol on SERIAL_ORDER OTG1 USART2各配置项的含义与底层影响如下MCU STM32F4xx STM32F427xx声明 MCU 系列与具体型号决定链接时选择哪个芯片启动文件与 Flash 驱动APJ_BOARD_ID TARGET_HW_CUBE_F4板卡 ID必须与 board_types.txt 中的宏定义一致。它最终会编译进board_info.board_type见 AP_Bootloader.cpp在刷写握手阶段上报给上位机用于校验固件与板卡是否匹配FLASH_BOOTLOADER_LOAD_KB 16Bootloader 占据 Flash 起始的 16KB应用固件从 16KB 之后开始存放。这与第一节提到的16KB 体积上限直接对应define BOOTLOADER_BAUDRATE 115200串口刷写的默认波特率见 support.cpp 中的#define BOOTLOADER_BAUDRATE 115200可通过PROTO_SET_BAUD命令在线切换SERIAL_ORDER OTG1 USART2Bootloader 监听哪些设备通道。README 明确说明The bootloader can load from USB or UARTs. The list of devices to load from is given in the SERIAL_ORDER option in hwdef-bl.dat。这里OTG1指 USB OTG1 接口USART2是飞控的遥测串口 TELEM1。它会被展开为BOOTLOADER_DEV_LIST宏见 support.cpp驱动 Bootloader 在所有列出的通道上轮询命令字节并在收到第一个有效命令后锁定到该通道lock_bl_port()。此外hwdef-bl.dat 还可以声明USB 的 VBUS 检测引脚PA9 VBUS INPUT OPENDRAIN、USB 数据引脚PA11/PA12 OTG_FS_DM/DP、SWD 调试引脚PA13/PA14、Bootloader 状态 LEDPE12 LED_BOOTLOADER OUTPUT以及片选引脚CS等。这些配置与主固件的 hwdef.dat 共享同一套由chibios_hwdef.py处理的语法。四、板卡 ID 与 PX4 协议兼容性4.1 为什么兼容 PX4README 指出The bootloader protocol is compatible with that used by the PX4 project for boards like the Pixhawk. 这意味着凡是 Pixhawk 系列FMUv1~v6 等使用的上位机刷写工具链都能直接用于 ArduPilot 的 Bootloader不需要额外的驱动或专属工具。这一兼容性来自代码层面的继承bl_protocol.cpp 的注释明确写道该协议移植自 PX4 项目的bl.c由 Andrew Tridgell 移植到 ChibiOS。协议版本号BL_PROTOCOL_VERSION当前为5见 bl_protocol.cpp。4.2 board_types.txt板卡 ID 的注册中心README 要求为兼容性起见我们在本目录维护一份板卡 ID 列表即 board_types.txt。这份文件集中登记了所有使用该 Bootloader 协议的主板类型格式为宏名 数值例如TARGET_HW_PX4_FMU_V2 9 TARGET_HW_PX4_FMU_V4 11 AP_HW_CUBEORANGE 140 AP_HW_KAKUTEF7 123README 强调the board IDs in that file match the APJ_BOARD_ID in the hwdef.dat and hwdef-bl.dat files——即 hwdef 文件里的APJ_BOARD_ID必须引用该文件中的宏。我们在上一节看到的APJ_BOARD_ID TARGET_HW_CUBE_F4正是如此其值为9。4.3 ID 分配规则从 board_types.txt 的注释中可以提炼出三条硬性规则1000 ~ 19999区间保留给 ArduPilot Bootloader 专用外部厂商不得私自占用只能通过向该文件提交 PR 分配非 OpenDroneIDODID板卡的 ID 不得超过10000ODID 板卡使用10000 基础板卡 ID的编码方式如AP_HW_CubeOrange_ODID 10140厂商若需预留一批 ID每次申请上限为 10 个且应优先填补已分配 ID 之间的空隙而不是在文件末尾追加please fill gaps rather than adding past ID #7109。五、底层刷写协议详解命令帧与状态机理解协议的最好方式是直接阅读 bl_protocol.cpp 顶部的协议规范注释。5.1 帧格式命令帧: opcode[command_data]EOC 应答帧: [reply_data]INSYNCstatusopcode与status取值来自协议宏定义EOCEnd Of Command标志命令结束INSYNC是应答前导字节status指示命令执行结果。关键协议字节bl_protocol.cpp方向名称值含义应答前导PROTO_INSYNC0x12应答的 in sync 字节命令结束PROTO_EOC0x20命令结束标志应答PROTO_OK0x10命令成功应答PROTO_FAILED0x11命令失败应答PROTO_INVALID0x13非法命令命令PROTO_GET_SYNC0x21重新建立同步命令PROTO_GET_DEVICE0x22读取设备 ID 信息命令PROTO_CHIP_ERASE0x23擦除程序区并复位写地址命令PROTO_PROG_MULTI0x27写入字节并递增地址命令PROTO_READ_MULTI0x28读取字节并递增地址命令PROTO_GET_CRC0x29计算并返回整个可写区的 CRC命令PROTO_GET_OTP0x2a读取 OTP 指定地址命令PROTO_GET_SN0x2b从 UDID 区读取序列号命令PROTO_GET_CHIP0x2c读取芯片版本MCU IDCODE命令PROTO_SET_DELAY0x2d设置最小启动延时命令PROTO_GET_CHIP_DES0x2e读取 ASCII 芯片描述命令PROTO_GET_VERSION0x2f读取 Bootloader 版本命令PROTO_BOOT0x30启动应用命令PROTO_SET_BAUD0x33切换串口波特率命令PROTO_EXTF_ERASE0x34擦除外置 Flash 扇区命令PROTO_EXTF_PROG_MULTI0x35写入外置 Flash命令PROTO_EXTF_GET_CRC0x37计算外置 Flash 的 CRC命令PROTO_CHIP_FULL_ERASE0x40强制全擦跳过磨损优化GET_DEVICE命令通过参数区分要读取的信息bl_protocol.cppPROTO_DEVICE_BL_REV1Bootloader 协议版本PROTO_DEVICE_BOARD_ID2板卡 ID即board_info.board_typePROTO_DEVICE_BOARD_REV3板卡硬件版本PROTO_DEVICE_FW_SIZE4可刷写区大小PROTO_DEVICE_VEC_AREA5向量表 7~10 的内容PROTO_DEVICE_EXTF_SIZE6外置 Flash 可用大小。5.2 标准刷写工作流bl_protocol.cpp 定义了协议版本 3 的标准流程这也是所有兼容上位机的刷写步骤GET_SYNC 验证板卡在线重新建立同步 GET_DEVICE 读取板卡类型决定上传哪个固件 CHIP_ERASE 擦除程序区并复位地址计数器 循环: PROG_MULTI 分块写入固件字节单次最大 64 字节见 PROTO_PROG_MULTI_MAX GET_CRC 校验整个可刷写区的 CRCcrc32 BOOT/RESET 收尾写入、复位芯片并启动应用值得注意的工程细节PROG_MULTI要求字节数为 4 的整数倍且写入地址不能越过board_info.fw_size边界bl_protocol.cpp前导 32 字节RESERVE_LEAD_WORDS 8个 32 位字会被暂存而不会立即写入 Flash直到收到BOOT命令确认整个上传成功后才在 PROTO_BOOT 分支中补写。这样可避免写到一半断电导致半成品固件被误启动防误擦除保护CHIP_ERASE只有在done_sync和GET_DEVICE信息齐备后才执行防止串口噪声误触发擦除lower chance of random data on a uart triggering erase超时回退机制收到无效命令时只要尚未开始擦除!done_erase超时时间会恢复为原始值避免卡死在 Bootloaderbl_protocol.cpp。5.3 跳转应用jump_to_app 的校验逻辑bl_protocol.cpp 的 jump_to_app() 展示了 Bootloader 跳转前的三道安全闸门若启用了AP_CHECK_FIRMWARE_ENABLED先调用check_good_firmware()做固件 CRC 校验失败则点亮LED_BAD_FW并停留在 Bootloader检查应用起始地址处前 8 个字RESERVE_LEAD_WORDS是否为0xffffffff未写满即视为上传未完成并验证向量表第二个字入口地址落在合法的 Flash 区间内对 CAN 启动的固件跳转前先初始化并喂狗stm32_watchdog_init()/stm32_watchdog_pat()一旦应用在 30 秒内未改写 RTC 标志导致看门狗复位Bootloader 会停留在自身等待用户刷入修复固件AP_Bootloader.cpp。跳转前还会按 MCU 系列关闭外设时钟与缓存F7/H7 需SCB_DisableDCache/ICache并把SCB_VTOR切换到应用向量表最后以do_jump()汇编代码装载栈指针与入口地址完成交接。六、固件加载通道不止 USB 与 UART虽然 README 重点描述的是 USB/UART 两条通道但从源码结构看Bootloader 实际上支持四类加载途径通道源码说明USB / UARTsupport.cpp BOOTLOADER_DEV_LIST默认通道由SERIAL_ORDER决定监听列表CANcan.cpp / can.h基于 DroneCAN/libcanard通过 CAN 总线刷写配合RTC_BOOT_CANBL快速进入、can_set_node_id设置节点以太网network.cpp / network.h通过网络刷写与状态上报受 AP_Bootloader_config.h 中AP_BOOTLOADER_NETWORK_ENABLED控制SD 卡flash_from_sd.cpp / flash_from_sd.h从 SD 卡读取固件镜像刷写由AP_BOOTLOADER_FLASH_FROM_SD_ENABLED开关控制默认关闭从 AP_Bootloader.cpp 的 main() 可以看到完整的启动决策链flash_init() 初始化 Flash 页表布局 check_ecc_errors()H7 启用 ECC 时 检查 ECC 错误 快速启动判定AP_FASTBOOT_ENABLED 看门狗复位 / RTC_BOOT_FAST / CAN 更新请求 check_good_firmware() 固件完好性检查可选 可选“stay in bootloader”引脚 强制停留 ext_flash.init() 外置 Flash 初始化若有 try_boot ? jump_to_app() 直接启动应用 init_uarts() / can_start() / network.init() flash_from_sd() SD 卡刷写 bootloader(timeout) 进入协议监听循环USB/UART 超时后 jump_to_app() 无命令则启动应用这段流程清晰地体现了固件好就秒启动、固件坏就停留等待刷写的容错设计超时时间默认HAL_BOOTLOADER_TIMEOUT5000ms见 AP_Bootloader.cpp一旦在超时窗口内收到有效命令lock_bl_port()会锁定端口并清零超时保证刷写过程中不会中途跳走。七、Bootloader 目录源码地图以下文件均位于 Tools/AP_Bootloader文件职责AP_Bootloader.cpp入口main()启动决策、看门狗、快速启动逻辑bl_protocol.cpp刷写协议状态机全部命令处理bl_protocol.h协议声明、LED 状态定义support.cppUART/USB 读写、Flash 读写擦除封装、board_infosupport.hstruct boardinfo定义与 Flash 函数声明can.cppCAN 通道刷写支持network.cpp以太网通道刷写与状态输出flash_from_sd.cppSD 卡固件刷写AP_Bootloader_config.h编译期开关SD 刷写、网络刷写mcu_f1/f3/f4/f7/h7/g4/l4.h各 MCU 系列的 ID/修订版描述表board_types.txt板卡 ID 注册表wscriptwaf 构建脚本其中boardinfo结构体support.h是上位机识别板卡的核心数据在 AP_Bootloader.cpp 中由编译期宏初始化struct boardinfo board_info { .board_type APJ_BOARD_ID, // 来自 hwdef-bl.dat .board_rev 0, .fw_size (BOARD_FLASH_SIZE - (FLASH_BOOTLOADER_LOAD_KB FLASH_RESERVE_END_KB APP_START_OFFSET_KB))*1024, .extf_size (EXT_FLASH_SIZE_MB * 1024 * 1024) - (EXT_FLASH_RESERVE_START_KB EXT_FLASH_RESERVE_END_KB) * 1024 };八、实践总结为自定义板卡启用 Bootloader 的步骤综合 README 与源码为一个新的 STM32 飞控板启用 Bootloader 的完整链路如下编写硬件配置在libraries/AP_HAL_ChibiOS/hwdef/BOARDNAME/下创建hwdef.dat主固件与hwdef-bl.datBootloader后者至少声明MCU、APJ_BOARD_ID、FLASH_SIZE_KB、FLASH_BOOTLOADER_LOAD_KB、SERIAL_ORDER注册板卡 ID在 Tools/AP_Bootloader/board_types.txt 中为板卡申请一个唯一 ID遵循 1000~19999 区间规则并让hwdef-bl.dat中的APJ_BOARD_ID引用该宏构建 Bootloader./waf configure --board BOARDNAME --bootloader ./waf bootloader获取产物build/BOARDNAME/bin/下的.bin/.hex通过 DFU 上传安装 intelhex 后自动生成.hexbuild/BOARDNAME/AP_Bootloader的.elf用于 gdb 调试验证通道确认SERIAL_ORDER覆盖了目标 USB 口与调试串口上电后 Bootloader 会按第四节所述流程等待主机命令或直接启动应用。这套 Bootloader 之所以能在 Pixhawk 生态中即插即用正是因为它严格遵循了 PX4 兼容的协议版本 5 与统一的板卡 ID 注册体系——理解这两点就掌握了整个 ArduPilot 固件刷写链路的地基。【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考