From 5dcbdbad655c2d69ab3d7fb583c08c507655945e Mon Sep 17 00:00:00 2001 From: "evan.liu" <583229071@qq.com> Date: Fri, 4 Sep 2026 20:49:15 +0800 Subject: [PATCH] V1.00.22 + OTA tool bank-misselection fix (triple protection) - firmware: version bump to V1.00.22 (0x00010016), no code change - ble_ota_update.py: cur-bank detection now reads the full devinfo output and parses strictly (early break at the 'cur bank:' prefix could miss 'APP2' and silently default to APP1 -> wrong payload selection, caught by the device bank_mismatch guard on hardware) - new pre-flight check_blob_bank(): payload vector reset PC must land in the target bank before transferring (BLE and UART paths) - UART path: post-reboot verification over the text CLI (bank+version), deterministic PASS/FAIL like the BLE path - verified: UART OTA APP2->APP1 V1.00.22 full pass with auto-verify - docs: dev log 45, AGENTS.md sync --- AGENTS.md | 6 +- Boot/MDK-ARM/build.log | 2 +- docs/开发日志.md | 27 +++++++ mcm-ddc-ble/MDK-ARM/bin/mcm-ddc-ble-app2.bin | Bin 55708 -> 55708 bytes mcm-ddc-ble/MDK-ARM/bin/mcm-ddc-ble.bin | Bin 55408 -> 55408 bytes mcm-ddc-ble/inc/app_version.h | 4 +- tools/ble_ota_update.py | 72 ++++++++++++++----- tools/out/caiic_ble_dual.bin | Bin 203164 -> 203164 bytes tools/out/caiic_ble_dual.hex | 22 +++--- tools/out/caiic_ble_dual_ota.bin | Bin 55408 -> 55408 bytes tools/out/caiic_ble_dual_ota.json | 4 +- tools/out/caiic_ble_dual_ota_app2.bin | Bin 55708 -> 55708 bytes tools/out/caiic_ble_dual_ota_app2.json | 4 +- tools/out/caiic_ble_dual_ota_dual.bin | Bin 111168 -> 111168 bytes tools/out/mothercup_ble_ota.bin | Bin 111168 -> 111168 bytes tools/out/mothercup_ble_prod.bin | Bin 88176 -> 88176 bytes tools/out/mothercup_ble_prod.hex | 14 ++-- tools/out/mothercup_ble_prod_ota.bin | Bin 55408 -> 55408 bytes tools/out/mothercup_ble_prod_ota.json | 4 +- tools/out/mothercup_ble_prod_ota_app2.bin | Bin 55708 -> 55708 bytes tools/out/mothercup_ble_prod_ota_app2.json | 4 +- 21 files changed, 114 insertions(+), 49 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ddaec93..55b2fd2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,14 +5,14 @@ 本仓库是 **mothercup(母乳杯)** 产品的完整代码仓库,包含三大部分: 1. **设备固件** — 基于国民技术(Nations)**N32WB031 BLE SoC**(Cortex-M0,64MHz HSI,**板载硅片实测 256KB Flash**(0x01000000~0x0103FFFF,开发日志 §37),RAM 48KB+16KB): - - **`mcm-ddc-ble/`** — 唯一活跃的应用固件工程(APP,链接在 APP1 bank `0x01008000`/112KB)。以 SDK rdtss 例程为蓝本,集成 FreeRTOS、UART CLI、BLE 自定义 GATT 服务(CLI 透传 / 设备信息查询 / BLE OTA 双 bank 直写升级)、bootsetting 与 APP_DATA 参数区结构化读写命令。当前版本 **V1.00.21**(`mcm-ddc-ble/inc/app_version.h`)。历史上曾有 `mcm-ddc-04/` 主工程,**已删除**,其功能已全部并入本工程。 + - **`mcm-ddc-ble/`** — 唯一活跃的应用固件工程(APP,链接在 APP1 bank `0x01008000`/112KB)。以 SDK rdtss 例程为蓝本,集成 FreeRTOS、UART CLI、BLE 自定义 GATT 服务(CLI 透传 / 设备信息查询 / BLE OTA 双 bank 直写升级)、bootsetting 与 APP_DATA 参数区结构化读写命令。当前版本 **V1.00.22**(`mcm-ddc-ble/inc/app_version.h`)。历史上曾有 `mcm-ddc-04/` 主工程,**已删除**,其功能已全部并入本工程。 - **`Boot/`** — 自写精简 bootloader(链接在 `0x01000000`/16KB):校验 bootsetting 记录自身完整性(magic + 结构体 CRC32)后按 active bank 的 `start_address` 直接跳转;**不校验镜像 CRC(CRC 校验在 OTA 升级过程中完成)**;记录无效或地址越界回退 APP1。 2. **手机 App `SmartAssiter/`** — uni-app **Vue3 + TypeScript** 工程(HBuilderX 项目管理,无 package.json),通过 BLE 连接设备:查看运行参数(温度/电压/转速等)、CLI 终端、OTA 升级页(当前停用,见下)。另有登录/注册/用户信息等云端业务页面。 3. **PC 工具 `tools/`** — 整片烧录包制作/烧录脚本 + bleak 蓝牙测试客户端。 关键文档: -- `docs/开发日志.md` — 固件全程开发日志(44 节,含所有踩坑根因与设计决策,排查问题先查这里) +- `docs/开发日志.md` — 固件全程开发日志(45 节,含所有踩坑根因与设计决策,排查问题先查这里) - `docs/ble_protocol.md` — CAIIC BLE 通信协议 V1.1(帧格式/GATT UUID/三类业务流程/维护命令/手机端开发指南) - `SmartAssiter/docs/修改记录_*.md` — App 侧每次改造的详细记录 @@ -95,7 +95,7 @@ mcm-ddc-ble/ "D:\Keil_v5\UV4\UV4.exe" -b caiic_boot.uvprojx -j0 -o build.log # Boot 增量构建 ``` -要求保持 **0 Error(s), 0 Warning(s)**。当前基线(V1.00.21):`Code=48872 RO-data=4980 RW-data=2076 ZI-data=29116`。 +要求保持 **0 Error(s), 0 Warning(s)**。当前基线(V1.00.22):`Code=48872 RO-data=4980 RW-data=2076 ZI-data=29116`。 **固件版本号约定(重要)**:每次修改固件代码必须递增 `mcm-ddc-ble/inc/app_version.h` 中的 `APP_FW_VERSION` 与 `APP_FW_VERSION_NUM`(格式 `0x00MMmmpp`,通常补丁位 +1),用于识别板上实际运行的固件;工程名与出包文件名保持不变。 diff --git a/Boot/MDK-ARM/build.log b/Boot/MDK-ARM/build.log index 1d68b51..4c324cd 100644 --- a/Boot/MDK-ARM/build.log +++ b/Boot/MDK-ARM/build.log @@ -9,4 +9,4 @@ Program Size: Code=1320 RO-data=680 RW-data=0 ZI-data=2104 FromELF: creating hex file... After Build - User command #1: fromelf --bin --output=.\bin\caiic_boot.bin .\Objects\caiic_boot.axf ".\Objects\caiic_boot.axf" - 0 Error(s), 0 Warning(s). -Build Time Elapsed: 00:00:01 +Build Time Elapsed: 00:00:00 diff --git a/docs/开发日志.md b/docs/开发日志.md index 8e0235f..9acd789 100644 --- a/docs/开发日志.md +++ b/docs/开发日志.md @@ -1132,3 +1132,30 @@ UART OTA 首轮实测失败("no OTA_RSP on UART"),排查过程与最终设 全部自动重传恢复,END ack 正常,复位进 APP2 复核通过);BLE OTA 回归 PASS(APP1,30s)。基线:Code=48872 RO-data=4980 RW-data=2076 ZI-data=29116。遗留:串口物理链路建议用户更换/重插,协议层已能自愈。 + +## 45. OTA 工具选错 bank 事故与三重防护(2026-09-04,V1.00.22,工具侧修复) + +用户实测 V1.00.22 包时工具报 `FAIL: OTA_END rejected, status=6 +(bank_mismatch)`,但现场查询发现设备**已在运行 V1.00.22@APP2**、 +bootsetting 记录完整——即前一次运行其实已成功,这次 FAIL 是重复运行时 +的误选 bank 被设备防呆拦截。 + +**根因(PC 工具 bug)**:`enter_ota_mode` 读 `devinfo` 时用 +"cur bank:" 前缀做读完标记,标记命中时 "APP2" 字样可能尚未到达,解析 +落入 `else bank=1` 分支——把运行在 APP2 的设备误判为 APP1,于是把 +APP2 链接的镜像发向 APP1 区。设备端 END 校验(向量表 Reset PC 必须落在 +目标 bank 内)正确拒绝(status=6),不变更 bootsetting、不复位—— +**防呆设计成功阻止了一次错刷**。 + +**修复(ble_ota_update.py,三重防护)**: + +1. bank 探测改为读到提示符的完整输出 + 严格正则 `cur bank: APP([12])`, + 读不到直接报错退出(删除"读不到就默认 APP1"的危险兜底); +2. **传输前预检** `check_blob_bank()`:载荷向量表 Reset PC 必须落在目标 + bank 地址范围内,选错包在发送前即拒绝(BLE/UART 两通道都加); +3. UART 通道新增**复位后自动复核**(与 BLE 通道对齐):END 后等重启、 + 重连 CLI 读 devinfo 比对 bank+版本,输出确定性的 PASS/FAIL,杜绝 + "显示 FAIL 实际成功"的歧义。 + +实测:修复后 UART OTA(APP2→APP1,V1.00.22)全程 PASS 并自动复核通过; +顺带修复了误刷进 APP1 区的内容。固件无改动(仅版本号 V1.00.21→V1.00.22)。 diff --git a/mcm-ddc-ble/MDK-ARM/bin/mcm-ddc-ble-app2.bin b/mcm-ddc-ble/MDK-ARM/bin/mcm-ddc-ble-app2.bin index cbc04e9dc6e37e59dff7f44d932b1a629140b735..a170ea2ee90304713a18d2d98b7d6cad06fbfe53 100644 GIT binary patch delta 48 zcmbQUnR(7;<_#=bJYo!t3}J?P1_pXYMwS Dm~If% delta 48 zcmeycf%(G*<_$MActjZ(8Nv+p3=H&)3^zZ~h-YOq-0Y(F#EVgMvu5QvW+3lJO+_>S Dm> 16, (v >> 8) & 0xFF, v & 0xFF) +BANK_BASE = {1: 0x01008000, 2: 0x01024000} + + +def check_blob_bank(blob, target): + """Pre-flight: the payload's vector-table reset PC must land inside the + target bank (the device re-checks this at OTA_END, but catching a bank + mis-selection here saves a whole transfer).""" + pc = struct.unpack_from("= 0 else "?", + target, fmt_ver(version))) + return 1 def main(): diff --git a/tools/out/caiic_ble_dual.bin b/tools/out/caiic_ble_dual.bin index 992eaea61e7598d7ce7180e8d81ad98dfd8dced7..19ea3c89b2b59c4edd9506e6557eb598a123d785 100644 GIT binary patch delta 153 zcmbQUnP<*so(%#HGKCMLHN_Yh85kUx80Xw%V3^pnrU}H4opj>T=8NoCSNqowCW-=qtW()e5OB4n;ka3aAy?TtoidCP^|gKpY1>XF!JPL kXp3is=y>AAC^lL1XZH33yO@%JIwt@4vu68+eN1Pf0J&T@T>t<8 delta 153 zcmbQUnP<*so(%#HGE@2@3q=_i85kUx80Xw%U?_RJ?iPrjF1b==^F{V6@|zNFc<_Kk z!VL8c4D^f)w+m!3^)YTPT6K|`(Qtb~KGPqj%?=x1xHF1w*8F)6DAxSr&-NdG7S Dm~If% delta 48 zcmeycf%(G*<_$MActjZ(8Nv+p3=H&)3^zZ~h-YOq-0Y(F#EVgMvu5QvW+3lJO+_>S Dm`^8w?DE52H1g0O>h585kxu zt!ZM9P~Nc75D8}0;K2MWMC+H zyY802Ar-BSCO0&AKpMgf^$ZO3j0`tRXvVWL8g8!8d*a0?x;eJ;95axoQ(M!DuB?x7 tyAuoJMUZrb-XEsz0^E!*+!;kD$5v)`^8w?DE52H1g0O>h585kxu zt!ZM9P~Nc75D8}0;K2MWMC+H zyY802Ar-BSCO0&AKpMgf^$ZO3j0`tRXvVWL8g8!8d*a0?x;eJ;95axoQ(M!DuB?x7 tyAuoJMUZrb-XEsz0^E!*+!;kD$5v)9SoS@Y*PW+3m!pNePzZPFYF delta 91 zcmeycf%U@%)(rvS Dm~If% delta 48 zcmeycf%(G*<_$MActjZ(8Nv+p3=H&)3^zZ~h-YOq-0Y(F#EVgMvu5QvW+3lJO+_>S Dm