# 光磁头固件在线升级方案 — 更改说明 ## 1. 方案概述 采用 **MCUboot Serial Recovery** 方案,复用 usart1 协议口实现固件升级。 - 应用层正常运行时,usart1 由 0x7EE7 协议占用 - 收到升级命令后,应用层直接重启 - MCUboot 接管 usart1,等待 3 秒看是否有 mcumgr 命令 - 主板在 3 秒内发送 mcumgr 命令 → 进入 serial recovery 模式 - 主板上传签名固件 → MCUboot 验证签名 → swap → 重启运行新固件 **关键特性**: - 零额外硬件(复用 usart1) - 应用层不运行 mcumgr,与 0x7EE7 协议零冲突 - MCUboot 内置 RSA 签名验证 - 升级中断电可回滚,设备不会变砖 --- ## 2. 涉及的文件 ### 2.1 新建文件 | 文件 | 用途 | |---|---| | `sysbuild.conf` | 启用 MCUboot bootloader + 签名密钥路径 | | `sysbuild/mcuboot.conf` | MCUboot 配置:serial recovery、签名、喂狗 | | `sysbuild/mcuboot.overlay` | MCUboot 设备树覆盖(当前为空,保留扩展) | | `src/dfu.cpp` | DFU 模块初始化确认打印 | | `doc/固件升级方案.md` | 详细升级方案文档 | ### 2.2 修改文件 | 文件 | 改动 | |---|---| | `include/com.hpp` | 新增 `DfuCommand` 回调(条件编译 `CONFIG_APP_DFU`),处理 0xFF 指令 | | `CMakeLists.txt` | 已有 `zephyr_sources_ifdef(CONFIG_APP_DFU src/dfu.cpp)` 控制 | | `Kconfig` | 已有 `config APP_DFU default y` | ### 2.3 未修改文件 | 文件 | 说明 | |---|---| | `boards/dr2501a/dr2501a_g0b0ce.dts` | flash 分区已就绪(boot=48KB, slot0/1=200KB, storage=64KB) | | `prj.conf` | 无需额外配置(应用层不运行 mcumgr) | | `boards/use_ms.overlay` | 传感器配置,无改动 | --- ## 3. 配置说明 ### 3.1 sysbuild.conf ``` SB_CONFIG_BOOTLOADER_MCUBOOT=y SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="${ZEPHYR_BASE}/../bootloader/mcuboot/root-rsa-2048.pem" ``` - 启用 MCUboot bootloader - 开发阶段使用 MCUboot 自带的 RSA-2048 密钥 - 量产时替换为自生成密钥 ### 3.2 sysbuild/mcuboot.conf ``` CONFIG_MCUBOOT_SERIAL=y # 启用 serial recovery CONFIG_BOOT_SERIAL_UART=y # 使用 UART 接口 CONFIG_BOOT_SERIAL_ENTRANCE_GPIO=n # 禁用 GPIO 按钮检测 CONFIG_BOOT_SERIAL_WAIT_FOR_DFU=y # 等待 mcumgr 命令触发 CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT=3000 # 等待 3 秒 CONFIG_BOOT_WATCHDOG_FEED=y # 喂狗(避免升级过程中看门狗复位) CONFIG_BOOT_SIGNATURE_TYPE_RSA=y # RSA 签名验证 CONFIG_BOOT_ERASE_PROGRESSIVELY=y # 渐进擦除(优化升级速度) ``` ### 3.3 条件编译 DFU 功能通过 `CONFIG_APP_DFU` 控制: - `y`(默认):编译 dfu.cpp,com.hpp 中包含 0xFF 指令处理 - `n`:完全移除 DFU 功能(零开销) --- ## 4. 协议扩展 ### 4.1 新增指令:0xFF 升级命令 | 子命令 | 方向 | 行为 | |---|---|---| | `0x01` | 主板→小板 | 进入升级模式(直接重启) | | `0x02` | 主板→小板 | 查询升级状态 | | `0x02` | 小板→主板 | 回复 0x00 = 应用层正常运行 | ### 4.2 帧格式 ``` 进入升级模式: 主板 → 小板: [7E E7] [FF] [01] [01] [CRC_L] [CRC_H] 小板: 无回复(直接重启) 查询升级状态: 主板 → 小板: [7E E7] [FF] [02] [00] [CRC_L] [CRC_H] 小板 → 主板: [7E E7] [FF] [02] [01] [00] [CRC_L] [CRC_H] ``` --- ## 5. 升级流程 ### 5.1 首次构建与烧录(需要调试器) ```bash # 构建(MCUboot + 应用) west build -p auto -b dr2501a_g0b0ce/stm32g0b0xx \ --sysbuild app/app_photomagnetic \ -d build # 烧录(一次性) west flash -d build ``` ### 5.2 后续升级(通过 UART,不需要调试器) ``` 步骤1: 主板发送升级命令 主板 → 小板: [7E E7] [FF] [01] [01] [CRC_L] [CRC_H] 步骤2: 小板重启,MCUboot 接管 usart1 MCUboot 等待 3 秒看是否有 mcumgr 命令 步骤3: 主板切换到 mcumgr 模式(3 秒内) mcumgr --conntype=serial --connstring='dev=/dev/ttyUSBx,baud=115200' \ image upload -e zephyr.signed.bin 步骤4: 标记待测试 mcumgr image test 步骤5: 复位触发 swap mcumgr reset 步骤6: MCUboot 验证签名 → swap → 重启运行新固件 ``` --- ## 6. 签名密钥管理 ### 6.1 开发阶段 使用 MCUboot 自带的开发密钥: ``` ${ZEPHYR_BASE}/../bootloader/mcuboot/root-rsa-2048.pem ``` sysbuild.conf 中已配置,构建时自动签名。 ### 6.2 量产阶段 ```bash # 生成自定义密钥对 pip install imgtool imgtool keygen -k keys/my-signing-key.pem -t rsa-2048 # 更新 sysbuild.conf SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="${APP_DIR}/keys/my-signing-key.pem" ``` > ⚠️ 私钥必须安全保管,丢失后无法签名新固件。 ### 6.3 签名验证流程 ``` 构建时:imgtool 用私钥签名 → zephyr.signed.bin 运行时:MCUboot 用公钥验证 → 验证通过才 swap ``` --- ## 7. Flash 分区布局 | 分区 | 偏移 | 大小 | 用途 | |---|---|---|---| | boot_partition | 0x00000 | 48KB | MCUboot bootloader | | slot0_partition | 0x0C000 | 200KB | 应用镜像(当前运行) | | slot1_partition | 0x3E000 | 200KB | 升级镜像(待 swap) | | storage_partition | 0x70000 | 64KB | NVS 存储 | 分区已在 `dr2501a_g0b0ce.dts` 中定义,无需修改。 --- ## 8. 安全机制 | 机制 | 说明 | |---|---| | 镜像签名 | RSA-2048 签名验证,公钥烘焙进 bootloader | | 未确认自动回滚 | test 模式下重启未确认 → MCUboot 自动回滚到原固件 | | 升级中断保护 | 升级中断电 → MCUboot 回滚,设备不会变砖 | | 等待超时 | 3 秒内无 mcumgr 命令 → 正常启动应用 | --- ## 9. 主板端配合 ### 9.1 升级时序 ``` t=0ms: 主板发送升级命令 [7E E7][FF][01][01][CRC] t=100ms: 小板重启 t=200ms: MCUboot 启动,开始等待 mcumgr 命令 t=200ms~3200ms: 主板发送 mcumgr 命令(必须在 3 秒内) t=3200ms: MCUboot 超时,正常启动应用(如果没收到 mcumgr) ``` ### 9.2 关键约束 - 主板必须在小板重启后 **3 秒内** 发送 mcumgr 命令 - 波特率:115200(与应用层协议一致) - 升级完成后,小板自动重启运行新固件 - 主板需检测小板重启(等待新固件的 ID 帧),然后切回 0x7EE7 协议模式 --- ## 10. 注意事项 1. **首次烧录需要调试器**:MCUboot + 应用首次烧录需要 J-Link/OpenOCD;后续升级全部通过 UART 2. **3 秒窗口**:主板必须在小板重启后 3 秒内发送 mcumgr 命令,否则 MCUboot 会正常启动应用 3. **签名密钥**:开发阶段使用默认密钥(不安全);量产必须替换为自生成密钥 4. **降级保护**:开发阶段建议关闭(`CONFIG_BOOT_DOWNGRADE_PREVENTION=n`),方便回退 5. **usart1 共享**:应用层协议和 mcumgr 在不同阶段使用同一 UART,不会冲突 6. **DFU 开关**:通过 `CONFIG_APP_DFU`(Kconfig)控制,默认启用;设为 n 可完全移除 DFU 功能 --- ## 11. 文件清单 ``` app/app_photomagnetic/ ├── sysbuild.conf # [新建] 启用 MCUboot ├── sysbuild/ │ ├── mcuboot.conf # [新建] MCUboot 配置 │ └── mcuboot.overlay # [新建] MCUboot 设备树(当前为空) ├── include/ │ └── com.hpp # [修改] 新增 0xFF 升级命令处理 ├── src/ │ └── dfu.cpp # [新建] DFU 模块初始化 └── doc/ ├── 固件升级方案.md # [新建] 详细方案文档 └── 升级更改说明.md # [新建] 本文档 ```