docs(vd960DBN): devlog 置顶 2026-08-13 复位/卡死全链路诊断闭环

printf 重入 + json_sensor_callback 卡死 + UART2 丢字节 三层根因,
SPI 写无罪/QFN28 无 NRST/5min restart 真相/修复清单/遗留待办
This commit is contained in:
wangfq
2026-08-14 03:02:17 +08:00
parent b493e10454
commit 960d1e83a1
+55
View File
@@ -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 打印)