Files
GateWay/.trae/documents/cat1-remote-upgrade-plan.md
T
YuanHongbin f206b8f7dd feat(ota): Cat1远程升级联调进度(App侧收发链路打通, 待整包实测)
- Update.c/h: NetUpgrade模块(0x7D流式组帧/0x81会话/断点续传/CRC32/TX队列)
- spiflash.c/h: 固件暂存区(扇区4038~4095)+进度区(4037), 日志回绕点前移
- CatOneTask.c: +LIPURC异步分发(循环解析同批多URC); 释放CatOneRev_Sem保REV_DATA快速返回; 升级应答帧发完即回WAIT_SEND
- CatOneTask.c: USART1专用Cat1(上电恒连), 调试日志走RS485 Ch1, CAT1日志常开
- Public.c/h: AsciiToHex长度参数uint8->uint16(修432字符帧截断)
- bsp.c/h, main.c, board.c, DebugCmd.c: APP_UPDATE_SPI_FLAG及配套适配
- 联调修复: sscanf锚点/窗口差值判断/AsciiToHex截断/URC被AT状态机吞帧/信号量缺失
2026-09-24 17:14:02 +08:00

7.1 KiB
Raw Blame History

Cat1 远程升级方案设计(待评审)

总体架构

App 扮演"接收端"角色(与 Boot 在 RS485 升级中的角色相同),服务器扮演升级主机:

服务器(升级主机) --TCP--> 合宙Cat1模组 --USART1--> App(RT-Thread)
    │                                          ├─ 收0x7D帧(0x81/0x82) → 固件分包写外部SPI Flash暂存区
    │←────────── 0x01 ACK(带进度) ──────────────┤
    │                                          └─ 收完→CRC32校验→置UpdateFlag=APP_UPDATE_SPI_FLAG→复位
复位
    └→ Boot: 检测APP_UPDATE_SPI_FLAG
         → SPI Flash逐扇区读 → 写内部B区 → CRC32(B)
         → 搬运B→A → CRC32(A) → 擦SPI Flash暂存区 → 置完成标志 → 复位跳App

升级协议完全复用 RS485 的 0x7D 帧:帧头 0x7D + DevMac(6) + Cmd(1) + PayloadLen(1) + Payload + CRC16(Modbus),命令 0x81 升级请求{PackageNum, AppSize, AppCrc32} / 0x82 数据{PackageIndex, PackageNum, DataLen, Data[200]} / 0x01 ACK / 0x02 请求数据。服务器端协议不变。

关键决策与理由

  1. Boot 不驱动 Cat1:AT 注网 30 秒起、Boot 仅 32KB 分区(当前 Code 16KB)、模组 TCP 连接态在 MCU 复位后不可控。收包/重试/续传等复杂逻辑全部放 App(RTOS 资源丰富),Boot 只做"从外部 Flash 搬运到 B 区"这一简单确定性动作。
  2. 固件暂存外部 SPI Flash:16MB 尾部划 58×4KB=232KB 暂存区(扇区 4038~4095),日志环形写入回绕点同步从 16MB 末尾前移到扇区 4038。
  3. 复用 UpdateFlag 机制:新增标志值 APP_UPDATE_SPI_FLAG(建议 0xA5A55A5A,与现有 START=0x55AA5A5A / UPDATE=0xA5A5AA55 / BOOT_UPGRADE=0x5A5A55A5 不冲突),boot_para_t 结构不变,RS485 本地升级路径完全不受影响。
  4. 依赖 TCP 可靠有序:应用层丢包仅发生在断连/模组重启,因此用"断点续传 + 超时重发请求"而非滑动窗选择重传,状态机与 Boot 版本同构,服务器实现简单。

升级流程(含 Cat1 特化处理)

  1. 服务器 → 0x81{PackageNum, AppSize, AppCrc32}
  2. App 校验 DevMac/合法性(AppSize==0 或 >232KB 拒绝)→ 回 0x01 ACK:
    • 载荷建议扩展为 {Status, ResumedIdx}:0x20=全新开始(App 擦暂存区)、0x21=断点续传(已收 ResumedIdx 包,服务器从该包续发)。注意:原 0x01 载荷 1 字节(0x20),扩展为 3 字节需服务器端同步适配(新版本服务器)
  3. 服务器从 ResumedIdx 起发 0x82{PackageIndex, ...}:
    • 流控(推荐窗口式):服务器连发 W 包(建议 W=816)→ App 校验 PackageIdx 顺序写入暂存区(乱序/重复包丢弃)→ App 主动发 0x02{期望包号} → 服务器继续。停等式(每包一问一答)在 Cat1 上太慢:1160 包 × RTT≈25 分钟+,窗口式约 30~60 秒
    • TCP 保证有序,App 端只需顺序校验 + 期望包号判定
  4. App 收完 → CRC32(暂存区, AppSize):
    • 通过 → 回 0x01{0x30 完成} → 写 boot_para_t{AppSize, Crc32Check, UpdateFlag=APP_UPDATE_SPI_FLAG} → 200ms → 复位
    • 失败 → 回 0x01{0x31 CRC错} → 不复位,清暂存区等待服务器重发(可多次)
  5. Boot 检测 APP_UPDATE_SPI_FLAG → 逐 8KB:读外部 2×4KB 扇区 → 擦写内部 B 区 1×8KB 扇区 → CRC32(B) → CopyAppBtoA()(现有)→ CRC32(A) → 擦外部暂存区(防残留误判,同 RS485 路径 B 区擦除教训) → 置 APP_BOOT_UPGRADE_FLAG → 复位跳 App
  6. App 启动(APP_BOOT_UPGRADE_FLAG)→ 擦外部参数分区 → 上线后服务器可查版本确认升级成功

