docs(vd960DBN): devlog 置顶 2026-08-13 复位/卡死全链路诊断闭环
printf 重入 + json_sensor_callback 卡死 + UART2 丢字节 三层根因, SPI 写无罪/QFN28 无 NRST/5min restart 真相/修复清单/遗留待办
This commit is contained in:
@@ -6,6 +6,61 @@
|
||||
|
||||
---
|
||||
|
||||
## 2026-08-13 — 复位/卡死全链路诊断闭环:printf 重入 + 回调卡死 + UART2 丢字节
|
||||
|
||||
### 现场症状(多轮)
|
||||
|
||||
| 阶段 | 现象 | 关键数据 |
|
||||
|------|------|---------|
|
||||
| ① 快照区落地后 | SPI 写触发复位 + 串口乱码 | RST=0x00000000 |
|
||||
| ② factory 写死循环 | 参数区 magic 不匹配 → 写→复位循环 | RST=0x08000000 → 0x00000000 |
|
||||
| ③ 加 HardFault 诊断后 | LUP 帧后复位 | RST=0x10000000 (SFT) |
|
||||
| ④ PRINT 临界区修复后 | 乱码消失,但 LUP 帧后**卡死** | 无复位(IWDG 未兜底) |
|
||||
| ⑤ 注释 enter PRINT 后 | 不卡死,偶发 checksum fail 刷屏 | 坏帧 `7F 03 39 EF...` 多帧拼接 |
|
||||
| ⑥ 关高频打印+清 flag 后 | **系统稳定**(6+ 分钟无复位) | SIM 心跳持续 |
|
||||
|
||||
### 根因链(三层,全部是软件问题)
|
||||
|
||||
```
|
||||
1. printf 重入: BLE 协议栈回调(peripheral.c, BB 中断上下文)与主循环都有 PRINT
|
||||
→ newlib printf 非中断安全交叉调用 → 输出乱码 + 堆/状态破坏 → HardFault
|
||||
2. json_sensor_callback enter PRINT: printf 处理 %d %d %d 死循环
|
||||
(LUP Rx %s 打印成功, enter %d 打印卡死) → 主循环永久卡死
|
||||
3. UART2 丢字节: LUP Rx 打印 190B @256000 = 7.4ms 关中断 (PRINT 临界区)
|
||||
→ UART2(19200) RX 溢出丢字节 → 帧解析错位 → 粘帧 → checksum fail
|
||||
+ g_pkg_uart_2.flag 清理缺失 → 坏帧反复处理 → fail 刷屏
|
||||
```
|
||||
|
||||
### 重要认知修正
|
||||
|
||||
- **SPI 写完全无罪**:模拟实验跑 17000+ 条写入(含 45ms 擦除 + 100ms 头写),0 硬件复位。推翻此前"SPI 写触发 VDD 跌落复位"判断
|
||||
- **CH32V208GBU6 QFN28 无 NRST 引脚**(数据手册第 1400 行 QFN28 列 = "-")→ "PA7/NRST 共线"假设作废
|
||||
- **5 分钟"神秘复位"真相**:`tcp_json` 的 `TCP_JSON_IDLE_TIMEOUT_MS=300000`(5min idle → restart)。主循环卡死时表现为 SFT 复位,恢复后只重启 TCP 服务
|
||||
- **IWDG 卡死未兜底**:iot_enable=0 时 `iot_mqtt_poll` 不跑 → 无人喂狗且未初始化 → 已改为 main 无条件 init + 主循环无条件 kick(待确认 LSI 频率偏差导致的超时漂移)
|
||||
|
||||
### 修复清单
|
||||
|
||||
| 文件 | 修复 |
|
||||
|------|------|
|
||||
| `SRC/Debug/debug.h` | PRINT 宏加临界区:保存/恢复 MSTATUS(防 printf 重入,中断里调用也能正确恢复) |
|
||||
| `loop_uart_proto.c` | LUP Rx 逐字节打印→缓冲一次性输出→`#if 0` 关闭(7.4ms 关中断丢字节根因) |
|
||||
| `tcp_json_srv.c` | json_sensor_callback enter PRINT `#if 0`(printf %d 卡死规避);not authed 打印 `#if 0`;修 `\\n` 双反斜杠 |
|
||||
| `usart_biz.c` | uart_srv 所有分支消费后统一 `InitPkgUart`(0xC0 + 非0xC0无BLE 原来不清 flag);重复逐字节打印 `#if 0` |
|
||||
| `ch32v20x_it.c` | HardFault_Handler 纯 RAM 写 mcause/mepc/mtval(官方 `__get_MCAUSE/MEPC/MTVAL`)+ fault_diag 无条件打印 marker |
|
||||
| `Link.ld` + `fault_diag.h` | .noinit 段(复位不清零)跨复位留痕:HardFault 现场 + 执行轨迹 marker |
|
||||
| `peripheral_main.c` + `iot_mqtt_srv.h` | IWDG 无条件初始化 + 主循环无条件喂狗 |
|
||||
| `cfig_flash.c` | factory 写止血:magic 不匹配时内存默认值(原 SPI 写→复位死循环) |
|
||||
|
||||
### 遗留待办
|
||||
|
||||
- [ ] UART2 偶发丢帧(1-3 分钟一次 checksum fail):波特率 19200→115200(需 Loop MCU 配合)或 RX 改 DMA/双缓冲
|
||||
- [ ] json_sensor_callback enter PRINT 的 printf %d 卡死根因(newlib lock / UART1 TC 轮询)——已注释规避,恢复前需查明
|
||||
- [ ] IWDG 卡死时未在 4s 复位:LSI 频率偏差 or 配置问题
|
||||
- [ ] `g_lup_sensor_cb` 单回调竞争:iot_evt_sensor_cb 与 json_sensor_callback 后注册覆盖先注册,事件沿检测可能被跳过(需多回调或合并)
|
||||
- [ ] 恢复快照区功能:`snap_init` 取消 `#if 0`、移除 `sim_snap_spi` 模拟实验,验证 BLE 0x28/0x29/0x2A 查询
|
||||
|
||||
---
|
||||
|
||||
## 2026-08-12 — 复位原因位定义错位修正 + POR 复位定位(电源方向)
|
||||
|
||||
### 诊断进展(现场 RST_REASON 打印)
|
||||
|
||||
Reference in New Issue
Block a user