# bootloader **Repository Path**: xuedejin/bootloader ## Basic Information - **Project Name**: bootloader - **Description**: 这是一个基于 STM32F103C8T6实现的 OTA 引导程序,负责在 MCU 启动时校验应用镜像、管理双槽更新状态、完成安全跳转,并在更新失败或预览阶段触发回滚。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-10-11 - **Last Updated**: 2026-10-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: bootloader, OTA, stm32, HAL ## README # STM32 OTA Bootloader 这是一个基于 STM32F103C8T6(Blue Pill / C8T6)实现的 OTA 引导程序,负责在 MCU 启动时校验应用镜像、管理双槽更新状态、完成安全跳转,并在更新失败或预览阶段触发回滚。 该工程基于 STM32CubeMX 生成的工程骨架,并使用 CMake + Ninja 进行构建,适合在 STM32F1 系列中做 Bootloader + 固件升级方案。 配套 APP 源码仓库:[https://gitee.com/xuedejin/iot_ota_app](https://gitee.com/xuedejin/iot_ota_app)。 ## 1. 功能概览 - 双应用槽设计:A / B 两个镜像槽位 - OTA 状态持久化:记录 active / pending / boot_count,并保存在 Flash 状态区 - CRC32 校验:验证应用镜像完整性与合法性 - 向量表与 MSP/Reset_Handler 合法性检查 - 启动前回滚机制:pending 镜像超过启动次数或CRC失效时自动回滚 - 调试串口输出:通过 USART1(PA9 TX / PA10 RX)输出状态信息 - 可直接与上层应用配合完成固件升级、预览和确认流程 ## 2. 目标硬件与存储布局 该项目针对 STM32F103C8T6 设备,Flash 容量约 64KB,内存布局如下: | 区域 | 起始地址 | 大小 | 说明 | | --- | --- | --- | --- | | Bootloader | 0x08000000 | 8KB | 引导区,存放本 Bootloader | | App Slot A | 0x08002000 | 24KB | 活动/备份应用槽 A | | App Slot B | 0x08008000 | 24KB | 活动/备份应用槽 B | | OTA Flag | 0x0800E000 | 4KB | 双页 OTA 状态记录区 | | Reserve | 0x0800F000 | 4KB | 预留区 | 核心分区定义见 [Core/Inc/boot.h](Core/Inc/boot.h)。 ## 3. 关键代码说明 ### 3.1 启动入口 - [Core/Src/main.c](Core/Src/main.c) - 完成 HAL 初始化、时钟配置、串口初始化 - 进入主循环后持续调用 `Start_BootLoader()` - 若 Bootloader 未成功启动应用,则 10 秒后重试 ### 3.2 Bootloader 启动逻辑 - [Core/Src/boot_start.c](Core/Src/boot_start.c) - `Start_BootLoader()`:读取 OTA 状态、校验 active 和 pending 镜像 - 负责跳转到对应槽位的应用入口 - 如果 pending 镜像无效、超过最大启动次数,或状态异常,则触发回滚 ### 3.3 OTA 状态机与 Flash 管理 - [Core/Src/boot.c](Core/Src/boot.c) - `Boot_IsImageValid()`:检查应用镜像是否合法 - `Boot_ReadState()`:读取 OTA 状态快照 - `Boot_SetPending()`:设置待升级镜像 - `Boot_ConfirmPending()`:确认升级 - `Boot_ClearPending()`:清除 pending,执行回滚 - `Boot_EraseSlot()` / `Boot_ProgramSlotData()`:擦除并编程 app slot - 使用双页写入策略,记录结构体中包含 `magic`、`version`、`sequence`、`record_crc32`、`commit` 等字段,确保掉电/中断时不会产生半写入状态 ### 3.4 串口输出 - [Core/Src/usart.c](Core/Src/usart.c) - 配置了 USART1,波特率为 115200 - `Serial_SendString()` 输出状态日志,便于观察 OTA 流程 ## 4. 启动流程说明 主流程大致如下: 1. Bootloader 启动 2. 读取 OTA 状态区中的 `active_slot` / `pending_slot` 3. 检查 `pending_slot` 是否存在并有效 - 若无效,执行回滚清理 - 若启动次数超限,也执行回滚 4. 若 `pending_slot` 合法且未超限,则递增计数并尝试启动该 pending 镜像 5. 若 `pending_slot` 无效或没有待升级任务,则校验 `active_slot` 是否有效 6. 若 active 镜像有效,则跳转到该应用程序 7. 若 active / pending 均无效,则 Bootloader 停留并等待外部处理 ## 5. OTA 状态字段 `BootFlagRecord` 结构体记录了 OTA 的关键状态,主要包括: - `active_slot`:当前已确认可用的活动槽 - `pending_slot`:待升级槽 - `active_size` / `active_crc32`:当前活动镜像大小和 CRC32 - `pending_size` / `pending_crc32`:待升级镜像大小和 CRC32 - `boot_count`:该 pending 镜像已经试运行的次数 - `sequence`:页记录序列号,用于双页比较新旧记录 ## 6. 使用 VS Code 按 F5 构建、下载和调试 本项目配置为通过 VS Code 的调试启动流程构建并启动 ST-Link 调试,不要求在 PowerShell 中直接调用 `cmake` 或 `st-flash`。 1. 使用 VS Code 打开项目根目录,并安装/启用提供 STM32Cube 调试功能的扩展及其工具包(包括项目配置所需的 Cube CMake、ST ARM Clang 和 ST-Link GDB Server)。 2. 连接目标板与 ST-Link,确认 VS Code 中已正确选择项目和调试器。 3. 打开“运行和调试”,选择 `STM32Cube: Launch ST-Link GDB Server`,按 **F5**。 4. `.vscode/launch.json` 中的 `preBuild` 会调用 STM32 扩展的构建命令;构建后,调试配置从当前项目上下文取得 ELF 文件,并启动 ST-Link GDB 调试会话,下载/调试目标固件。 当前调试配置为 `stlinkgdbtarget`,入口设为 `main`。它依赖 VS Code 中对应的 STM32 扩展命令及项目上下文;因此,直接在普通 PowerShell 中运行 `cmake` 或 `st-flash` 报“无法识别”并不代表 F5 配置不可用。若按 F5 时失败,应查看 VS Code 的“输出”面板和调试控制台中的扩展、构建或连接错误。 工程同时提供 CMake 的 Debug/Release 预设(见 [CMakePresets.json](CMakePresets.json))。如果需要脱离 VS Code 调试扩展进行命令行构建,则需自行安装可用的 CMake、Ninja 及 `starm-clang` 工具链,并将其加入 `PATH`;命令行烧录也需另行配置相应下载工具。此方式不是本项目默认的 F5 工作流。 ## 7. 调试串口 Bootloader 使用 USART1 输出启动和 OTA 状态日志:PA9 为 TX,PA10 为 RX,串口参数为 115200、8N1。可连接 USB 转串口适配器查看日志;串口日志与 ST-Link 下载/调试是独立功能。 ## 8. 应用侧配合方式 本 Bootloader 只负责“启动与回滚”,并不直接提供完整的网络/串口 OTA 协议。上层应用(或外部固件更新主机)通常需要遵循如下流程: 1. 将新固件写入非活动槽(例如 Slot B) 2. 校验新镜像的大小和 CRC32 3. 调用 `Boot_SetPending()` 设置待升级槽 4. 让 MCU 重启 5. Bootloader 在下一次启动中以 pending 镜像进行预览 6. 若用户确认成功,则调用 `Boot_ConfirmPending()`,将 pending 提升为 active 7. 若升级失败,则调用 `Boot_ClearPending()` 退回 active 镜像 ## 9. 典型文件结构 ```text . ├── CMakeLists.txt ├── CMakePresets.json ├── STM32F103xx_FLASH.ld ├── startup_stm32f103xb.s ├── bootloader.ioc ├── Core/ │ ├── Inc/ │ │ ├── boot.h │ │ ├── boot_start.h │ │ ├── gpio.h │ │ ├── main.h │ │ └── usart.h │ └── Src/ │ ├── boot.c │ ├── boot_start.c │ ├── gpio.c │ ├── main.c │ ├── stm32f1xx_it.c │ ├── usart.c │ └── system_stm32f1xx.c ├── Drivers/ ├── cmake/ └── build/ ``` ## 10. 说明与注意事项 - 该工程为 Bootloader 代码,不能直接作为最终产品应用主程序运行;真正的用户应用应当被烧录到 App Slot 中,并通过 Bootloader 跳转执行。 - 向量表地址必须与镜像所在槽位一致,否则 Bootloader 会拒绝跳转。 - 该设计依赖 Flash 擦除/编程的可靠性,因此需要保证 MCU Flash 未被写坏,并确保更新过程有稳定电源。 - 当前 `BOOT_MAX_PENDING_BOOTS` 定义为 3,超过此阈值后将触发回滚,避免无限重试损坏系统。 ## 11. 适用场景 - STM32 单片机 OTA 升级 - 双槽安全启动方案 - 工业设备、网关、嵌入式控制器的可靠更新机制 - 需要应用回退与预览验证的升级场景 ## 12. 结论 该项目实现了一套较完整的 STM32 双槽 OTA BootLoader 方案,重点解决了: - 固件升级前的镜像验证 - 应用槽切换与启动安全 - Bootloader 读写 Flash 的状态管理 - Graceful rollback / bootcount 机制 - 稳定的无损升级状态维护 适合在 STM32F1 平台上扩展为实际产品级固件升级模块。