超时与重试参数(Cat1 特化,均为 App 侧状态机)

参数 Boot RS485 值 Cat1 版建议 理由
等包超时 500ms 3 秒 Cat1 RTT + 模组缓冲
重试次数 3 5 偶发断连需模组重连
断连恢复 — 模组重连(现有逻辑)后服务器重发 0x81,ACK 带进度续传 TCP 断开后应用层无从补偿
整体超时 — 30 分钟无进展 → 放弃升级(清标志,不复位) 防止无限等待

断电自愈矩阵(Cat1 路径)

断电/异常时机 恢复行为
App 收包中断连/断电 暂存区+进度保留 → 重连后 0x81 续传
App 置标志后、复位前 Boot 正常走 SPI Flash→B→A
Boot 搬运中(写B区)断电 UpdateFlag 仍为 SPI_FLAG → B 区 CRC 有效则重搬;无效则清标志回老 App
搬运完、擦暂存区中断电 参数未写 → B CRC 判定重搬(B 仍在);参数已写 → 跳新 App

改动清单

App(GateWay 工程)

文件 改动
spiflash.h/c 新增 FLASH_FW_STASH_BASE(扇区 4038 起)+ StashErase/StashWrite/StashRead;AddLog 回绕点 16MB→扇区 4038;新增 CRC32(与 Boot GetCrc32 同算法 0xEDB88320)
CatOneTask.c(或新文件) Cat1 通道增加 0x7D 帧组帧解析(+LIPURC hex→二进制后按 0x7D 组帧,与现有 0x7A 链路并存,按帧头区分);升级接收状态机(移植 Boot AnalyzeData+BL 状态机,超时/重试参数按上表)
Update.c 新增 UpdateFromStash():写 boot_para_t(APP_UPDATE_SPI_FLAG + AppSize + Crc32Check)→ 复位
bsp.h(App) APP_UPDATE_SPI_FLAG 宏;boot_para_t 不动
main.h(App) 版本号随迭代递增

Boot(HC32F460BootLoader 工程)

文件 改动
bsp.c/h SPI Flash 驱动:与 App 相同总线(需确认外部 Flash 挂载的 SPI 外设与引脚,Boot 复用),W25Q 写使能/扇区擦/页读命令;约 +2~3KB(Boot 当前 16KB,32KB 分区内余量足够)
main.c/h APP_UPDATE_SPI_FLAG 宏 + main() 决策分支(SPI_FLAG → 新状态 BL_STASH_TO_B);BL_STASH_TO_B:逐 8KB 外部读→B 区写→CRC(B) 通过进 BL_COPY_TO_A(现有),失败清标志回老 App;BL_COPY_TO_A 成功分支追加"擦外部暂存区"

服务器端(不在本仓库,需同步开发)

  • 实现 0x81/0x82 升级主机逻辑:窗口流控(W 包一批)、解析 0x02 期望包号、断点续传(ACK 的 ResumedIdx)、完成/失败状态处理

风险与待确认项

  1. 调试口与 Cat1 共用 USART1(PB08 方向切换):升级期间必须保证 UART 方向锁定在 Cat1 侧(CAT1_ON()),升级状态机运行期间禁止调试打印切向(U_DBG_LOG 若触发 DBG_ON() 会破坏 TCP 数据)。实施时需审查 DEBUG=1 下所有升级路径的打印。
  2. 外部 Flash 挂载总线待确认:读 spiflash.c 确认 SPI 外设号/引脚/QSPI 模式,Boot 驱动按此实现。
  3. 日志区历史数据:回绕点前移到扇区 4038(约 15.77MB),已存历史日志超出的部分会被覆盖——现网日志增长慢,实际影响小,但需知晓。
  4. 0x01 ACK 载荷扩展(1→3 字节)需服务器端配合,若服务器不改动则退化为停等式流控(慢但兼容)。
  5. 升级流量:232KB/次,Cat1 资费可忽略。