# 光磁头固件升级操作指南 ## 1. 环境准备 ### 1.1 安装依赖 ```bash # GUI 工具必需:串口库 pip install pyserial # 固件签名工具(imgtool 随 Zephyr/MCUboot 自带,也可单独安装) pip install imgtool # 可选:命令行升级(smpmgr)——GUI 已内置 SMP 客户端,不装也能升级 pip install smpmgr ``` ### 1.2 生成签名密钥(量产阶段) ```bash # 在应用目录下生成密钥对 cd /home/issac-zys/code/zephyr_prj_template/app/app_photomagnetic mkdir -p keys imgtool keygen -k keys/mykey.pem -t ecdsa-p256 # 更新 sysbuild.conf 中的密钥路径与签名类型 # SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y # SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="${APP_DIR}/keys/mykey.pem" ``` > 开发阶段可跳过此步,使用 MCUboot 自带的开发密钥 `root-ec-p256.pem`。 > ⚠️ **密钥算法必须与签名类型一致**: > - `-t ecdsa-p256` 对应 `SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y` > - `-t rsa-2048` 对应 `SB_CONFIG_BOOT_SIGNATURE_TYPE_RSA=y` > 不匹配会报链接错误(如 `undefined reference to 'ecdsa_pub_key'`)。 > 本项目 boot 分区只有 48KB,建议用 ECDSA-P256(RSA 会把 MCUboot 撑到接近极限)。 > 更换密钥后必须**完整重建**(删 build 目录),否则签名/验签用的还是旧公钥。 --- ## 2. 首次构建与烧录(需要调试器) ### 2.1 构建 MCUboot + 应用 ```bash cd /home/issac-zys/code/zephyr_prj_template # 构建(sysbuild 模式,自动构建 MCUboot + 应用) west build -p auto -b dr2501a_g0b0ce/stm32g0b0xx \ --sysbuild app/app_photomagnetic \ -d build ``` 构建产物: - `build/mcuboot/zephyr/zephyr.hex` / `.bin` — MCUboot bootloader(0x08000000) - `build/app_photomagnetic/zephyr/zephyr.signed.hex` / `.bin` — 签名后的应用固件(0x0800C000) > ⚠️ 注意:顶层 `west flash -d build` 只会烧应用镜像,不会烧 MCUboot!MCUboot 必须单独烧录。 ### 2.2 烧录(一次性,需要调试器) ```bash # ① 先烧 MCUboot 到 0x08000000(覆盖出厂 godtek bootloader,只需一次) west flash -d build/mcuboot # ② 再烧签名应用到 slot0 (0x0800C000) west flash -d build ``` > 两条命令顺序不能反:没有 MCUboot 时,0x0800C000 的镜像头无法被引导,设备会完全无反应。 ### 2.3 验证首次启动 串口调试口(usart3)应输出: ``` *** Booting MCUboot build ... *** Booting Zephyr OS build ... [dfu] init: upgrade command enabled (0xFF) [com] init: rx table=4, id sent [main] init on dr2501a_g0b0ce ``` 协议口(usart1)应输出 ID 帧: `[7E E7][01][03][XX XX XX][CRC]` --- ## 3. 后续升级(通过 UART,不需要调试器) ### 3.1 升级流程图 ``` ┌─────────────────────────────────────────────────────────────┐ │ 主板 / 测试工具 │ │ 1. 发送升级命令 [7E E7][FF][01][01][CRC] │ │ 2. 等待 300ms(小板重启) │ │ 3. 通过 smpmgr 上传固件(3 秒内) │ │ 4. 标记待测试 + 复位 │ │ 5. 等待新固件启动 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 光磁头(小板) │ │ 1. 收到升级命令 → 直接重启 │ │ 2. MCUboot 启动 → 等待 SMP 命令(3 秒) │ │ 3. 收到 SMP 命令 → 进入 serial recovery │ │ 4. 接收固件 → 直接写入 slot0(主槽,串口恢复固定写主槽) │ │ 5. 复位 → MCUboot 校验签名 → 启动新固件 │ └─────────────────────────────────────────────────────────────┘ ``` > ⚠️ **重要:串口恢复(serial recovery)是把镜像直接写入 slot0(主槽)**, > 不是写 slot1 再 swap(那是应用内 mcumgr DFU 的做法)。因此: > 1. **升级过程中绝不能抢占/打开串口**(比如用其他串口工具、或让本工具重新 Connect), > 否则上传中断会把 slot0 擦到一半,设备无法启动; > 2. 上传中断后设备不会变砖——MCUboot 仍在运行并停留在 serial recovery 等待区, > 直接用 smpmgr 重新上传即可恢复(或 `west flash -d build` 重烧应用); > 3. 设备异常停在 bootloader 时,再点一次升级按钮也能恢复(0xFF 命令对 MCUboot 无害, > smpmgr 会自动连上当前等待中的 serial recovery)。 ### 3.2 使用 smpmgr CLI 升级 #### 步骤 1: 发送升级命令 使用串口工具或 Python 发送升级命令: ```python import serial, struct, time def send_upgrade(port='/dev/ttyUSB0'): cmd = bytes([0x7E, 0xE7, 0xFF, 0x01, 0x01]) crc = 0xFFFF for b in cmd[2:]: crc ^= b for _ in range(8): crc = (crc >> 1) ^ 0xA001 if crc & 1 else crc >> 1 cmd += struct.pack(' 可选:仍可用命令行一键升级(需已安装 smpmgr): > `smpmgr --port /dev/ttyUSB0 --timeout 10 upgrade build/app_photomagnetic/zephyr/zephyr.signed.bin` ### 3.4 自动化升级脚本 ```bash #!/bin/bash # upgrade.sh - 光磁头固件升级脚本 # 用法: ./upgrade.sh /dev/ttyUSB0 zephyr.signed.bin PORT=${1:-/dev/ttyUSB0} FIRMWARE=${2:-build/app_photomagnetic/zephyr/zephyr.signed.bin} echo "=== 光磁头固件升级 ===" echo "串口: $PORT" echo "固件: $FIRMWARE" # 检查固件文件 if [ ! -f "$FIRMWARE" ]; then echo "错误: 固件文件不存在" exit 1 fi # 发送升级命令 echo "1. 发送升级命令..." python3 -c " import serial, struct, time with serial.Serial('$PORT', 115200, timeout=1) as ser: cmd = bytes([0x7E, 0xE7, 0xFF, 0x01, 0x01]) crc = 0xFFFF for b in cmd[2:]: crc ^= b for _ in range(8): crc = (crc >> 1) ^ 0xA001 if crc & 1 else crc >> 1 cmd += struct.pack(' 串口恢复(serial recovery)是直接把镜像写入 slot0 主槽,固件即刻生效、 > 不存在“待测试/回滚”的概念。旧版文档里的 swap/回滚描述来自应用内 mcumgr DFU, > 本方案不适用。 ### 4.1 上传中断/镜像损坏后的恢复 上传中断只会擦掉 slot0 一部分,MCUboot 仍然在运行并停留在 serial recovery 等待区, **不需要调试器**即可恢复: ```bash # 直接重传即可(设备已在 bootloader 等待,无需再发升级命令) smpmgr --port /dev/ttyUSB0 --timeout 10 upgrade \ build/app_photomagnetic/zephyr/zephyr.signed.bin ``` 或使用 GUI:再次点击 **Upgrade Firmware**(0xFF 命令对 MCUboot 无害,smpmgr 会自动连上)。 ### 4.2 强制恢复(需要调试器) 如果连 MCUboot 都进不去(比如误烧了 boot 分区): ```bash # 重新烧录 MCUboot + 应用 west flash -d build/mcuboot west flash -d build ``` --- ## 5. 故障排查 | 现象 | 原因 | 解决方案 | |---|---|---| | smpmgr 超时 | 上传未在 3 秒窗口内开始 | 先确认设备已进 bootloader(串口有 MCUboot 日志)再上传 | | 上传中断 | 串口被其他工具/GUI 占用 | 关闭其他串口工具,重新上传(需从头传,不支持断点续传) | | 上传后无法启动 | 上传中断擦坏了 slot0 | 设备停在 bootloader,直接重传或 `west flash -d build` 重烧应用 | | 签名验证失败 | 密钥不匹配 | 用构建时相同的密钥(开发期 `root-ec-p256.pem`)签名 | | smpmgr 连接失败 | 端口错误/被占用 | 确认端口号,关闭占用程序后再试 | --- ## 6. 注意事项 1. **3 秒窗口**:小板重启后,MCUboot 等待 SMP 命令 3 秒;超时则正常启动应用 2. **波特率**:应用层协议和 smpmgr 都使用 115200 3. **签名**:开发阶段使用默认密钥 `root-ec-p256.pem`;量产必须替换(且必须用 ECDSA-P256,RSA 装不进 48KB 分区) 4. **升级期间勿占用串口**:上传过程中不要打开其他串口工具、不要让 GUI 重新 Connect,否则上传中断会擦坏 slot0 5. **调试器**:首次烧录 MCUboot 需要;后续升级不需要 6. **断电保护**:升级中断电 → MCUboot 仍在运行,停在 serial recovery 等待区,重新上传即可恢复,设备不会变砖 --- ## 7. 工具对比 | 工具 | 安装方式 | 优点 | |---|---|---| | **GUI 工具(推荐)** | 集成在 `scripts/test_gui.py`,内置 SMP 客户端 | 图形界面,一键升级,无需额外依赖(smpmgr/mcumgr 均可不要) | | **smpmgr** | `pip install smpmgr` | 命令行,支持 Serial/BLE/UDP,适合脚本化 | | **mcumgr CLI** | Go 编译/下载二进制 | Zephyr 官方工具,功能完整 |