feat(vd960DBN): Loop MCU 远程 OTA 固件实现 (MQTT V1.08, ROADMAP P1.4 ①)
先存后刷: MQTT 分片下载 → W25Qxx OTA 暂存区 (0x010000 512KB) → 全镜像 CRC32 复核 → 本地 0x9F ISP 透传刷写 Loop MCU (AT32F421) - 新增 ota_srv.c/h: CRC32(ISO-HDLC 逐位零表)/OtaMeta 双备份(节流 4KB flush)/ 会话状态机(begin/data/end/abort/flash)/本地刷写状态机(非阻塞 tick: A5→A6→A7 停等 ACK 1s×3)/安全窗口(有车拒绝 force 跳过)/失败 event_report ota_error - iot_mqtt_srv.c: 6 个 ota_* 命令分发 + 会话静默(event_report 积压/offlog·快照 落盘暂停, 结束补发) + IOT_EVT_OTA_ERROR + iot_any_car - usart_biz.c: uart_srv OTA 分支 ACK 分发 (本地刷写→ota_flash_feed_ack, BLE 透传不变) - peripheral_main.c: ota_init + ota_poll 挂主循环 - offlog: OTA_START 0x60/OTA_RESULT 0x61 审计事件 - tests/test_ota_srv.c: gcc 隔离单测 9 组全过 (mock NOR/UART2/时钟, 嵌入真实实现) 抓到 2 个真 bug: ①A7 序号未递减(bootloader 等不到末包) ②重发时 retry 清零(超时永不失败) - 语法检查: ota_srv/iot_mqtt_srv/usart_biz/offlog 0 新增错误 (基线 interrupt 假阳性除外) - devlog 置顶条目 + 待板上验证清单
This commit is contained in:
@@ -4,6 +4,49 @@
|
||||
>
|
||||
> 项目定位: DLD960 通信板 — BLE 配网、TCP JSON 协议服务、Loop MCU 串口桥接
|
||||
|
||||
## 2026-08-20 — Loop MCU 远程 OTA 固件实现(MQTT V1.08,ROADMAP P1.4 ①)
|
||||
|
||||
### 背景
|
||||
|
||||
协议设计稿 V1.01 拍板 + 并入 MQTT 协议 V1.08 + DBNMQTTool OTA 页签/协议单测先行。本次固件实现**先存后刷**:MQTT 分片下载 → W25Qxx OTA 暂存区(0x010000 起 512KB)→ 全镜像 CRC32 复核 → 本地 0x9F ISP 透传刷写 Loop MCU(AT32F421)。
|
||||
|
||||
### 变更
|
||||
|
||||
| 文件 | 变更 |
|
||||
|------|------|
|
||||
| `ota_srv.c/h`(新增) | CRC32(ISO-HDLC 逐位,零查表 RAM)、OtaMeta 元数据(双备份 0x010000/0x010200,节流 4KB flush)、会话状态机(begin/data/end/abort/flash)、本地刷写状态机(非阻塞 tick 驱动:A5→pre_ok→A6→addr_ok→A7×N 停等 ACK,1s 超时 ×3)、安全窗口(有车拒绝,force 跳过)、失败 event_report ota_error |
|
||||
| `iot_mqtt_srv.c` | 命令分发加 6 个 ota_* 分支;会话静默(downloading/flashing 暂停 event_report 发送 + offlog/快照落盘,队列积压结束后补发);IOT_EVT_OTA_ERROR 事件类型 + `iot_evt_report_ota_error` + `iot_any_car` |
|
||||
| `usart_biz.c` | uart_srv OTA 分支 ACK 分发:`g_ota_flash_active` 时交给 `ota_flash_feed_ack`(本地刷写),否则透传 BLE(现状) |
|
||||
| `peripheral_main.c` | `ota_init()` 初始化 + `ota_poll()` 挂主循环(uart_srv 后,先消费 ACK 再推进) |
|
||||
| `offlog.c/h` | 事件类型 OTA_START 0x60 / OTA_RESULT 0x61 + 包装函数(升级开始/结果审计留痕) |
|
||||
|
||||
### 关键参数
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| 下载单片 | 256B + 单片 CRC32(hex 512 字符 < RECV_BUF 1024) |
|
||||
| 镜像上限 | 96KB(Slot 100KB - 4KB 边界余量) |
|
||||
| 刷写块 | 248B(0x9F LEN 为 uint8 → DATA ≤254B;bootloader 2KB 扇区累积写) |
|
||||
| 分区 | 元数据 4KB + Slot A/B 各 100KB(0x011000/0x02A000)+ 预留 308KB |
|
||||
| 断点续传 | 元数据 received 节流 4KB flush,掉电丢 ≤4KB(平台重发幂等,协议已定义) |
|
||||
| 刷写窗口 | 64KB ≈ 265 块 × ~20ms ≈ 6~8s;非阻塞调度保 MQTT 保活/IWDG |
|
||||
|
||||
### 单测(gcc 隔离,`tests/test_ota_srv.c`,mock NOR/UART2/时钟)
|
||||
|
||||
9 断言组全过:CRC32 标准向量 0xCBF43926 / hex 解码 / 元数据双备份恢复 / 会话流 20 片→ready / 断点续传(16 片 flush 后精确续传)/ 幂等·乱序·单片 CRC / 刷写全流程(21 块 A7 逐块 ACK)/ 有车拒绝 + force 跳过 / pre_ok 超时重试失败告警。
|
||||
|
||||
**抓到 2 个真 bug(单测价值实证)**:
|
||||
1. **A7 块序号未递减**:`_fs_sub` 每块 ACK 后不减 → bootloader 永远等不到末包(sub==1)→ 刷写卡死。修复:ACK 成功路径 `_fs_sub--`。
|
||||
2. **重发时 retry 清零**:START/ADDR 分支 `_fs_retry=0` 每次重发清零 → 超时重试永不失败。修复:重发保持计数(首发由 ota_cmd_flash 置 0,ACK 成功由 feed_ack 清 0)。
|
||||
|
||||
### 待板上验证
|
||||
|
||||
- UART2 TX 阻塞轮询(248B ≈ 13ms)与主循环时序、擦除 45ms×N 分散阻塞对 MQTT 保活影响
|
||||
- Loop 实际 bin 大小(验证 96KB 余量)、bootloader 真实 ACK 时序
|
||||
- 会话静默后 event_report 补发行为(队列积压恢复)
|
||||
|
||||
---
|
||||
|
||||
## 2026-08-19 — 固件版本 V1.02.04(SPI 存储适配两项修复)
|
||||
|
||||
### 内容
|
||||
|
||||
Reference in New Issue
Block a user