fix(vd960DBN): init/clear 懒擦修复不断重启 — 34s 全量擦除超 IWDG 4s

现场: 烧录快照固件后 CH32V208 不断重启 + 串口乱码
根因: snap_init 首擦 751 扇区 ~34s (头在擦完才写→复位后仍全新→死循环);
      snap_clear 34s / offlog_clear 2.8s 同类; 均超 IWDG 4s
修复(懒擦): init/clear 只擦写指针起点扇区 ~45ms, 其余由环形写切扇区
      逻辑自动擦; clear 为逻辑清除 (count=0 旧数据不可读)
附带: usart_biz.c 非 0x7F 帧 %s 打印改 hex (Loop 数据当字符串=乱码源)
      snapshot.h 线程模型注释修正 (lup_process_frame 实际在主循环 uart_srv)
测试: test_snapshot 9例(新增 lazy_erase) + offlog/ble_offlog 回归全过
This commit is contained in:
wangfq
2026-08-12 18:31:56 +08:00
parent 92887a3d92
commit 3d4814bffe
8 changed files with 105 additions and 32 deletions
@@ -22,13 +22,13 @@
* - 顺序写, 写满擦下一扇区 (环形覆盖), 天然磨损均衡
* - 上电从头部记录的写位置向后扫描, 找第一条无效记录 = 真实写位置 (掉电恢复)
*
* 线程模型 (关键):
* - snap_enqueue(): 中断上下文 (USART2 ISR → lup_process_frame → iot_sensor_ingest),
* 只做打包 + RAM 环形暂存 (memcpy, 无阻塞, 无 SPI 操作); 满时丢新不覆盖
* - snap_flush(): 主循环上下文 (iot_mqtt_publish_sensor), RAM 暂存 SPI 落盘
* (扇区切换擦除 ~45ms 阻塞仅发生在主循环, 与 offlog 同底线)
* - 单生产者 (中断) 单消费者 (主循环) 无锁环形: 生产者只写 tail,
* 消费者只读 head, 留一格判满
* 线程模型 (关键, 2026-08-12 修正):
* - USART2 ISR 只逐字节喂 lup_feed_byte(), 完整帧由主循环 uart_srv() 调
* lup_process_frame → iot_sensor_ingest → snap_enqueue() — 全程主循环
* - snap_enqueue(): 打包 + RAM 环形暂存 (无 SPI, 无阻塞); 满时丢新不覆盖
* - snap_flush(): iot_mqtt_publish_sensor 每轮调用, RAM 暂存 → SPI 落盘
* (扇区切换擦除 ~45ms 阻塞发生在主循环, 与 offlog 同底线)
* - 单生产者单消费者无锁环形: 生产者只写 tail/count, 消费者只读 head
*
* 记录格式 SnapRec (64B 定长, 无 padding):
* magic(1) len(1) flags(1) rsvd(1) | seq(4) ts_ms(4) boot_seq(2) rsvd2(2) | coils(48)
@@ -124,7 +124,7 @@ typedef struct {
void snap_init(void); /* 上电初始化 (扫描恢复) */
uint8_t snap_enabled(void); /* Flash 初始化成功 */
void snap_enqueue(const LUP_SensorReport *sr); /* 中断安全: 打包→RAM 暂存 (满丢新) */
void snap_enqueue(const LUP_SensorReport *sr); /* 主循环入队: 打包→RAM 暂存 (满丢新) */
void snap_flush(void); /* 主循环: RAM 暂存→SPI 落盘 */
uint32_t snap_count(void); /* 有效记录数 */