d4867ddbe2
影响面:一个头文件宏(App/algo/prot_set.h)+ 七份文档口径;固件行为逐位 等价,无功能变化。门禁全绿后提交,未推送。 验证链 - @build:0 错 0 警;Code 213,520 → 213,188(−332 B),RO/RW/ZI 不变。 - 真机 @test PASS:戳 fw build: Oct 22 2026 10:36:15 suite=NONE;无 [ERR]/ERROR/FAIL/Fault;708 ms 到 net init: OK;protect task start、 i104: listening on 2404、[STACK] 三面水位齐。 - 主机单测:prot_set 90/90、prot_elm 47/47、iec104 97/97。 - 等价性穷举:宏内 42 个字面量;int32 全域 ÷1024 往返 4,494,305 例零 差异;×1024 方向 20 万随机 float 零差异(×/÷1024 是 2^10 指数平移, 不产生尾数舍入)→ 定值默认值/上下限、校验和、104 上送值全部不变。 F-6 双精度软浮点(已落地) - 两个 Q10 宏去掉显式 (double)、1024.0 → 1024.0f:保护判据每 20 ms 每 元件 3 次定值读取改走 F407 单精度 FPU,不再软件模拟。 - .map 里 dflti/d2f/f2d/dfixi/fepilogue 共 300 B 消失;自研侧对双精度 helper 的引用归零。 - 更正报告归因:全库 0 处 %f(扫 App/Src/Inc/Drivers 共 173 个 .c/.h), 剩下 dadd/dmul/ddiv/depilogue/dfixul = 1,018 B 由 MicroLIB printfa.o 的 _printf_core → _fp_digits 无条件引用,只要还用 snprintf 就删不掉; 报告"把 %f 改整数刻度"没有可执行对象。 F-4 LVGL 死代码(判定不做) - 报告列的五项字节数逐字节仍准(合计 10,060 B),但没有一项有开关: 根因是 lv_draw_sw.c 的 execute_drawing() 无条件 switch 引用全部 task 类型,链接器 --remove 无从下手。 - 唯一总开关 LV_DRAW_SW_COMPLEX 被 ui_deco.c 的"浅 V"3 px 粗斜腿依赖 (斜段与其所需 mask 核心都在该开关内);2026-09-03 已实测失败并把两端 =1 固化 → UI_设计架构.md §1.4 第 7 条。 - 报告原"mask/grad 是文字与矩形绘制必经路径"证伪:字形走 blend 层 mask_buf,不经 lv_draw_sw_mask_*。 - 剩余路线需给 Lib/lvgl 打本地补丁(上限 ≈16 KB),而 Flash 仅占 22.1%、 无 OTA/双镜像预算 → 收益不抵代价;图片链同理不打补丁。 F-5 uvprojx 空 TU(降级为观察项) - 实测 326 个 .c / LVGL 201 个 / .map 零产出 127 个;但增量构建 4~5 s、 空 TU 只在全量重建或改 lv_conf.h 时才重编,且远程 CI 刻意不跑 @build。 - 报告原"编译时长 −40%"无基线记录,不复述;真要做用 Keil 原生 <IncludeInBuild>0</IncludeInBuild>,且排在任何 lv_conf.h 改动之后。 文档与台账 - 审查报告 §0.1/§0.4/§1/注册表/§5.1/§5.4/§6.4/W4 行按实测更正,补 2026-10-22 变更记录行与 F-4/F-6 记录去处行;登记簿 N-28 改写为"三项 已判定、仅剩 F-5 观察项"。 - 更正 FTL 写回缓存旧口径(sys_log_mcu.c 注释、运行与自检记录设计说明 §4.4、实机测试实施指南 §9.1):f_close 经 sync_fs → CTRL_SYNC → ftl_flush_cache 已落盘,"写另一个文件逼出脏页"不是必要条件;2026-10-02 那次"复位后写入整段丢失"根因是 dhara resume 锚错 checkpoint。 - 部署环境要求 §3.3 资源预算由 2026-09-11 快照刷新为 2026-10-22 实测, 并补 CCM 红线行(旧"SRAM 95.4%/极度紧张"的说法早已失效)。 - ram_baseline.py --update/--write、check_mem_numbers.py --write 已回填: mem-budget(SRAM1 57.4% / CCM 87.9%,阈值 92%)与 mem-numbers 转绿。
App/log/ — 日志子系统
两类日志:持久化运行日志(
sys_log,落 NAND)与控制台日志(console_log,走串口)。 两者都遵循单写者模型,避免多任务交错输出。
文件一览
| 文件 | 作用 |
|---|---|
sys_log.h |
日志接口(平台无关):定长 64B 记录写入 /log/run.log·selftest.log |
sys_log_mcu.c |
sys_log 的 MCU 端后端实现(NAND + FatFs) |
console_log.c/h |
控制台单写者日志:多任务日志经队列汇入唯一写者,避免串口输出交错 |
soe_rec.c/h |
SOE 记录纯编解码(B9):64B 定长记录(CP56Time2a 时标 + 类型 + 元件号 + 单调序号 + 值 + sum8 撕裂校验),零 I/O 零 OS 依赖,主机单测覆盖 |
soe_store.c/h |
SOE 落盘胶水(B9):/log/soe.log,protectTask 投递(零文件系统)→ defaultTask 排空落盘 |
关键机制
syslog(运行/自检记录)
- 唯一写者 = defaultTask;其它任务只投递,不直接写盘
- 单记录定长 64 B,循环写;待机页可显示记录
- 内核启动前的日志走无锁静态缓冲
s_preboot[8]暂存(因为内核启动前不能建队列), 内核启动后由syslog_drain惰性创建真队列并排空 - ⚠️ 写盘必须校验
f_write返回的字节数(该 FatFs 移植在簇分配失败时返回FR_OK+ 短写, 不报错误码);追加写必须FA_WRITE|FA_OPEN_APPEND(FA_OPEN_APPEND单独用不含写位)
console_log(控制台单写者)
- 多任务的生产者 → 单写者消费者,消除任务间日志行交错
- 设计详见
docs/子系统设计/控制台单写者日志设计说明.md
soe(SOE 事件顺序记录,B9)
- 记录 = 64 B 定长二进制(
soe_rec.h布局),落/log/soe.log; 与 run.log 分文件——run.log 是文本记录、有 UI/主机读取方,二进制 SOE 混入会破坏读取器;分文件保持"定长 64B + 条数=fsize/64 + 满删重建 + FTP 下载 + 主机解码"同一套先例 - 生产者 = protectTask(元件动作/返回、软压板投退、采样闭锁/恢复六类
边沿):
soe_store_post()纯 RAM(取时标 + 组记录 + 队列/待发环), 零 NAND I/O;⚠️ post 内禁DBG_*——会把 protectTask 静态最坏链 垫高一帧(实证 872→1192 B FAIL),丢弃留痕由 drain(defaultTask)差值上报 - 唯一写者 = defaultTask:挂
syslog_drain()尾部(继承其卷就绪门), 50 ms 节拍 → SOE 落盘延迟 ≤50 ms;写盘纪律全套照 syslog(卷锁 try /FA_WRITE|FA_OPEN_APPEND/ 校验字节数 / 满删重建 / 失败留痕去重), 绝不把名字/参数类错误码归入卷损坏触发集 - 时标口径:sys_clock 秒域时基 → CP56 ms 域 = 秒×1000(亚秒恒 0, 不造假);墙钟未建 → IV 位如实置位;seq 仅上电生命周期内单调 (容量重建不重置,仅复位重置——主机解码按 boot 段分段断言)
- 主机侧:
test/host/soe/decode_soe.py解码 + 断言(校验和/seq 单调/ CP56↔epoch UTC 交叉);⚠️ 交叉校验用calendar.timegm,不是本地时区的dt.timestamp()(+08 机差 28800 s,首跑实证坑)
相关文档
docs/子系统设计/控制台单写者日志设计说明.mddocs/子系统设计/运行与自检记录设计说明.md- FatFs 陷阱:
AGENTS.md「平台约束」