From f274d70fbddebba0093eaf3f8bfd6bd6a54b8595 Mon Sep 17 00:00:00 2001 From: wangfq Date: Mon, 17 Aug 2026 15:34:09 +0800 Subject: [PATCH] =?UTF-8?q?docs(vd960DBN):=20devlog=20=E9=87=8D=E5=86=99?= =?UTF-8?q?=202026-08-17=20=E6=9D=A1=E7=9B=AE=20=E2=80=94=20=E6=A0=B9?= =?UTF-8?q?=E5=9B=A0=E9=97=AD=E7=8E=AF=20+=20=E6=9D=BF=E7=BA=A7=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E9=80=9A=E8=BF=87=20(2026-08-17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 条目重写为完整闭环: 诊断(Hex日志+实验A/D) → 根因(.bss挤占RAM→栈1.9KB→ printf栈溢出→PC跑飞) → 修复链(4 commit) → .map分析(BLE栈16KB固定) → 二轮瘦身 → 板级验证(用户实测无异常重启) - 验证项标记: 一轮瘦身版无复位(MQTT/BLE正常), 二轮瘦身版测试无异常重启 - 遗留: TCP JSON 回归 + 快照区 3s 初始化回归 --- vd960DBN/docs/devlog.md | 108 +++++++++++++--------------------------- 1 file changed, 35 insertions(+), 73 deletions(-) diff --git a/vd960DBN/docs/devlog.md b/vd960DBN/docs/devlog.md index 1648544..1729cda 100644 --- a/vd960DBN/docs/devlog.md +++ b/vd960DBN/docs/devlog.md @@ -4,103 +4,65 @@ > > 项目定位: DLD960 通信板 — BLE 配网、TCP JSON 协议服务、Loop MCU 串口桥接 -## 2026-08-17 — 快照区延后初始化(开机 3s 后)— 启动早期 SPI 重负载疑似触发跑飞 +## 2026-08-17 — 频繁"复位"根因闭环:.bss 挤占 RAM → 栈溢出 → PC 跑飞 ### 背景 08-14 恢复快照区功能(8873b33)后,现场频繁"复位"(100~180ms 一轮完整启动日志)。 -Hex 日志诊断: + +### 诊断过程(Hex 日志 + 二分实验) | 观察 | 推断 | |------|------| -| RST_REASON 首次 0x08000000(POR),之后恒 0x00000002(无任何复位标志位) | 非硬件复位(POR/IWDG/SFT/PIN 都会置位) | -| 无 FAULT_DIAG 输出 | 非 HardFault(fault_diag 仅在 HardFault 后打印) | -| 每轮都到 `INIT: snap ok`,之后无任何 ASCII 直接 71B 乱码+重启 | 跑飞点在 snap_init 之后(offlog_boot/load_cfg/output_cfg 区间) | -| 实验A(跳过 offlog_boot,commit 0c717e4):仍崩 | offlog_boot 非触发点 | -| BOOT_CNT 恒=1(.noinit 计数器每次从 0 开始) | RAM 全丢级重启(掉电-恢复但未触发 POR) | +| RST_REASON 首次 0x08000000(POR),之后恒 0x00000002(无复位标志位) | 非硬件复位(POR/IWDG/SFT/PIN 都会置位),是 PC 跑飞跳回 0 | +| 无 FAULT_DIAG 输出 | 非 HardFault | +| snap ok 后 71B 乱码 + 无 ASCII 打印 | 跑飞点在 offlog_boot/load_cfg/output_cfg 区间 | +| 实验A(跳过 offlog_boot, 0c717e4):仍崩 | offlog_boot 非触发点 | +| 实验D(跳过 load_cfg/output_cfg, 452ff68):**完全正常启动** | **触发点 = load_cfg/output_cfg** | +| BOOT_CNT@0x2000f84c END:0x2000f834 | **.bss≈46KB → 栈仅 ~1.9KB**(危险) | -### 结论 -启动早期 SPI 重负载(offlog_init 擦+整扇区写回 ~80ms + snap_init 擦+整扇区写回 ~80ms) -让电源/系统进入临界状态,随后的 SPI 操作(load_cfg 读参数区)成为压垮点。 -08-13"稳定 6 分钟"实为实验状态(snap_init/offlog_boot 均 #if 0),非完整固件。 +### 根因 +**.bss 挤占 RAM → 栈仅 1.9KB → load_cfg/output_cfg 的 printf 栈峰值触顶** +→ 溢出覆盖 .noinit(g_boot_count 恒 1、g_fault_diag 消失)+ 返回地址 → PC 跑飞 → 循环。 +08-13"稳定 6 分钟"实为实验状态(snap_init/offlog_boot 均 #if 0),非完整固件; +快照区延后无效,因为问题不是快照 SPI,是栈空间被 .bss 挤占。 -### 方案 -快照区延后到开机 3s 后初始化:避开启动早期 SPI 重负载窗口;3s 内传感帧 -由 snap_enqueue/snap_flush 的 !_ready 门控自然丢弃(视为无效快照数据)。 +### 修复链(4 个 commit) +| commit | 内容 | +|--------|------| +| 452ff68 | 实验D:BOOT_CNT 加 END/SP 打印 + 跳过 load_cfg/output_cfg(定位触发点) | +| 26f2326 | 止血:load_cfg 去调试打印、output_cfg 暂关(设备稳定启动) | +| 421334e | RAM 瘦身一轮:ETH 1520→768、payload/MQTT buf 1400/1024→800(栈 1.9→4.7KB) | +| 89ba602 | 闭环:恢复全部调试打印 + load_cfg 字符串 0 终止保险 | -| 文件 | 变更 | -|------|------| -| `snapshot.c` | 新增 `snap_delayed_init()`:主循环每轮调用,mstick()>=3000 且未初始化时执行 snap_init(非阻塞) | -| `snapshot.h` | 声明 `snap_delayed_init()` | -| `peripheral_main.c` | main() 移除 snap_init 调用;主循环喂狗后加 snap_delayed_init();撤销实验A(恢复 offlog_boot)/实验B(恢复 load_cfg/output_cfg);保留 BOOT_CNT 诊断打印 | - -### 实验 D 结论(2026-08-17 晚,commit 452ff68/后续) -实验 D(跳过 load_cfg/output_cfg)**设备完全正常启动**(WCHNET/TCP/BLE 全通)→ -**触发点确认 = load_cfg_from_flash / output_cfg_from_flash**(栈溢出)。 - -BOOT_CNT 打印扩展证实 RAM 布局: -``` -BOOT_CNT:1 @0x2000f84c END:0x2000f834 SP:0x2000ffd0 -``` -- END(0x2000f834) = 堆起点 → **.bss ≈ 46KB**(BLE 栈 + ETH DMA 7.6KB + SPI_FLASH_BUF 4KB + 网络缓冲) -- g_boot_count@0x2000f84c = .noinit 被推到 RAM 顶 → **栈仅 ~1.9KB**(危险) -- 栈溢出 → 覆盖 .noinit(g_boot_count 恒1/g_fault_diag 消失) + 返回地址 → PC 跑飞 → 循环 -- **快照延后无效的原因**:问题不是快照 SPI,是栈空间被 .bss 挤占 - -### 修复(栈溢出止血) -| 文件 | 变更 | -|------|------| -| `cfig_flash.c` | load_cfg 内 3 处调试 PRINT 注释(magic mismatch ×2 + Sub_Code ×1)——printf 栈峰值是压垮 1.9KB 栈的最后一根稻草 | -| `peripheral_main.c` | load_cfg 恢复(保留配置加载);output_cfg 调用 #if 0(纯调试打印,栈峰值高) | - -### RAM 瘦身(2026-08-17 晚,commit 后述)— .bss ≈46KB → 目标栈 4KB+ -实验 D 确认栈溢出根因后,.bss 瘦身四刀(省 ~4.8KB,栈 1.9KB → ~6.7KB): - -| 文件 | 项目 | 现状 | 改为 | 省 .bss | -|------|------|------|------|---------| -| net_config.h | ETH_MAX_PACKET_SIZE | 1520 (RX×4+TX=7.6KB) | **768** (MSS=700 最大帧 758B) | **3.76KB** | -| iot_mqtt_srv.c | payload[] | 1400 | **800** (loop_data 最大~604B) | 0.6KB | -| iot_mqtt_srv.h | IOT_MQTT_SEND_BUF_LEN | 1024 | **800** (影响 _iot_send_buf/resp/buf) | 0.22KB | -| net_srv.c | MAX_MQTTBUF_LEN | 1024 | **800** (512 仍不够勿回改) | 0.22KB | - -⚠ ETH_MAX_PACKET_SIZE 768 是贴着 MSS=700 的最小值:TCP 帧 758B ✓; -若现场出现 >728B 数据的大 UDP 包会截断,保守可改 1024(省 2.48KB)。 - -### .map 分析 + 二轮瘦身(2026-08-17 晚,commit 后述) -用户提供编译后 .map 解析结论: +### .map 分析(用户提供编译产物) - **BLE 栈(libwchble.a)固定占用 RAM 低 16KB(0x20000000~0x20004000,链接脚本外)**——WCH CH32V20x 工程约定,不可裁剪 -- 用户 48KB:.data 1.6K + .bss 41.7K + .noinit 28B → 栈 4.7KB(实测稳定) +- 用户 48KB:.data 1.6K + .bss 41.7K + .noinit 28B → 栈 4.7KB - .bss 大块:RECE_BUF_LEN 系列 ~10KB、Mem_Heap 7.2KB、MACRx/TxBuf 3.8KB、eth DMA 5.9KB、SPI_FLASH_BUF 4KB、ARP 1.2KB、iot buf 2KB -二轮瘦身(省 ~3.4KB,栈 4.7KB → ~6.3KB + 中断栈峰值降 1.8KB): - +### 二轮瘦身(cb63c58)— 栈 4.7KB → ~6.3KB + 中断栈峰值 -1.8KB | 文件 | 项目 | 改动 | 收益 | |------|------|------|------| | net_config.h | RECE_BUF_LEN | MSS×2(1400)→**1024**(MSS=700 帧+头≈740B 够) | 5 数组省 ~2.6KB | -| net_config.h | WCHNET_NUM_ARP_TABLE | 50→**16**(停车设备连接 IP 少) | ~0.8KB | -| tcp_json_srv.c | tmp_buf[RECE_BUF_LEN] | 局部→**static**(中断上下文 1KB 栈数组) | 栈峰值 -1KB | -| tcp_json_srv.c | frame[TCP_JSON_MAX_FRAME] | 局部→**static**(中断上下文 800B) | 栈峰值 -0.8KB | +| net_config.h | WCHNET_NUM_ARP_TABLE | 50→**16** | ~0.8KB | +| tcp_json_srv.c | tmp_buf[RECE_BUF_LEN]/frame[800] | 局部→**static**(中断上下文栈数组) | 栈峰值 -1.8KB | -### 遗留(根治) -- [x] BLE 栈占用确认:16KB 固定(RAM 低区),不可裁剪 -- [ ] (可选)g_report_cfg 1400B 结构体审查(ReportConfig 含大数组?) -- [ ] (可选)Mem_Heap_Memory 7.2KB 是 WCHNET 库内部堆,需查库配置是否可减 -- [ ] 快照区 3s 延后初始化保留(已确认非根因,作为启动早期 SPI 减压无害) - -### 验证 -- [x] 实验D:跳过 load_cfg/output_cfg → 正常启动(WCHNET/TCP/BLE 全通) -- [ ] 板级:本修复版(load_cfg 恢复+去打印)→ 正常启动 + 配置加载生效 -- [ ] 板级:不再循环重启 +### 板级验证(用户实测) +- ✅ 一轮瘦身+打印恢复版:**无复位**,MQTT 连 159.75.137.141:1883、BLE 广播正常、dev_serial=DC045A49718F 配置加载生效 +- ✅ 二轮瘦身版(RECE_BUF_LEN 1024 + ARP 16 + static):**测试无异常重启** +- [ ] 待回归:TCP JSON 命令交互(RECE_BUF_LEN 减小后接收缓冲 1024 ≥ MSS 帧 740B,理论无影响) +- [ ] 待回归:快照区 3s 后初始化(`INIT: snap ok`)、断网快照落盘、BLE 0x28/0x29/0x2A ### 遗留 -- BOOT_CNT 打印保留(确认 .noinit 段生效 + 区分复位 vs 跑飞重启) -- 快照区延后 3s 期间(0~3s)传感数据不落盘(按需求接受) -- 电源裕量问题若确认:W25Q32 VCC 加 100nF+10uF 电容、SPI 走线远离电源 +- BOOT_CNT 打印保留(区分复位 vs 跑飞重启,诊断价值) +- 快照区延后 3s 保留(非根因,但作为启动早期 SPI 减压无害) +- (可选)g_report_cfg 1400B 结构体审查、WCHNET Mem_Heap 7.2KB 库配置——收益有限暂不动 --- ## 2026-08-14 — 快照区功能恢复启用 + UART2 波特率澄清 + ### 背景 printf 重入复位问题已确诊修复(2026-08-13,SPI 写无罪)。实验遗留的隔离代码收尾:快照区恢复启用、模拟写密度的 `sim_snap_spi` 实验桩移除。