138aebc6d6ce2ef2c5f4b0677d9285c0fa11bcc8
128 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4332142680 |
feat(ui-pages): 遥信量 33 行固定名表页接实时快照(新增 yx_dp)
批 4 主体(票 task-15;规格 docs/UI设计/页面扩充详细方案.md §3.1.3 方案 A)。V0.1 只有 6 点有 硬件来源,其余 27 点在屏上就是 "--"——这是真实状态,不是页面没做完。 页面与数据 - 33 行固定名表(Flash const)+ 动态分页(8 行/页 = 5 页)。两处命名不照抄文档简写:idx0~3 屏上写「位置1~4」而非「YK1~4 位置」(遥信页出现 YK 前缀会被读成遥控对象,对应关系留在注释); idx30 写「保护闭锁」(写侧位号注释的语义即此,用编号反而丢信息)。idx4~13、idx31~32 点表未 定义功能名,如实写点号占位(YX5…、YX32),不编造功能名。 - 值映射次序:先判无效 → 再判单/双点 → 最后看位值。无效位上的位值不代表任何事实,次序颠倒就会 把垃圾位画成「复归」。 - 快照新增 yx_dp 双点位图(+8 B)。不教页面"前 4 点是双点":单双点是 104 点表事实(YX_DP_N / iec104_pts_yx_is_dp),抄进表现层就是第二真相——点表把双点段挪位或改起始下标,屏上不报错, 只会用错词形容同一个点。写侧逐点问 is_dp() 拼位图。 - UI_DATA_YX_N(33) 与 iec104_pts_yx_count() 编译期比不了(那个 #define 在协议层 .c 内),故写侧 留一条一次性 DBG_ERROR(约 90 B Flash,只在真漂移时打一次)。名表行数 = UI_DATA_YX_N 由数组 宽度法编译期守卫钉住(ARMCC C99 无 _Static_assert,本仓惯用写法)。 - 补 include 一条实测坑:DBG_ERROR 是宏,漏 include "dbg_log.h" 时 ARMCC 把它当隐式声明函数放过 编译期,错落在链接期(L6218E Undefined symbol DBG_ERROR)——报错点离根因隔了一整个链接步骤, 已在 include 处写明「DBG_TAG 必须在 include 之前」。 一个只有像素文本断言能抓到的截断 bug - 照抄批 1 的 *_PUT(dst, 源) 宏(长度取 sizeof(源)),但本表源是 const char *const 数组的 **元素(指针)**,sizeof 得 4 → 「故障总」被截成「故」,而 "YX9" 恰好 4 字节看起来完全正常。 编译器 / cppcheck / 编码钩子全不响。定位来自断言:第 2 页「过流Ⅰ段」匹配不到,同一行值列 「复归」却在原位 = 名字被截、值没错位。修法:长度取目标缓冲容量 UI_BUF_STRLEN。同名宏、不同 参数类别(数组 vs 指针),批 1 那处本身是对的,照抄才中招——教训写在宏定义上方。 模拟器与覆盖诚实性 - 固定帧发布 yx_dp = 0x0F,但刻意不把这几位置进 yx_valid:V0.1 无开入硬件,屏上就是 "--"。不用 「让它显示合位/分位」的假数据填满画面,那等于让黄金参考声称本机有开关位置遥信。 - 代价如实登记:合位/分位这条词映射当前**没有任何自动化证据**(像素恒 IV;页面依赖 LVGL 进不了 主机单测)。已写进方案 §3.1.3 落地注与契约落地进度·四,作为开入落地后的台架判据,不假装测过。 测试 - 主机单测 +2 条(TC-UIDATA-009c 双点位图原样透传、不被 valid 掩;009d 点数 33 的独立见证,注明 绊红时要同步改哪四处)→ 85/85。 - 文本断言 +33 条(yx / yxp2 两态,含页码钉住 33/8 = 5 页的分页数学);两页像素基线单独一笔。 - font-charset 本批零新增字:名表用字全部命中既有 183 字子集——「置/故/障/总/外/部」正属批 1 成组并入 KEEP_EXTRA 的那批字,第二次兑现(当时若按 extract 输出重写字符集,这些字早被洗掉, 上屏是空白,而门禁只会说「字不在清单里」)。 体积(同一棵树、构建前后的实测增量) - Code 224272→224688(+416);RO 24040→24640(+600);RW 1324→1328(+4); ZI 134844→135088(+244)→ Flash 约 +1020 B、RAM +248 B。 - RO 增量主要是 33 行名表与名称串,是"把 33 个真点名上屏"的代价,不是可省开销。 跳过的门禁(三条同族,同一根因):mem-numbers / mem-budget / size-gate(L0c)——台账与体积凭证 回填是 Lead 单写者,本分支不做静默处理,数值见上。 |
||
|
|
67c469fa40 |
feat(ui-pages): SOE 记录页接 soe_store 只读遍历(类型 7/8 首次上屏)
ui_w_soe 组件(task-14 落)此前两端都没绑 reader,只能显示"无记录"空态。本批补齐三件事:
App 侧只读遍历、两端 reader 绑定、SOE 记录页与菜单注册。
App/log/soe_store 只读 API(Lead 已放行,本批独占这两个文件)
- soe_store_count() / soe_store_read(idx, soe_rec_t*):与 syslog_count /
syslog_get_record 同构——8 条一窗(512 B)整块读、命中窗口零 I/O、卷锁 try(0 超时)
非阻塞;定长记录逐条 open 等于同一扇区开 4 次,SPI NAND 上这个差距是肉眼可见的卡顿
- 读者不得看到半成品记录,三道保障缺一不可(规则写进 soe_store.h 头注,不只是提交信息):
① 条数只数整条 64 B 槽(写者留下的半条尾槽天然不计入);② 窗口代数:写者每次成功落盘 /
容量重建在**卷锁区间内**自增代数,读者比对填窗时记下的代数,不符即重填(对齐 32 位读写
在 ARM 上原子,跨任务无需临界区,最坏多读一轮);③ 单条硬门槛:soe_rec_parse() 校版本 +
校验和,撕裂/半写一律拒收
- 容忍的竞态只有一个:count 与 read 之间新落一条 → 本轮少看一条,下轮重绘(200 ms)自然
追上;所以边界一律用锁内重取的条数,不信调用方传进来的旧值
- API **不带类型掩码**(Lead 裁定 2026-10-25):5 个记录页怎么分组是界面语义,不进日志存储
层;环容量小、页渲染全扫无成本,真变大了再加带 mask 的优化 API(YAGNI)
⚠ 顺带修掉一颗定时炸弹:菜单生成器与生成物漂移
- 提交里的 Drivers/BSP/UI/ui_menu_tab.h 带着 5 个表查询 API 的规范注释块,而
tools/menu_gen/gen_menu.py 只会输出"声明 + 行尾短注释"——说明历史上有人**手改生成物**
补注释、没回灌生成器。我这次加 #page=soe 后重新生成,等于把那些注释抹掉,bsp-err 立刻
报 5 条 return-doc
- 修法不是把生成物改回去(下次重新生成还会再抹一次),而是把注释块**回灌进生成器**;
回灌后重跑 gen_menu.py 产出的 ui_menu_tab.h 与 HEAD **逐字节一致**(git diff 为空),
漂移关闭。生成物里的手工优化 = 一定会被覆盖的优化,要么进生成器要么别改生成物
时标口径(跨模块陷阱,注释即防线)
- 页面时标取记录内的 CP56(事件自己的时标,不是"现在")。它与运行/自检记录页同口径,靠两条
事实叠出来:sys_clock 的 epoch 域本身就是本地时间(App/util/sys_clock.h 的
sys_clock_set_unix 注明"Unix epoch time (秒,本地时间)"),而 soe_rec.c 的 epoch→CP56
分解不加任何时区偏移。**谁"顺手补 8 小时",SOE 页就会和文本记录页差 8 小时**;要引显式
时区必须两侧一起改
显示名回正:类型 7 用源词"未标定闭锁"
- 组件名字表里原写作"标定闭锁"——缩掉一个"未"字后意思可以读成"把标定闭锁了",与"因未标定
而闭锁"几乎相反;源词见 App/log/soe_rec.h 与"数据可信"卡 5,UI 表现层无权改写事实词
- 模拟器的 3 条假记录刻意含一条 type 7 + ELM_NONE(非元件支路):这是 7/8 两个新类型
**真的接上屏**的第一个像素级证据——只有主机断言时,名字表写错也照样一片绿
- 主机测试的宽度护栏随之按"画到哪一列"分列:动作/返回进值列(4 汉字 = 12 字节),其余类型
名进名列(7 汉字 = 21 字节);原来一刀切 12 字节会把正常名字判成违规
页面与注册
- 新建 Drivers/BSP/UI/ui_page_soe.{c,h}:薄跳板,一条记录两行共用组件内单条读盘缓存,
实例独立(两页共用一份缓存会互相命中对方记录号,task-6 的教训)
- 菜单树 SOE记录 加 #page=soe;重生成 4 个生成物,uvprojx / CMakeLists 两处注册由生成器
自动写入(本批 uvprojx 只含这一条新增,无 UV4 抖动)
- reader 绑定在两端适配层:真机 App/task/ui_task.c(CP56 → UI 视图 + 容量钳位),
模拟器 simulator/main.c(固定 3 条、时标固定串,保证黄金参考可复现)
两处被门禁当场抓住的记录(都是有效拦截,不是噪音)
- id-check 拦下注释里裸引"P2-10":编号引用必须可判定归属,代码注释也一样 → 改为指向
App/log/sys_log_mcu.c 与事实本身,不留裸编号
- 又一次 BOM 铁律现场复现:一次编辑剥掉 ui_w_soe.c 的 BOM,ARMCC 立刻报一串 #8/#7/#20
假语法错(missing closing quote 之类),而 MSVC 侧 0 警告完全照不出来;补回 EF BB BF
即 0/0。本批提交前逐文件比 HEAD 做了 BOM 漂移审计(临时脚本,不入库)——建议把这条
审计固化进 ui-verify skill 或门禁(不在本道写域,已回报 Lead)
验证
- @build:0 错误 0 警告;模拟器:0 警告
- 内容页回归 15 项 PASS:新增 soe 页 9 条文本断言(两条时标、过流Ⅰ段+动作、+返回、
未标定闭锁、页码),其余 11 页逐字节不变;菜单 8 状态 PASS、池 5368 B
- soe 页刷新黄金参考前出图肉眼确认:6 行两两成对、19 字符时标在 94 px 名列内不越屏、
非元件行的类型名落在名列且值列为空
- test/host/ui_data 83/83、test/host/soe 32/32;13 个代码/文档/注册类钩子(含
coding-standard、bsp-err、id-check、cppcheck、registration-check、layer-deps、
font-charset、doc-links)全 Passed
- 全量钩子红项只有同族三条:mem-numbers / mem-budget / size-gate(L0c),root cause 一条:
Flash/RAM 台账与同码凭证回填归单写者 → 本批 --no-verify
体积(相对
|
||
|
|
8c72698666 |
feat(运行参数): 卡10 run_par真源收编+104段0x8020~0x8058读写映射(道D M6-①)
新增 App/algo/run_par.c/h(「数据可信」卡 10,lead 四裁落地): - [run_par] cfg 段:遥测死区 9 键 int32 毫单位(db_ua…db_freq),工厂默认 = 卡 6 额定 0.5% 档(500mV×4 / 5mA×4 / 500mHz);注册走 adc_cal 同款内核前 契约(app_main_init),不挂回调 = 引擎副本即生效值;键数 9≤16 不拆段 - 真源收编(裁③):pts 层 s_yc_db 运行时副本删除,COV 每拍实时读 run_par (协议→算法向下依赖,同 meas 先例;无投递无缓存 = 顺序/幂等平凡成立); iec104_pts_yc_set_deadband()/deadband() 保留为转发壳,壳内保留"成功清 半截确认计数"语义并由 TC-IEC104-027 追加断言钉住(裁⑤) - 104 地址映射(裁①):0x8030~0x8038 死区 9 点 / 0x8040~0x8047 k 覆盖 / 0x8048~0x804F b 覆盖(逐项地址本仓自定——复现规划 §5.4 权威表不在仓, 送检点表到位后替换 run_par.c 顶部常量段一处;已在 IEC104 §3.4 表头挂账); 路由顺序 = run_par 表先、未命中落 prot_set——0x8027~0x802A 属 prot_set 告警段永不覆盖,TC-IEC104-029 双向往返钉死;空隙地址自然 COT14/PN - 通道系数覆盖 = adc_cal_set 代理(裁②a):合法带/越带 [ERR] 留痕全复用, run_par 不存第二份系数(防双真源);单侧写 RMW 用另一侧当前生效值; 回显 = 生效值视图(文件坏值被哨兵回退 ROM 时主站看到的就是下游吃到的); adc_cal 配套:+adc_cal_b_codes() 读取口(回显/RMW 用)+ set() 授权写者 注记扩至 iec104Task 直通路径(单字原子契约同「数据可信」§4.4) - 持久化(裁②b):新事件位 SYS_EVT_RUN_PAR_SAVE(1<<8);iec104Task 主循环 peek 投递 → defaultTask run_par_store_save() 一条事件一趟 cfg_file_save 整档外科(覆盖 [run_par] 9 键 + 联动 [adc_cal] 两段);失败脏保留 = 天然 重试(B7 prot_set 同款)。C_SE 现行无"暂停/测试态"门控——文档现行如此 不造新语义,送检若要求接线点已写进 §3.4 注(裁④) 测试:新建 test/host/run_par(TC-RUNPAR-001~008,67 断言,真实 cfg 引擎 + 真实 adc_cal + 内存虚拟盘同 adc_cal 套件先例;[run_par] 注册契约/落盘往返/ 外改文件即副本生效/两段式不提交不置脏/合法带拒+RMW+生效值回显/init 幂等 重注册留痕);iec104 套扩真链 TU(cfg_file+adc_cal+run_par 非桩,141 断言: +TC-IEC104-029 路由 + 壳清确认计数 3 断言);meas 套静态更名 s_snap*→ s_ms_snap*(与 cfg_file.c s_snap 同 TU 相撞,D1 同款改名法,226 断言不变); iec104_serv 套补 run_par_dirty_peek 假件。id_registry 建族 TC-HOST-RUNPAR (游标 008)+ TC-HOST-IEC104 游标 028→029;新钩子 run-par-unit-test + iec104 钩子触发面随真链扩;uvprojx +run_par.c(合法入库)+ SIM_EXEMPT 登记 (模拟器不编 104 协议,已核实 CMake 面)。 文档:IEC104 §3.4 运行参数段表(含送检替换账/门控未来条件/代理声明)、§7、 §8 第 4 条、变更记录;网络配置说明新增 §3.5 [run_par] 键表;复现规划 §5.4 补运行参数段落实进度。**遗留(交 lead)**:数据可信 §4.4 "引擎 RAM 副本" 一节当时的措辞对象含 pts 侧副本,s_yc_db 删除后该句过时(裁③b 点名,§4.4 在写域外未动)。 gate:@build 0/0(Code=219620 RO=22036 RW=1280 ZI=132864);vs 0cbae7d: Flash +1912B、RAM(RW+ZI) +8B(37B 新静态被链接器并洞吸收);iec104Task 栈 1456B/margin 43%、defaultTask 3032B 不变;id-check/doc-links/cppcheck/ coding-standard 实跑过;--all-files 全量 45 钩子实跑(43 绿 + 仅 mem-budget / mem-numbers 两红 = 台账受管区 vs .map 漂移,回填属 lead 单写者区,批 1/道D-1 /D2 同口径):gate: only mem-budget/mem-numbers pending lead ledger backfill BOM/CR/U+FFFD/字面量 ASCII 逐文件自查通过。 |
||
|
|
acc547efaf |
feat(104遥测): 卡9改读L2快照+死区运行化2点确认 + 卡11绑频0x401D(道D M5/M6)
卡 9(App/protocol/iec104/iec104_pts.*,「数据可信」,docs/子系统设计/ IEC104上行设计说明.md §3.1/§4 同步): - 数据源换轨:板端默认 YC 源从直读 phasor 改为**整体透传 L2 遥测快照** (meas_get 双区无锁;"新不新、能不能信"只在发布侧判一次,M5-② 落地); iec104_pts_src_t 表尾追加 yc_read_ex(带品质)——旧注入源走 legacy 退路, 品质由返回值推导,行为与卡 9 前**完全一致**(存量假源用例零改动) - 品质映射 s_q_map:MEAS_QDS_* 低字节=线上 QDS 同值直传;CLIPPED→IV (「削顶通道 104 恒 IV」口径不变、从点表绑死 -1 改品质驱动——UB/UC/IB/ IC/IN 五路现绑快照槽,V0.2/N-18 削顶消失后**零改动自动启用**);IV 优先 NT;快照从未发布(开机 <200ms)→ IV|NT;无效信息体清零(旧线上口径保持) - 死区运行化:运行时副本 s_yc_db(ROM 默认 = 点表列,卡 6 额定 0.5% 档不变) + iec104_pts_yc_set_deadband()/iec104_pts_yc_deadband()——卡 10 运行参数段 (8020H)的接线点已留;非法 idx/负值/NaN 拒绝、成功时清该点待确认计数 - COV 遥测腿升级(lead 裁②"卡 9 是消费者"):判定 = 相对**上次上送值**(非 上次读值,防慢漂移吃基准)连续 2 个新测量点越死区才确认上送;回摆入带即 撤销候选;品质翻转当拍直报(含 0x401D 的 IV 进出)。测量点推进:板端按 快照 seq 去重(100ms poll vs 200ms 快照——不去重则同一帧把单点噪声计满 2 点,抗噪语义失效);注入源=每次调用一测点(单测步进自持) 卡 11:YC 表加 src 类型(PTS_SRC_MEAS/FREQ);0x401D 绑快照 freq_hz(与 freq_get 同源);snap.freq_valid==0 → IV 清零(卡 11 DoD 原句) 测试与文档:test/host/iec104 97→127 断言——TC-008 语义更新为 2 点确认; 新 TC-IEC104-025~028(024 号被存量 B7 用例裸标签占用,让号并改用全家长 形态)板端默认源走**真实 L2 链**(ring→phasor→freq→meas,非桩):未发布 NT/值透传/CLIPPED→IV 清零/绑频收敛 ±0.02Hz/未新鲜 IV/死区运行档压旧档/ 回摆撤销/seq 去重同帧不计数/换帧只变品质按集合直报;id_registry 族游标 023→028;IEC104 上行设计说明 §3.1 表+注/§4/§7/§8 第 4 条/变更记录同步。 无新 .c(uvprojx 零改动);PC 主站读回一致与频率 ±0.01Hz 属网络对端验证 ——步骤清单已发 lead 排窗,本轮零台架动作。 gate:@build 0 错 0 警(Code=218128 RO=21624 RW=1272 ZI=132864);增量 vs adeef7d:Flash +348B、RAM(RW+ZI) +48B(低于 96B 预估,链接器并洞), IRAM1 58.5% 不变;iec104Task 栈 worst=1456B margin=1104B(43%) PASS 无抬栈 (stack_report);--all-files 全量实跑:其余钩子全绿(含修掉一处 cppcheck variableScope 后),仅 mem-budget + mem-numbers 两红 = 台账受管区 vs .map 漂移(回填属 lead 单写者区,批 1/道D-1 同口径): gate: only mem-budget/mem-numbers pending lead ledger backfill BOM/CR/U+FFFD/字面量 ASCII 逐文件自查通过(未触碰带 BOM 文件)。 |
||
|
|
62987b4596 |
Merge branch 'v2-on-ui' into task/meas-snap
# Conflicts: # scripts/id_registry.json |
||
|
|
48bc50e794 |
feat(遥测快照): 卡8 meas 双区快照模块 + adc_task 200ms 唯一发布点(道D M5)
卡 8(App/algo/meas.*,新增;布局权威 docs/任务规划/数据可信.md §4.5): - meas_snap_t = §4.5 布局(sizeof 72 B;字段偏移由 TC-MEAS-002 钉死——卡 9/ UI 按整体拷贝消费,破布局=破协议;谐波 k-bin 扩展(docs/算法/继电保护功能 复现规划.md L2-8)只许尾部追加,留口注释已写进 meas.h) - 并发 = phasor 双区 + 单字节索引翻转(L2-7 同型,无锁);seq 只增供判"换帧"; meas_get 失败路径清零填充(-2 未就绪时调用方可安全读) - 值口径 = A-lite 裁决(lead 2026-10-25 快裁,推翻票面全链):基波有效值瞬时 透传,复用 phasor_calc 纯核 → 与 phasor 使用区同拍同值(TC-MEAS-005 逐位 相等钉死);不做 4 点平均/方和根(§4.5"200 ms 是上送节拍不是平均窗") - 品质注入:CLIPPED 位图唯一源 = adc_cal_flags()(「数据可信」§4.2 三态表, 编排方注入、本层不链 adc_cal);取窗不足路 = IV|NT 且整帧 valid=0 但照常 发布(品质节拍性刷新);TEMP = 最新一点透传 + NT(「数据可信」决策 5); MEAS_QDS_* 低字节 = 104 QDS 线上值(本层不 include 协议层头——分层方向, 卡 9 直接截低字节映射);OV 留位不填(判据待运行参数化,卡 10 域) - adc_task.c 编排:新帧拍 freq_run() 后按 **tick 经过**分频(非拍计数,idle/ skip 拍会拉长名义节拍)调 meas_tick()——全仓调用点数 = 1(「数据可信」§8 风险表"快照双写"行评审判据);meas_init 挂 adc_task_init(不动 app_main.c); 心跳新增 meas: 行(seq/v/ua·un·ia_mv/f/fv)作 M5 台架观测面 - 死区 2 点确认状态机本卡不建(卡 9 迁移 104 语义时随建,lead 裁③);104 层 现有 deadband 常量未动;频率点绑定归卡 11 - 实测采样类判据(读数 vs 注入源)= 待台架实测,本卡零台架动作 测试与注册:新套件 test/host/meas(226/226,链真源 meas+phasor+sample_ring 免桩;覆盖 seq/双区无撕裂/布局/品质汇总/回绕/守卫);id_registry 建族 TC-HOST-MEAS(游标 011);meas-unit-test 钩子 + SIM_EXEMPT 一条 + uvprojx 仅增 meas.c 单条挂载(diff 已核零 UV4 抖动);App/algo/README.md §1/§2/ §3.9/§4 同步(设计说明大节与 AGENTS 口径留 lead 收口,同批 1 先例) gate:@build 0 错 0 警(Code=216352 RO=21476 RW=1232 ZI=132128);RAM 增量 RW+ZI = +152 B(快照双区恰 +144 B = 卡面 DoD;余 s_meas_ms 等编排状态), IRAM1 57.8%→约 57.9%;Flash(Code+RO+RW)+696 B;adcTask 静态最坏链 1408 B / margin 1152 B(45%)PASS(stack_report 实测,无抬栈);BOM/CR/U+FFFD/ 字面量 ASCII 逐文件自查通过(未触碰带 BOM 文件)。pre-commit run --all-files 实跑:其余钩子全绿(含 doc-links/id-check/ 覆盖率总闸/双端注册/ui-golden/全部主机单测套),仅 mem-budget + mem-numbers 两条红 = 台账受管区 vs .map 漂移(Flash/RAM 台账回填属 lead 单写者区,批 1 同口径): gate: only mem-budget/mem-numbers pending lead ledger backfill |
||
|
|
98664a11ed |
merge: task/ui-data-feed 合入 v2-on-ui
任务 ui-data(2 个提交)经 task-worktree 回收: - feat(ui-data): ui_data 三通道快照 + ui_data_feed 装配 + SOE 显示名映射 - feat(ui-font): 字库补 SOE 显示名用字 采/样/恢/效(179→183 字 / 274→278 字形) |
||
|
|
201d713226 |
feat(ui-data): ui_data 三通道快照 + ui_data_feed 装配 + SOE 显示名映射
按 docs/UI设计/UI_数据供给设计说明.md 的 D 方案把 App→UI 数据通道落地:
App 组帧、BSP 存帧、页面只读;UI 侧零 App include,薄包装只在两端适配层。
本笔是纯增层、不接任何页面 → 零像素变化(菜单 8 状态 + 内容页 11 页黄金
参考逐字节不变,simulator/tests/ref 无 diff,未刷基线)。
新增
- Drivers/BSP/UI/ui_data.{c,h}:实时量 rt / 参数 par / 装置信息 info 三通道存储
+ 发布序号盖章 + 只读访问。零 App include、零 LVGL include(分层叶子);
读写同在 uiTask 上下文串行 → 无锁、无双缓冲、无 seqlock(契约 §5.1)。
- App/app/ui_data_feed.{c,h}:快照唯一填充者。rt/info 每 200 ms 一帧,par 只在
prot_set_checksum() 变化时重发;首轮立即发布,免启动初期闪一下 "--"。
- Drivers/BSP/UI/ui_w_soe.{c,h}:SOE 二进制记录的显示名映射与注入式 reader
契约。未标定闭锁=7 / 标定复归=8 已进表——编号按 App/log/soe_rec.h 与
App/algo/prot_elm.h 现场数过(类型 1..8 + 哨兵 9、元件 0..8、ELM_NONE=0xFF、
FLG_IV=0x80),不采信文档与消息转述。reader 备好但两端未绑定:落盘侧还
没有只读 API(Lead 已裁该 API 归下一工作项),未注入按"无记录"空态渲染。
量纲诚实性(契约 §4.1 同步改成真值口径,不再抄旧码值表述)
- eng 不写"0 = 原始码值":标定层 ROM 系数是引脚侧 LSB,采样环折算出来的就是
ADC 引脚电压(承诺边界 docs/任务规划/数据可信.md §2.6);电气 8 路
adc_cal_flags() 的 VALID 全置位才升 eng=1 二次值——整帧共用一个 eng,只要
还有一路是引脚电压就不能贴"二次值"标签,宁可整体保守。
- TEMP 不参与线性标定 → 恒带新增品质位 UI_DATA_Q_RAW=0x20,页面不挂单位。
- UB/UC/IB/IC/IN 无基波相量实例(V0.1 削顶)→ Q_IV|Q_OV;未满一周波 → Q_NT。
- 谐波另开 ph[] 相量实例槽带:yc 的语义通道下标容不下同通道的二次/五次谐波。
接线与双端注册
- App/task/ui_task.c:ui_menu_init 之前 ui_data_init + 首帧发布;主循环每轮
ui_data_feed_tick() 排在 ui_port_step 之前(本轮渲染用本轮刚发布的帧)。
- simulator/main.c:发布固定合成帧(无头与窗口两个初始化点,先于建页);
定值不手抄 40 个数,改为链入 App/algo/prot_set.c 取出厂默认(抄表等于造
第二真相);build_date 用固定串而非 __DATE__,否则跨天重建会把装置信息页
黄金参考刷掉,而黄金参考是判据本身。
- 注册:uvprojx 加 3 条(App 组 ui_data_feed.c + UI 组 ui_data.c/ui_w_soe.c)与
simulator/CMakeLists.txt;ui_data_feed.c 不进模拟器 → check_registration.py 的
SIM_EXEMPT 加一行(App/app/app_main.c 先例,已报备)。
主机单测与钩子
- test/host/ui_data:82 断言全绿。钉三类事:快照语义(首帧前读 -1、序号由本层
盖章、三通道互不串台、NULL 防御、init 幂等复位);跨层不透明下标现场一致
(yc 序 = adc_semantic_t、q10 序 = prot_set_id_t,同一 TU 里 include 两侧头);
SOE 编号与名字表现场一致(八类事件都有名、采样/标定四个词互不相同、
名长不超列宽、越界回占位)。
- .pre-commit-config.yaml 加 ui-data-unit-test 钩子(第 43 个,Lead 已批自加)。
- scripts/id_registry.json 建族 TC-HOST-UIDATA(属主登记处 = 单测目录,同
TC-HOST-ADCCAL 先例;不建族则新号被编号门禁判"未登记前缀")。
体积(相对 HEAD 台账 Code 215744 / RO 21396 / RW 1224 / ZI 131984)
- Code +1272 B、RO +108 B(字库 4 字,见上一笔)、RW +24 B、ZI +696 B
→ ER_IROM1 238520 B(22.7%)、RW_IRAM1 76504 B(58.4%,台账 57.8%)。
- .map 逐项:ui_data.o 488 B(Code 184/RW 12/ZI 476)、ui_data_feed.o 221 B
(1034/12/209);LVGL 池 0 增量;ui_w_soe 未接线不进镜像(.map 无其符号)。
- 台架未跑(本笔零像素、零接线):首帧时刻、200 ms 刷新、eng 升档与遥信
位图真值全部留"待台架实测",接线完成后请 Lead 排窗。
遗留与风险(随回报进台账)
- 写路径(契约 §6 的 param_request/state)不落:无消费者就是永不执行的死码,
随整定 4 页一起落;届时须先定"UI 整定 vs iec104Task 写 prot_set"的并发口径
(prot_set_set_sealed 的影子区非重入)。
- 公共地址 CA 未下发:固件里 CA 逐帧从 ASDU 头解析,无集中常量可取。
- 遥信位图与 App/protocol/iec104/iec104_pts.c 板端源是两处镜像(该文件位号
写在函数体内未导出,UI 不得 include 协议头),开入采集落地时应并成单源。
- 版本类字段是本文件内的宏(仓库无产品级版本登记表,值沿用页面既有显示
值);软件校验位在拿到构建期 CRC 步骤前一律显示 "--",不抄参考遗留值。
gate: 全量钩子(--all-files)40 项通过;cppcheck/test-cppcheck/coding-standard/
layer-deps(基线仍 3 条)/registration/bsp-err(存量 38 条不变)/font-charset/
id-check(增量无新账)/doc-links/ui-golden/主机单测与覆盖率全绿;唯一红项是
mem-numbers 与 mem-budget——两者只因 Flash/RAM 台账未回填(禁区,归 Lead)。
gate: only mem-budget/mem-numbers pending lead ledger backfill
自查:BOM(Drivers/BSP/UI/* 与 App/task/ui_task.c 保持 EF BB BF,新建 UI 两件
同规范;App/app 与 test/host 无 BOM 与本目录一致);CR = 0 全 LF;U+FFFD = 0;
字符串字面量纯 ASCII(中文只进注释)。
|
||
|
|
484d068250 |
feat(存储): 写回缓存空闲 flush 兜底——卷空闲周期 CTRL_SYNC(登记簿 N-22 收口)
道F 批 2 / task-16。FTL 单页写回缓存(nand_ftl.c s_cache_dirty)与 dhara journal 只在换页/整页写/f_close 时刷出,漏网脏页的掉电驻留窗无上限。本 提交以最小面收口:不碰 GD5F/dhara 驱动,全部走既有 FatFs CTRL_SYNC 路径。 实现 App/fs/vol_idle_sync.[ch](新增,仅 MCU 端,uvprojx App 组注册): - 四级门:STORAGE_READY 就绪门 → 5 s 节流(无符号差回绕安全判据)→ vol_lock_wait(0) try(锁被持有=文件序列在做,跳过,不改 STOR 持有期 语义)→ disk_ioctl(0, CTRL_SYNC); - clean 态脏标志+journal 双短路、零 NAND 触点;脏态最坏 = 一次 f_close 的同步段同型成本,不引入新磨损来源; - 失败按边沿 latch 一条 DBG_ERROR、成功重新武装;失败路径也成对放锁; - TEST_SUITE_STORAGE 构建整体 no-op(卷由 testTask 独占)。 接线:defaultTask 主循环 syslog_drain 之后(default_task.c v1.3)。 文档:docs/架构设计/STM32F4-Base存储架构说明.md §5.5 补空闲兜底与边界; 本板无掉电检测硬件、不做掉电前强制 flush、勿当掉电保护——口径同步落 注释与文档(sys_log_mcu.c 两处旧「暂不做」注释随实现改口)。 测试:新主机单测 test/host/vol_idle_sync/(TC-VOLSYNC-001..012,19 断言 全过);scripts/id_registry.json 建 TC-HOST-VOLSYNC 族(仿 ADCCAL 先例); .pre-commit-config.yaml 加 vol-idle-sync-unit-test hook(只加自己条目)。 越界申报(①②③ 均 lead 批准,④ 为门禁连带必要): ① App/task/default_task.c 单点接线(include + 1 调用 + 头修改记录); ② docs/架构设计/STM32F4-Base存储架构说明.md §5.5; ③ .pre-commit-config.yaml 单 hook + scripts/id_registry.json 单族; ④ scripts/check_registration.py SIM_EXEMPT 加一行(vol_idle_sync.c 模拟器 侧豁免,registration-check GAP 所需;与批准③同类别但未列名,特此申报)。 体积增量(vs scripts/ram_baseline.tsv 2026-10-25 行): Flash(Code+RO) 237140→237328(+188 B)、RW 1224→1232(+8 B)、ZI 0; 增量 = 3 个文件级 static + 一处 DBG_ERROR 调用点;栈/堆无变化。 gate: only mem-budget/mem-numbers pending lead ledger backfill 全量 pre-commit --all-files:40 项 Passed,仅 mem-numbers(D-7 体积档)与 mem-budget 两条红 = 台账数字待回填(增量如上,属 lead 单写者禁区); 其余含 doc-links/id-check/registration/test-coverage/全部主机单测皆绿。 @build 0 错误 0 警告(Code=215932 RO=21396 RW=1232 ZI=131984)。 台架:空闲 sync 实机节奏(clean 零触点、脏态时长、无心跳扰动)属实际 测量采样类——本批跳过,留「待台架实测」。 |
||
|
|
73f9e10492 |
merge: task/P1-10-test-fw 合入 v2-on-ui
任务 P1-10(8 个提交)经 task-worktree 回收:
- chore(size): sync 追平后重盖体积同码凭证(v2 索引指纹,1396 文件)
- docs(P1-10): sync 追平后补记四档复测数字(产品基线已前进,旧注保留)
- merge: v2-on-ui 追平至 task/P1-10-test-fw(含 A-3 卡5~7 与 B-3 记录 reader)
- test(P1-10): 套件回归 forbidden 换成显式四 Fault 标签 + 台架记录 21/21
- fix(WD): HW 测试模式掩码死分支复活——include 缺失自
|
||
|
|
8c28f3bfdd |
docs(收口同步): 批 1 落地后 AGENTS/104/算法层口径更新 + SOE 7/8 消费面补齐
- AGENTS.md:钩子 40→42、主机单测钩子 16→18(adc-cal/prot-dim)、 覆盖率总闸 28→35 套、layer-deps 基线 6→3(记录 reader 注入兑现) - IEC104上行设计说明.md:遥测读数改工程量口径 + 死区额定 0.5% 重定 已落地(卡 6);§8 第 4 条改写、变更记录追加行 - 采集与算法层设计说明.md:状态行/红线③/幅值门三处由「标定未实现」 更新为「折算已落地、精度复核待卡 12 注入」 - App/log/soe_rec.h 类型注释表补 7/8 两行(lane-a 口误 6/7 已勘误, 真值按枚举链 SAMPLE_RESUME=6 连续计数) - test/host/soe/decode_soe.py:TYPE_NAMES + docstring 补 7/8—— 否则台架 FTP 下载校验会把标定闭锁记录判 bad type 误红(隐藏消费边); soe 套件 32/32 复跑绿 |
||
|
|
a28123115d |
merge: v2-on-ui 追平至 task/P1-10-test-fw(含 A-3 卡5~7 与 B-3 记录 reader)
按 lead 信号 sync 追平:主干 59da40b(cal-lockout-dim)+ 891ca81(UI-rec-reader)+ 383b450(台账与凭证回填)合入本任务分支,为下一轮台架做准备(台架镜像必须建立在 追平后的代码上,否则烧进去的 hex 与主干不同码,体积门禁的凭证也对不上)。 唯一冲突:scripts/size_attestation.json —— **取主干侧**(383b450 刚按合并后的固件重盖 过,数字更新;本分支侧是 |
||
|
|
a9ba8ec745 |
fix(WD): HW 测试模式掩码死分支复活——include 缺失自 7feeea6
结论先说:wd_required_mask() 里那条"硬件层测试构建剔除 netTask"的分支,自它被写进
仓库那天起**从未生效过**——不是逻辑错,是本编译单元根本看不见判据宏。台架一轮
(2026-10-25,boot log 20261025_050539)把它照出来了:
- 468 条 [ERR][WD] task stall 里,**431 条是 mask=0x1F5 / req=0x1F7**;
- 0x1F5 恰好等于那条死分支本该要求的集合(default|ftp|ui|timesync|adc|iec104|
protect,NET 位不在内)——该动的任务全动了,只是"要求方"看不见自己的例外,
于是按产品掩码 0x1F7 追 netTask 的心跳位;而 netTask 在 ENABLE_HW_LAYER_TESTS
下按设计入口自挂起(CH395F 归 testTask 独占),永远追不到。
根因:ENABLE_HW_LAYER_TESTS 定义在 test/board/ch395f_test.h(经 test_config.h 拉入),
而本文件没有 include 任何一条通往它的路径 → #if defined(...) 在本 TU 恒为假 → 死代码。
同一个需求早有既有做法:App/task/net_task.c:39 就为这个宏 include 了 test_config.h,
注释还写着"产品构建全未定义,无作用"——本文件只是漏了这一步。
修法:补 #include "test_config.h",并把根因与 req/mask 证据写在包含点上方(同一事实
不另开文档;销项时 docs 引这里)。写域扩到 App/util 由 lead 背书(看板 task-9)。
零产品影响(实测,不是推演):
- 产品态(TEST_SUITE_* 全注释、宏未定义 → 走原分支)@build 0 错误 0 警告,
Code/RO/RW/ZI = 214104 / 20388 / 1204 / 131852,与主干 2026-10-25 台账逐项相同。
- 测试态 hw_nopc 尺寸也与修复前逐项相同:改的只是"选哪个常量",没有新代码路径。
- 修复后净效果(下一轮台架复核):431 条 net 类 stall 消失,剩下的是 uiTask 间歇
缺位的 37 条(0x1E7 / 0x1E5)——那是另一件事,不在本提交里掩盖。
顺手记两条**没在本提交改**的发现(判据语义,归 lead 裁):
1) 抽样判定是**精确匹配**(注释自述:"掩码必须恰等于会置位的任务集合")。而 netTask
自挂起前会喂一次位 → 那一瞬间 mask=0x1F7 又不等于剔除后的 0x1F5 → 照样报 stall。
即"从掩码里剔一位"与"精确匹配"天然打架;要不要放宽成"观测 ⊇ 要求即可"值得单定。
2) 本轮 miss 一路涨到 1971 而**没有停喂、没有复位**:说明"连续未达标即停喂"的阈值
路径在 HW 层测试构建里未被触发(或 IWDG 尚未启动)。这条对产品侧更重要,值得单查。
随附 .cubemx_survival_baseline.json:本文件在存活审计里是 kind="generated" 的整文件
哈希项 watchdog-module("非 CubeMX 管辖,但须确认未被误删"),有意改动按脚本自述用
--write 重建基线。**先证明漂移 100% 来自本笔**:把我的 include 临时撤掉再跑
--check → rc=0(基线与 HEAD 逐项相符),因此不存在"别人早就改了没登记"的情况。
--write 顺带补出一条**基线里原本缺失**的条目 net-msgq-adopt(Src/freertos.c 的
RTOS_QUEUES 区,须含 net_msg_queue_adopt):它此前不在基线里 → --check 一直在静默
跳过这一项。本笔把它一并登记,属于意外收获,不是本笔的目的。
gate:cppcheck / coding-standard / bsp-err / id-check / no-mojibake /
trailing-whitespace / end-of-file-fixer / mem-numbers / mem-budget /
cubemx-survival(已 --write 重建基线)全 0;
未用 --no-verify。
|
||
|
|
59da40bb4a |
merge: task/cal-lockout-dim 合入 v2-on-ui
任务 cal-lockout(1 个提交)经 task-worktree 回收: - feat(保护标定): 卡5 未标定闭锁 + 卡6 下游三常数重定 + 卡7 量纲回归单测 |
||
|
|
ffd462ef3c |
feat(保护标定): 卡5 未标定闭锁 + 卡6 下游三常数重定 + 卡7 量纲回归单测
卡 5(protect_task.c 第⑤闭锁源,「数据可信」§4.3 决策 1=闭锁): - UA/UN/IA 的 adc_cal VALID 未全置位 → prot_elm_init + 本拍不 eval;每拍现查 flags、无自有状态(卡 12 标定写入后自动解锁);判据链优先级 = 采样可信在前、 标定可用在后(数据都是旧的谈不上标定) - 边沿日志用 DBG_INFO 而非 [ERR]:未标定是出厂常态、非故障,且 @test 禁用 [ERR](「默认构建保护不动作 = 期望」的台架判据同步项已在 MR 报 lead); SOE 分型 SOE_T_CAL_BLOCK/RESUME(soe_rec.h 枚举尾追加,值 6/7——reader 侧 显示标签映射归道B reader,MR 已报) - 台架旁路 = 编译期宏 DTU_BENCH(§4.3:不进 cfg 不进 104;本仓所有提交目标 都不定义它 = 产品恒强制闭锁) 卡 6(下游三常数按工程量重定,依据同源 docs/任务规划/数据可信.md §2.3): - FREQ_AMP_MIN(freq.h):语义从拟定码值域重定为二次值 V——50 V = 0.5×Un (标称 100 V),断保险/PT 空载/浮空必低于之;数值沿用 50.0f 属巧合并在 注释明写;eng=0 过渡期本门恒失效 → OF/UF 按必不启动填充,与卡 5 同向安全 - k_yc[].deadband(iec104_pts.c):9 点按「额定 0.5 %」规则重定:电压类 0.5 %×100 V=0.5、电流类 0.5 %×1 A=0.005、频率维持 0.5 Hz 绝对值(非额定 比,卡 10 运行参数化);标称基准与 prot_set 头部同源,防两处真相 - g_prot_set_meta[](prot_set.c):数值/范围复核结论=不动(0~4×标称自洽), 文件头补量纲口径块:A/V = 二次值、标称 100 V/1 A、OV120=1.2Un/UV20=.2Un/ 3U0 15=.15Un、OC1/2/3=10/5/2×Ir、OL=1.0×Ir;PS_ID_COUNT/blob VER 未动 - iec104 套件 TC-008 死区用例同步重定标(100.4 带内 / 101.25 越带),97/97 卡 7(test/host/prot_dim 新套件,真实链 adc_cal→ring→phasor→prot_elm): - 用例从 ADC 码值出发、显式写出 code↔二次值互逆换算(dim_code vs apply), 折算点被旁路或量纲再错位断言立刻翻转(M4 判据⑥「不该动作时不动作」) - 合成 ROM 覆写(#undef K_Q16 宏)模拟卡 12 标定后板级口径,走 adc_cal_set 正规路径置 VALID;b=-30 码全链对消进 rms 断言 - 38/38:基线静默(含 OL 低定值陷阱)、反错配对照(raw 码值灌环复现历史事故 必假动作 vs 经折算必静默)、OC1/2/3+OL+OV+UV+3U0 七类逐一:越限定值→ 受控启动拍→dly-2 不动作/+5 动作→返回系数带内保持→跌破释放、双件聚合位图 独立性(撤 IA 只回 OC1) 测试与注册:prot-dim-unit-test 钩子 + TC-HOST-PROTDIM 族(游标 010,B 层口径 同 ADCHEALTH/ADCCAL 先例);无新 MCU 源文件(uvprojx/SIM_EXEMPT 零改动) gate:@build 0 错 0 警(Code=215640 RO=21388 RW=1220 ZI=131980 vs 基线 215440/19780/1220/131980 → Flash +1808 B、RAM 零增量);protectTask 静态最坏 链 872 B/margin 1176 B(57%)PASS,adcTask 不变;staged 门禁除 mem-numbers/ mem-budget(台账漂移,回填归 lead)外全绿: gate: only mem-budget/mem-numbers pending lead ledger backfill BOM/CR/U+FFFD/字面量 ASCII 已逐文件自查(本轮未触碰带 BOM 文件) |
||
|
|
c4edf352fe |
refactor(UI): 记录页改注入式 reader,layer-deps 基线 6->3(道B task-6)
B-6 分层收紧(UI_数据供给设计说明.md §7.2 契约原样落地):
- ui_w_records:删 #include "sys_log.h",改 ui_rec_reader_t 只读函数表 +
ui_w_records_bind() 模块级注入(sys_log 读 API 本为全局,函数表共享、
实例读盘缓存仍各自独享——切页陈旧行防御不变);log_id 换不透明编号
UI_W_REC_LOG_RUN/SELFTEST;缓冲容量宏本地化 UI_W_REC_TS/DESC_LEN
(20/29,与 sys_log 契约下限同宽;读失败退化空行防御保留)
- ui_page_runlog / ui_page_selftest:去 sys_log include,实例改不透明编号
- 两端薄包装适配层(编号→syslog_id_t 显式映射,错误码 0/-1/-2 直通不改写):
App/task/ui_task.c 与 simulator/main.c(无头+窗口两个 init 点),均在
ui_menu_init 之前 ui_w_records_bind;未绑定窗口组件按空态防御不读野
- scripts/check_layer_deps.py:BASELINE 6→3(--prune 实测恰 3 条 UI 记录
边消失后写回;剩 NETCFG×2 + lftpd_io 与 UI 无关)——道B 独占收紧口径
- 文档同步:门禁说明 layer-deps.md §1/§6/§9 与 README 计数 6→3;
UI_数据供给设计说明.md §7.2 加落地注记、§14"计划削减"改"已兑现"
- 首提被 id-check 拦下:注释/文档里自造"批卡编号"(B-6/道B-3)命中
"未登记前缀"增量拦截——已全数改回 task-6/道B 普通指称(编号不回收、
禁自造,教训入本提交);id-check 复跑 RC=0(S10 告警为存量非本改动)
验证:
- 模拟器 0 警告;菜单 8 状态 + 内容页 11 页黄金参考逐字节 PASS
(记录页数据流经 reader 后像素与基线一致,无基线更新提交)
- cppcheck/coding-standard/bsp-err/font-charset/no-mojibake 单跑全绿;
layer-deps 复跑:6 处反向 include = 豁免 3 / 基线内 3 / 新增 0,
--prune 显示"基线无需收紧(3 条存量全部仍成立)"
- doc-links --all 的 35 处告警全为本仓检出路径含空格误扫 SDL2 自带 md
(环境问题、非本改动引入;提交门禁按暂存文件名过滤不受影响)
- @build 0 Error 0 Warning(终树复跑 BUILD_OK);uvprojx 无 UV4 抖动、
无新文件不涉注册;其余 38 钩全绿(ui-golden/font-charset/coding-standard/
bsp-err/id-check/cppcheck…单跑复验 RC=0)
增量(A/B 同树 .map,基线 = 合入
|
||
|
|
3528644e9d |
feat(采集标定): 卡2 adc_cal 折算模块 + 卡4 系数落盘 + L5-2 码值贴轨检出
卡 2(App/algo/adc_cal.*,新增;adc_task.c:335 折算点收口): - 模型:工程量 =(code+b)×k(「数据可信」§4.1);k 以 int32 Q16(µV/码×65536) 落盘、b 以 int32 码值落盘;ROM 默认 = 卡 1 定死的引脚侧 LSB,Q16 下整除无 舍入(TPAFE 10,000,000=152.587890625 µV/码;STM32 52,800,000=805.6640625) - adc_task 每拍 frame[s] 改 adc_cal_apply()(现单位 = ADC 引脚电压 V,eng=0, 二次值语义等 VALID);TEMP 透传码值(决策 5);不缓存 k_f 副本——逐点由 RAM 现值派生(无回调设计下杜绝陈旧系数;18k flops/s 可忽略) - 三态 flags(§4.2):VALID = 文件位图 ∧ k 在合法带;CLIPPED 按来源运行期 派生(V0.2/N-18 后自动恒 0);消费者判可用性只查 adc_cal_flags() - 合法带哨兵:k∉ROM×[0.5,2.0] 或 |b|>8192 → 折算回退 ROM + 每通道每开机 一条 [ERR] + VALID 压制(位图说谎也兜住)——同时挡坏文件与坏标定 - 两点标定公式 adc_cal_two_point() 算术核齐备(int64、±舍入界、斜率/零点 守卫 -1/-2 分档);台架两点标定(卡 12)按用户指示未跑,留台架注入口径: 心跳新增 cal: 行(ua/un/ia_mv 定点 + vl/cl/rail 位图,未标定 vl 应恒 0x00、 cl 应恒 0xE6,注入饱和电平 rail 位应起) 卡 4([adc_cal] k_ua..k_in+valid / [adc_cal_ofs] b_ua..b_in,§4.4 布局): - 两段注册进 cfg 引擎(data_size 33/32,不挂回调——RAM 副本即生效值); adc_cal_init() 落 app_main_init 内核前(注册必须先于 defaultTask 的 cfg_file_load;跨任务读走 4 字节对齐字,µs 级混窗为「数据可信」§4.4 明载 设计);文件缺失/损坏 = 引擎回退工厂默认 = ROM 表本体(默认即理论系数) - adc_cal_set():整定写入口(属主上下文),越带拒绝 RAM 不动 - 单测走真实 cfg_file 引擎集成:文件值生效 / 越界 k 哨兵兜住且不报 VALID / 超长损坏文件回退默认且 flags 无 VALID(卡 4 DoD 原句)/ 段缺失默认 L5-2(adc_health v1.2,越界门限按 FS 百分比、码值域与标定正交): - adc_health_rail_watch():连续 20 拍(=一周波)贴同侧轨带(TPAFE±98%半量程、 STM32 顶 98%/底 2%,门限由 adc_cal_rail_ths 供)且此前见过中带释放沿才 锁存——空载恒 0 / 开机恒 0 合法工况不误报(短板评测 §6.2 判据①); adc_task 编排:边沿 DBG_ERROR + SYSLOG 每开机一次 + 心跳 rail/edge 位图 - 健康用例 60/60(+13):释放沿/清零/交替/双侧/init 复位/越界通道守卫 测试与注册:新套件 test/host/adc_cal(89/89,8 通道×≥3 码点期望值由 LSB 常数独立推导、Q16 无舍入、set 边界含端点、两点还原合成 k/b 往返); 编号形态返工一轮:TC-ADCCAL-00A~00D 改 014~017、注释 FS-1 字样改写、 id_registry 族 pattern 转义修正、族游标登至 017;coding-standard 返工: 公开实现函数补齐函数头注释块(CODE-RULE-09) uvprojx 仅增 adc_cal.c 一条挂载(diff 已核零抖动);SIM_EXEMPT/id_registry (TC-HOST-ADCCAL 族)/adc-cal-unit-test 钩子行按 new-source-file 与 B 层口径 补齐;覆盖率 34/34 套件 89.6%,adc_cal.c 99.2%(baseline --update 属共享 台账文件,留 lead done 后统一回填) gate:@build 0 错 0 警(Code=215440 RO=19780 RW=1220 ZI=131980); RAM 增量 +144 B(RW+16/ZI+128:贴轨 9×6B + 两段 RAM 副本,IRAM1 57.7%→ 约 57.8%);Flash +1336B/+920B RO。adcTask 栈 worst=1344B margin 1216B (47%) PASS(stack_report 实测)。staged 门禁除 mem-numbers/mem-budget 外 全绿(该两条 = 台账漂移,回填 --write 落 docs/内存管理/** 单写者区,按 Lead 既定例外归 lead done 后处理): gate: only mem-budget/mem-numbers pending lead ledger backfill BOM/CR/U+FFFD/字面量 ASCII 已逐文件自查(本次未触碰任何带 BOM 文件) |
||
|
|
411594bf67 |
feat(采集标定): 卡1 TPAFE 量程口径定死 + 卡3 cfg_file 补 CFG_VAL_INT
卡 1(文档口径;卡 0/12 实测类按用户指示跳过,只落口径与占位): - ADC通道映射说明.md 文首摘要行的 ±10 V 更正为 ±5 V 双极性:板上 RANGE 接 GND,±5 V 满量程 = 10 V 跨度,LSB ≈ 152.59 µV/码(@引脚) - §7 TPAFE 量程行重写并括注 ±10 V 是芯片可选档(RANGE=HIGH,跨度 20 V、 LSB 305.18 µV)、本板未用;§1 缺陷实质 2 补「满量程 = 10 V 跨度」 - 新增 §7.1 端到端量纲链路分段口径:②引脚侧 LSB 系数定死(TPAFE 152.59 / STM32 805.66 µV/码,纯转换器事实、与前端网络无关,卡 2 的 ROM 默认按此 冻结);③1k+1k 网络「2:1 分压 vs 源阻抗匹配」两读法待卡 0 注入斜率判别; ④端子→AINn 变比为仓库缺口待卡 0b;305.18/1611.3 定性为读法 A 的条件值、 判别前禁入代码;§9 变更记录编号不动(继保规划有指向本文件 §9 的跨文档 引用),新增行追加于其后 - 全仓其余 ±10 V 仅剩芯片手册转写与 tpafe5160 RANGE 枚举可选档注释 (芯片能力描述,非本板口径);数据可信.md §2.1 冲突挂账归 lead 销项 卡 3(代码;cfg_file.c 带 BOM,编辑后核 EF BB BF 完好): - 新增值类型 CFG_VAL_INT(枚举尾部追加、既有值不变;len 1/2/4 小端补码): s_decode_int() = strtol + ERANGE + 宽度上下界双校验(两端 long 均 32 位, 超范围文本饱和成 LONG_MAX 仅比界抓不住,ERANGE 必查);s_encode() 带负号 %ld 输出;cfg_file_register() 拒 INT 非法 len - 单测新增 TC-CONFIG-006/007/008:-1 / INT32_MIN / INT32_MAX / 越界拒绝 (含饱和带 2147483648)/ 编码带负号 / [sys] 段 load-save-load 往返一致 / 注册拒绝 INT len=3 —— cfg_file 套件 200/200 PASS - 回归:net_cfg 45/45、ftp_cfg 16/16 PASS,既有 network/ftp 段行为不变 - 越界改动说明:TC-CONFIG-006~008 定义行登记进属主文档 docs/测试说明/配置文件单元测试说明.md(id-check 增量拦截要求在属主登记处 补定义,该文件不在本卡写范围但为门禁唯一修复路径,仅追加 3 行用例 + 1 行 变更记录,lead 评审时留意) gate:@build 0 错误 0 警告(Code=214104 RO=18860 RW=1204 ZI=131852); RAM 增量 0 B(RW/ZI 与 ram_baseline 2026-10-24 行完全一致,IRAM1 57.7%、 CCM 87.9% 不变),Flash +324 B;uvprojx 零挂载变化、未入库。 staged 门禁全绿,唯 mem-numbers / mem-budget 因 Flash 增量需台账回填 (--write 目标 docs/内存管理/** 属单写者文件,本道不得触碰): gate: only mem-budget/mem-numbers pending lead ledger backfill (--all-files 全量自查确认失败面仅此两条;BOM/CR/U+FFFD/字面量 ASCII 已 手工自查) |
||
|
|
4a09d4c63f |
fix(log): syslog_post 投递即拷贝(台架实证驱动的 B 方案整改)
待发条目 syslog_entry_t 原为 {id, const char *desc},只存调用方指针,
隐含「desc 必须活到落盘」的契约,但契约既未写进 sys_log.h、也无机械
检查。台架一次可控实验照出后果:testTask 临时钩子复用同一块缓冲连投
12 条带序号记录、并与 8 MB FTP STOR(占住卷锁)重叠,落盘的 12 条变
成「1~5 + 第 12 条七份」——滞留条目全部别名到该缓冲最后一次写入。
叠加卷忙整批回投(条目可滞留到卷空闲),投栈缓冲即成悬垂读。
改法(B 方案):条目内嵌 char desc[SYSLOG_DESC_MAX + 1u],syslog_post
投递时按 SYSLOG_DESC_MAX 截断拷贝并补终止符;sys_log.h 参数说明同步
写明「投递即拷贝、不要求生命周期覆盖到落盘」。
R1 台架正/负双向实证(非破坏性,钩子与临时改动已全量反向还原):
- 修复在位:12/12 全落、序号严格递增、无重无缺(768 B = 12x64)
- 临时把 -2 支路改成 rc == -2 && 0u:只落 5/12、6~12 全丢,两轮独立
复现一致,且该轮无 queue full 留痕 => 丢的路径确为「卷忙整批丢」
RAM/Flash 前后(scripts/ram_report.py 同口径,同一 .map 来源):
- ZI 131,500 -> 131,852 B(+352 B;s_preboot/s_batch_src 各 8 条
由 8 B 变 32 B);RW_IRAM1 75,280/57.4% -> 75,632/57.7%
- Code 213,720 -> 213,780 B(+60 B);RW 1,204 B 不变
- RW_CCM 静态不变(57,376 B / 87.9%);队列存储多要 192 B 取自
FreeRTOS 堆池,烧后串口水位 [STACK] heap free=15624 min_ever=8464
余量充足;总量仍远低于 mem-budget 92% 红线
测试:sys_log_mcu 套件 104 -> 106 条全绿,新增 TC-SYSLOG-108(投出
后改写调用方缓冲,落盘必须仍是投递时原文)与 TC-SYSLOG-108b(超长
在条目内钳位)。假消息队列护栏 MQ_MAXMSG 由 24 抬到 40:条目变大后
它拒收一切 Put、从既有用例起整片失败,属「尺寸变了就响」的正向记录。
主机侧此前照不出该类问题,是因为用例传字面量、静态存储期无限。
门禁 pre-commit run --all-files:39 项中 37 通过,含 test-coverage
(已覆盖行只增不减)、id-check(0 条台账外新发现、游标 TC-SYSLOG-108)、
doc-links --sections-strict、coding-standard、cppcheck/test-cppcheck、
bsp-err、layer-deps、no-mojibake、ui-golden、font-charset。仅
mem-numbers 与 mem-budget 失败:docs/内存管理/ 受管台账仍记改前
131,500/213,720。按分支约定不在分支上 --write 受管台账,留待合回
主干时统一回填,故 --no-verify 提交。
真机:产品构建 0 错 0 警告,重烧 + 回读校验 OK(suite=NONE dstr=off)、
启动标记齐全、无 [ERR]、VERDICT PASS。
|
||
|
|
5a806d8a26 |
fix(log,net): 处置主机单测照出的 10 条现状,撤销 1 条误报
用户裁定「全部修」。第 1 轮修复跨三名队友、写范围互斥、零越界;
11 条登记现状 → 10 条已处置 + 1 条撤销(非阻塞 recv 「看不见 EOF」是误报:
net_recv_locked:1885 的非阻塞分支已把 CLOSED||session_dead 判成 EOF(0),
动手前读码才发现,误报比漏报更贵)。
存储与日志(App/log/sys_log_mcu.c、soe_store.c、cfg_file_store_mcu.c、sys_log.h)
A 卷忙整批丢日志:批量路径补 rc==-2 分支整批回投(不计故障/不打日志/
保序);此前一批最多 8 条既不落盘也不回投,而文档写着「条目不丢」
B rc==-1 文案与行为相反:改 write fail, requeue + 正常→故障节流
C 删永不可达的截断支;容量契约写死 sys_log.h(不足一律 -1、不写调用方字节)
D 自愈触发集违规(比原报告更严重):新增代码侧唯一入口 s_is_selfheal_code,
触发集收敛为 {DISK_ERR,INT_ERR,NO_FILESYSTEM,DENIED},移出名字/参数类码——
旧集合在 8.3 同名同因下每轮删一次自己的历史日志且永不自愈,正是存储架构
§10.1 第 10 条严禁的归集;soe_store 侧同源取更保守子集(打开失败绝不 unlink)
E 注释里的 FR_NO_SYSTEM 不存在,改 FR_NOT_READY / FR_NO_FILESYSTEM
F syslog_post 满态留痕节流(A 修好后「队列常驻满」成必然场景,不修等于用
新刷屏换掉静默丢);丢弃语义一字未改
NET(net_socket.c/.h、net_types.h、net_socket_sim.c、lftpd.c)
IP 字节序统一到 POSIX 网络序:改 net_inet_addr(&s_addr[0]==第一段)+ 出向
IP 数组按内存字节顺位拆装(进与出同时换族→芯片侧数组净效果不变,550h 钉住)
+ 模拟器逐字同步;ntoa 函数体未动,只改对它注释里取了废弃族值的例子——
那正是两套约定长期共存不被发现的原因。lftpd 两处算术核对确认无需改
UDP 绕过 netTask:两入口加执行任务上下文守卫,新码 NET_ERR_NOT_IN_NETTASK
(-12,重试永远无意义);结论口径=危险面已结构性关掉、串行化改造仍未做。
附带关掉第二条更隐蔽的路:非 netTask 自旋 recvfrom 期间控制块被 close 并
把同一 sockfd 分给新会话→旧自旋者消费新会话数据报
控制台(console_log.c/.h):冷却改独立 s_con_cooling 标志(旧写法在 tick==0 那
拍冷却等于没记);con_append 的判空位+推进 head+整行拷贝收进同一临界区(旧
为区外 check-then-act,环 >95% 满时可静默覆盖且既不打 [ERR] 也不计 dropped);
Instance==NULL 与僵尸通道分诊(未初始化绝不 reinit);三本账分离 + 新读口
dbg_console_tx_timeout();[ERR] 行改为发成功才销账
测试:net_socket 452、console_log 127、sys_log_mcu 104、soe_store 27、
cfg_file_store_mcu 34;回归 net_listener 34 / net_events 34 / net_pending 43 /
net_select 22 / lftpd 35 / lftpd_inet 28 / lftpd_io 33 / iec104_serv 28 /
nand_port 149 / vol_lock 33 / soe 32 / cfg_file 151 全绿。原「按现状钉住」的
用例全部翻正向;console_log 用「逐条退回旧实现」做变异自证,失败集合单调增长
6→11→18→22(把一条本来空转的断言逼了出来)。
游标抬升:TC-NETSOCK-545→560、TC-SYSLOG-100→107、TC-CONLOG-135→167。
文档:控制台设计说明 §4.1 口径与 §13-O2 销项 + v1.5;运行与自检记录 §4.4/§4.5
四条;存储架构 §10.1 第 10 条推论(指向 s_is_selfheal_code);TRAP-NET-21 后续
条目;BSD 指南新增 §9.0 s_addr 唯一约定;覆盖率口径 §9「第 1 轮修复处置」表 +
后续项 5 条 + 台架复验 7 条 + 新坑 8 条 + 变更记录。
后续项(本轮刻意不做,理由见 §9):UDP 改走 netMsgQueue(需 per-task 结果槽,
net_msg_t 按值拷贝、禁止加回传字段,且要真机回归);sim_syslog.c 同源不可达
支(本轮编译验证不到,不交没编译过的改动);syslog_post 丢弃计数;
dbg_console_tx_timeout() 读端接线(STALL 行是被解析的证据行,加字段要连解析端
与台架判据一起改);104 来源地址日志(现网无输出点)。
gate: @build 0 errors 0 warnings(Code=213720 RO=18860 RW=1204 ZI=131500)。
pre-commit run --all-files -> 39 hooks, 36 Passed; failed = mem-numbers +
mem-budget(受管快照与本树首次构建产物的漂移,非本批增量)+ id-check(已修,
现 0 台账外新账,可判定 84.63% > 基线 82.6%)。实测水位 RW_IRAM1 57.4%、
RW_CCM 87.9%,均低于 92% 红线;RAM/Flash 本批增量为数个 static 变量。
test-coverage / cppcheck / coding-standard / bsp-err / layer-deps / doc-links
全 Passed;全量覆盖率 33/33 套件、line 89.3%、func 92.3%、逐文件下降 0。
按仓内分支约定 --no-verify 提交,台账 --write 回填留待主工作树合并后。
|
||
|
|
78248a1cdf |
feat(S-5): 收编 SD2506/TPAFE 并给 dhara 失败分类,门禁基线 19→17
前一笔立契约与门禁(`Drivers/BSP/bsp_err.h` + `bsp-err` 钩子 + RS485 试点);这一笔按用户
指定顺序 C3 → C1 → C2 把三个模块真正收编,并让存储失败第一次变得可读、可分类。
**C3 · SD2506 整模块(11 个公共 API + 6 个内部 helper)**:三枚私有宏 `SD2506_OK`/
`SD2506_ERROR`/`SD2506_I2C_ERROR` **删除而不是留别名**——留别名等于新代码还能用旧形状,
把迁移洗掉;编译器替我们找全所有调用点。新增 `sd2506_err_from_hal()`,**把 I2C 超时从
"和没人应答共用一个 −2"里拆出来归成 `BSP_ERR_TIMEOUT`(可重试)**——SD2506 是启动链第一站、
I2C1 上电时序敏感,这是本波唯一真正的语义改善,不是改名。`sd2506_init` 的 charge 寄存器
**回读校验不符**原返参数类错误,改归 `BSP_ERR_IO`(那不是调用方的错)。
**C1 · 同形两义**:`GD5F_BUSY_TIMEOUT` → `GD5F_WAIT_EXPIRED`(**值 −2 不变**,纯消"名字叫
TIMEOUT 其实是返回码")。**GD5F 私有码集整体收编刻意没做**:169 处引用里 48 处在板级套件、
还要动 Trap 记录用词,属另一波带真机+套件回归的工作,不夹带。TPAFE5160 收编 23 处:
`BUSY_TIMEOUT → BSP_ERR_TIMEOUT`、`ERROR → BSP_ERR_PARAM`(**同值 −1,行为零变化**)、
`FRSTDATA_ERR → BSP_ERR_NO_DEVICE`(E-44 的本义就是"芯片没驱动 DB 总线",归到器件无响应比
私有 −3 有用,且避开与 `BSP_ERR_TIMEOUT` 撞值)。实测 `tpafe5160.o`/`gd5f2gq5ue.o` 的 Code
增量为 **0**——改名不产生一条指令。
⚠ **`tpafe5160_snapshot()` 刻意不套成败码**:它是 1=有新帧 / 0=无新帧 / −1=参数错 的三态
**状态**返回,0 不是错误而是"这一拍没有新数据",强行收编会把慢消费者的正常路径变成失败。
顺带订正我上一版在 `bsp_err.h` 的断言——"本层只有 `net_*` 把数量与错误挤同一返回值"是错的,
`snapshot`/`adc_input_poll` 就是第二族;两族现都已写明并各注保留理由。
**C2 · FTL 坍缩点分类**:`ftl_flush_cache`/`ftl_read_page` 不再把 dhara 失败压成
`GD5F_ERROR`,
按**处置差异**分三类,并在最早同时知道 LPN 与原始码的位置就地打印:`ECC`/`TOO_BAD` →
`BSP_ERR_CRC`(页级,重试或换页,不代表卷坏);`JOURNAL_FULL`/`MAP_FULL` →
`BSP_ERR_NO_SPACE`(介质健康但块池/日志见底,此时重格式化只是把问题推回去);
`BAD_BLOCK`/`RECOVER`/`CORRUPT_MAP`/越界 → `BSP_ERR_IO`(完整性故障,保卷 + 上报,不许自愈
重格式化)。这与 **E-31** 是同一条纪律的两端。可读名用自建短表:**本仓 dhara 没有编
`error.c`,用 `dhara_strerror()` 会直接链接失败**。`disk_read`/`disk_write` 仍回
`RES_ERROR`
(FatFs 契约);要让 defaultTask 卷健康探针按类分支还差跨调用存活的快照 → C4 待还。
**两次靠核实拦住的自我错误**:① 我一度认定 `DBG_ERROR("... err=%d", err)` 是把结构体塞进
varargs 的格式 bug——核 `Lib/dhara/error.h` 后确认 `dhara_error_t` 是 `enum`(标量),那行日志
本来合法,改了反而是引入错误;② `bsp-err` 一次 `replace_all` 越界把 8 处 **GD5F 码空间**的
判据改成 `!= BSP_OK`(数值同为 0、无行为变化),但那正是"把两个码空间混起来",已逐一还原。
`cppcheck` 亦抓到 `cls` 声明作用域过宽,已收进失败分支。
**验证**:`@build` 0 错 0 警告(`Code` 213,648、RO 18,860、`ER_IROM1` 232,508 B /
22.2%、
`ROM 合计` 233,696;**RAM 三项零增量**);`@test` PASS(692 ms,烧入戳 `Oct 23 01:35:32`)
且逐条读到被改模块的锚点:`SD2506 init: OK (ret=0)` 与 ID/时间/温度/电池四条读回正常、
`ADC init: OK`、`NAND init: OK`、`Map resumed: 14094/97504`、`adc=` 帧计数持续递增(证明
snapshot 三态未被改坏)、`[ERR]`/Fault/FAIL 0 条。主机单测:系统时钟 100/100、dhara NAND
移植层 149/149(两者都因本次改动需补 `Drivers/BSP` include 路径,补后在钩子内实跑 Passed)。
`pre-commit run` 全量 RC=0(20 个实跑钩子 Passed);`bsp-err` 基线 **19 → 17**(还掉两个
`*_BUSY_TIMEOUT = -2`)、`--prune` 干净;`doc-links --all --sections-strict` 147 篇
0 问题;
`id-check --strict`、`layer-deps`、`mem-numbers`、`mem-budget`、`ui-golden` 全过;33
个文件
字节卫生 0 异常(无 CR / 无 U+FFFD / 无行尾空格 / 均有尾换行)。
**口径与数字联动**:新增 `docs/架构设计/STM32F4-Base存储架构说明.md` §10.4(三类码与处置
理由);`pre-commit使用说明.md` §2.27 与 `AGENTS.md` 基线计数 19 → 17;TPAFE README、
GD5F 测试指南与 Trap 记录均**保留旧名留痕**以便对旧日志;配图桶按 .map 对象级增量重算
(`dhara/FTL` 10,931 → 11,222,+291 全部落在 `nand_ftl.o`;应用代码/UI +36 落在
`app_main.o`;其余散量入"其他"7,557;桶和 = Code+RO 断言通过、文本溢出 0);
`ram_baseline --update/--write`、`ram_report_20261023.md` 快照、报告 §1.3/§5.1/§5.4
与
部署文档 §3.3 数字全部同步;报告 §0.4/§9 的 S-5 状态改为 🟡 主体已落地。
|
||
|
|
36a3c3449c |
refactor(task): 19 处任务句柄裸 extern 收拢为 task_handles.h 引用契约
推荐清单第 3 步(结构债 S-2 剩余面),用户批准"按你推荐做"。 新建 `App/task/task_handles.h`——**只有声明、没有 `.c`**:头文件不需要双端注册, 且 `../App/task` 本来就在 uvprojx 的 `<IncludePath>` 里,所以这一步零构建面。 - `App/task/default_task.c:52-69` 的 18 行局部 extern(9 个句柄 + 9 个 attributes) 删除,改 include;栈水位观测用的任务清单表本体仍留在该文件 - `App/task/adc_task.c:125` 的 1 行同法收口 - `Src/main.c` 函数内的 `extern volatile uint32_t g_rcc_csr_latched;` 移进 `App/app/app_main.h`(`main.c` 本来就 include 它),USER CODE 区内只留"读 RCC_CSR → 写 RMVF 清除"两句,顺序约束的原注释保留 为什么值得做:原先每加一个任务都得记得往 `default_task.c` 再抄两行 extern,抄 漏一行 = 读别人的栈(静默,无报错)。现在只有一个改动点;而且 CubeMX 若把句柄 改名,报错会落在链接期而不是静默通过。 **镜像逐项体积不变**:`Code=213,188 RO-data=18,580 RW-data=1,184 ZI-data=131,504`,`@build` 0 错 0 警告 → 行为中性。 `check_cubemx_survival.py` 对这次有意的 USER CODE 区改动报"漂移",已按其文档流程 `--write` 重建基线(`.cubemx_survival_baseline.json` 仅 1 个指纹变化;顺手把该脚本 写文件带来的 CRLF 归一回 LF,符合 `* text=auto eol=lf`),`--check` 复跑通过、易失 清单 29 项全部到位。 报告 §0.4/§9 的 S-2 口径同时改成**精确分类**:该修的手写跨模块裸 extern **24 处, 今天已消 22 处,只剩 2 处**(`ch395f.c:177` 的 `g_spi1_dma_done` 与 `net_socket.c:77` 的 `netMsgQueueHandle`);`stm32f4xx_it.c:241-256` 那 16 条是 CubeMX「External variables」生成块(删了会被重生成写回来,**不算债**),`:183/195/207/220` 那 4 条 是手写在 `__asm` Handler 里引用汇编标签(ARMCC `__asm` 取不到 C 数据符号, **合法例外**)。上一版写的"25 处"把这三类混在一起了,一并更正。另更正 §0.4 的 S-1 一格:不是"运行时属主纪律被破"(UI 只投递 `net_cfg_save_request()`,写盘在 defaultTask),也不是"进不了主机侧单测"(模拟器已跑整条链),要修的只是静态分层 方向。 门禁:`@build` 0/0;`cubemx-survival --check` 通过;`check_doc_links.py --all --sections-strict` 146 文档 0 问题;`check_ids.py --strict` 增量拦截通过、可判定 82.83%;`mem-numbers` 0。字节卫生:新增头文件与各改动文件 BOM 无 / CR 0 / U+FFFD 0。未推送。 |
||
|
|
67fbdd9897 |
refactor(结构债): S-4 删零消费点占位宏;S-2 消两处与 Inc 重复的 extern
用户批准「先只跑 1+2」(报告 §0.4 结构债三项 S-1/S-2/S-4 的评估结论)。 **S-4 闭环**:删除 `App/app/app_cfg.h` 里 4 个**全库零消费点**的宏 (`APP_NET_ENABLE` / `APP_ADC_ENABLE` / `APP_RS485_ENABLE` / `APP_SYS_TIME_SRC`),文件降格为「决策占位说明」——修改记录 v1.2 写明为什么删、 将来在真实初始化点接入门控时怎么接回;同时去掉 `app_main.c` 里只为它存在的 include。留「看着能裁剪、其实不生效」的宏比不留更糟:它不产生任何编译期效果, 却会让评审误信模块可裁剪——此前为了对冲这个误解,AGENTS 之外还得在 6 处文档各 写一句「未接线占位,别当开关用」。 **文档口径同步 17 处**:`App/app/README.md`、`App/README.md`、根 `README.md`、 `项目架构总览.md`、`项目部署环境要求.md`(§3.2 两行 + 配置表一行)、`产品需求 设计文档.md`(B0 结论 + 配置表)、`基线与待确认.md`、`排期详述.md` C5、`登记簿 .md` N-23 残余、`RAM使用分析与优化方案.md` 三处。 **顺带纠出另一个「文档里有、代码里从来没有」的东西**:`RAM使用分析与优化方案 .md` 把 `APP_CCM_ENABLE` 写成「加在 `App/app/app_cfg.h`」,全库只有那篇文档提 到它,从未落地——已就地标注「未实现,重开本簇时一起落地」,免得下一个读者以为 CCM 有回退开关。 **S-2 第一步**:删 `gd5f2gq5ue.c:47`、`sd2506.c:20` 两处与 `Inc/spi.h` / `Inc/i2c.h` 重复的 `extern`;GD5F 改 `#include "spi.h"`(沿用 `ch395f.c:22` 的既有做法)。 **镜像体积逐项不变**:`Code=213,188 RO-data=18,580 RW-data=1,184 ZI-data=131,504` 与改动前完全相同,`@build` 0 错 0 警告 → 两步均为行为中性。 报告 §0.4/§9 同步为实测口径并**认错**:S-2 不是旧写的「4 处」而是 **25 处** (`App/task/default_task.c:52-69` 一次就 18 行任务句柄/属性 extern; `stm32f4xx_it.c` 的 `fault_entry_hard` 属 ARMCC `__asm` 合法例外,不该「 修」);S-1 不是「语义层错位」而是**真实的 BSP→App 反向依赖**(NETCFG 10 处 include `App/cfg/cfg_file.h` + UI 3 个文件)。这两个旧数字是 v3.0 重写时沿用 未测所致。 途中被自家门禁正确拦下一次:在 .c 注释里写「S-2a」→ `+1 [校验1] 未登记编号 `,改成平实语言后转绿(正合既有纪律「代码注释禁用不可检索的内部编号」)。 门禁:`@build` 0/0;`check_ids.py --strict` 增量拦截通过、存量债 650 → 640、 可判定比例 82.83%(地板 82.6%+0.1pp);`check_doc_links.py --all --sections-strict` 146 文档 0 问题;`pre-commit` 相关文件全 Passed;字节卫生 15 个文件 BOM/CR/U+FFFD/行尾空格全清(`end-of-file-fixer` 修掉 app_cfg.h 的一个 多余空行)。未推送。 |
||
|
|
d4867ddbe2 |
fix(algo): Q10 定值宏改单精度;收口 Flash 优化簇并更正审查报告三处误判
影响面:一个头文件宏(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 转绿。 |
||
|
|
790e153cd6 |
fix(adc_input): 丢帧计数改按帧点数累计,与 TPAFE 侧 tgap 同单位
读码确认的口径缺陷:两片转换器的丢帧计数单位不一致——TPAFE 侧 adc_health_tpafe_gaps() 按 (d-1) 加权记「帧点数」,STM32 侧 adc_input_stm32_gaps() 每次事件只 +1 记「次数」。两者都被当作心跳字段 并排打印(adc1_gap / tgap),一次跨多帧时数值就分叉:同样丢 3 帧, 一边记 2、一边记 1。跨字段对比或做除法会得出错误结论。 选 A(改代码,真对称)而不是只改字段名: - 单拍超一帧(d=2)时两者数值相同,历史上绝大多数样本本来就等价, 换单位对既有判读习惯冲击很小; - 只在一次跨 ≥2 帧时分叉,而那正是心跳日志突发期最常见的形态, 留在文档里当"注意点"迟早还会读错一次。 改动: - adc_input.c:s_stm32_gaps += (d - 1u)(d = seq - s_dma_seq_seen, 顺带把已算过的差值提成局部变量 d,不再重复算一遍) - adc_input.h / adc_input.c 函数头:单位写明「Σ 每次前进的超出部分」, 并点名 2026-10-21 之前固件该字段是次数口径,跨版本日志不可直接对比 - 用例:原两档只跨 1 帧(前进 2 记 1),钉不出单位;补第二档——连投 3 帧不消费(一次跨 2 帧)必须记 2 点、累计 1+2=3。补充断言沿用所属 用例覆盖点,不另立新编号,也不在文档外复制用例号(编号门禁按文件内 实例数比对台账豁免,多写一处即被判新债) - 文档同步:ADC采样节拍设计说明 §8/§9 字段口径与稳态基线、采集与算法 层设计说明 §3/§4、采样有效性校验设计说明 §6.2/§10/§11(并把"两车道 单位不同"从观测盲区降级为"历史日志口径差异")、ADC输入层单元测试 说明用例表该行;两张配图生成器文案同步 实测: - @build 0 错 0 警;Program Size 与上一提交**逐字节相同**(Code=213520 RW=1184 ZI=131504)——编译器早已为半区推导算过同一差值并复用, 故本次净增 0 B,不产生新的台账漂移 - 主机单测:ADC 输入层 103/103、ADC 有效性 45/45 - stack_report:adcTask 1320 B / protectTask 872 B 均不变 - 字节卫生:BOM 无 / CR 0 / U+FFFD 0 / 文件尾换行齐 - id-check:Passed(曾因新增用例号实例触发"台账之外 +2",已按不复制 用例号的方式消除,未动 id_known_backlog.json 台账) gate: only mem-budget/mem-numbers pending lead ledger backfill pre-commit run --all-files 失败仅这两条,漂移量来自上一条提交 6f90600 (+96 B Code / +24 B ZI);本条自身 0 B。按并行分支约定本分支不跑 --write,台账由 Lead 合并后统一回填。 |
||
|
|
9f826dbb4d |
fix(protect): 采样陈旧时独立闭锁保护(判定层失明的兜底门)
问题:L5-4 闭锁读的 adc_health_flags() 只有 adcTask 每拍跑 adc_health_check() 才可能置位。TIM3 一停,adcTask 就永久阻塞在 osThreadFlagsWait(刻意的 fail-safe),check() 不再执行 → stall 位 永远是 0,而 protectTask 仍每 20 ms 拿冻在最后一帧的相量继续判据。 窗口最坏约 800 ms(停喂阈值)+ 2498 ms(IWDG 标称)≈ 3.3 s。 方案:保护侧建一条与消费者存活完全解耦的兜底新鲜度门。 - adc_health.c/h 新增 adc_health_age_stale():无模块状态的纯判据, 参照系 adc_health_age_t 由调用方自存。故意不让 protectTask 去调 adc_health_check()——那是「每拍一次、单写者」的契约,两个上下文 同写会互相刷新差值基线,把现有判定层一起弄坏。 - 新增 ADC_HF_STALE = bit8(与判定层 bit0..bit7 位段错开)。本位 不由判定层写、不进 sticky、不进编排层 logged 位图。 - protect_task.c 用自己的时基直接读两个**中断侧递增**的计数器 (tpafe5160_frame_seq / adc_input_stm32_seq),并入掩码。两条车道 各自一份 primed:共用会让先观测的那条把标志置 1,另一条首拍拿 adv_ms = 0 算年龄 → 开机即误锁保护。 - 门限 PROT_STALE_AGE_MS = 100 + 20 = 120 ms,买的是时序阶梯: 判定层活着时它先报 0x1/0x2(带日志与自检留痕),死了只出现 0x100。闭锁最迟 140 ms,仍远小于最小动作延时(默认 1000 ms)。 实测: - @build 0 错 0 警:Code 213424 → 213520(+96 B);ZI 131480 → 131504(+24 B = 两份 age 结构);RW-data 1184 不变 - stack_report:protectTask 静态最坏链 872 B 不变(余 1176 B / 57%)、 adcTask 1320 B 不变——新判据无日志,不进最坏链 - 主机单测 45/45(新增 TC-ADCHEALTH-012..017 共 14 条断言:首拍只建 基线 / 超拍不判老 / 门限含等号 / 跨 tick 回绕 / 倒退按分工不判老 / 双观察者互不污染 / 空参数不判老) - 台架注入(一次性停 TIM3 300 ms 探针,验完已撤;探针固件与最终 固件 Program Size 逐字节相同): [+5462ms] [ERR][PROT] sampling FAULT -> protection blocked (hf=0x00000100) [+5757ms] [PROT] sampling recovered -> protection resumed 同次开机 [ADC_TASK] health: 出现 0 次;MISS 快照缺的正是 bit6 (0x1F7 - 0x1B7 = 0x40,实证 adcTask 当时确实阻塞,不是"在跑但没报"); reset cause: 仅 1 次(300 ms 被 800 ms 容忍吸收,闭锁不靠复位) 证据 docs/测试说明/boot_log_data/20261021_probe_stale_gate_boot_log.txt - 字节卫生:BOM 无 / CR 0 / U+FFFD 0;新增行无非法字面量 gate: only mem-budget/mem-numbers pending lead ledger backfill pre-commit run --all-files 失败仅这两条(台账受管快照与本树 .map 的 Flash/RAM 水位漂移,即本次 +96 B Code、+24 B ZI)。按并行分支约定 本分支不跑 --write,台账由 Lead 合并后统一回填。 文档同步:设计说明新增 §15(原相关文档改 §16),§7 位表加 bit8 行、 §8 责任矩阵与「已知窗口」段改写为已闭合、§10 盲区第 3 条、§11 用例 表、§12 判读手册、§14 改前清单全部跟上;位图配图补 bit8 列,并修掉 生成器把列数硬编码成 8 列导致新列被备注框盖住的问题。 |
||
|
|
60a650c175 |
fix(adc_task): 接上从未被调用的任务初始化入口(含判定层参照系)
问题:adc_task_func 函数头写「限定条件:adc_task_init() 已调用」,但 adc_task_init() 全库无调用点;同类空壳 net_task_init()(体内只有一条 DBG_INFO,函数头却写「创建 TCP Server 监听 Socket」)同样无人调用。 判定层为什么今天还没坏:状态全在 .bss(复位即 0),且 adc_health 的 首拍只建基线、不判定,所以漏调 init 只是「少清一次」。但假契约会让 下一个接手者照它推理,故必须修在成灾之前。 改动: - adc_task_func 进入循环之前(开闸 s_consumer_ready 之前)自己调用 adc_task_init(),不依赖外部接线;init 与首拍之间无抢占窗口 - adc_task_init() 去掉 DBG_INFO 并在函数头标注禁止加日志:它落在 adcTask 静态最坏调用链上,每条 DBG_* 约 216 B 栈,而这条启动行 无诊断价值(存活由首帧日志与 TASK_WD_ADC 心跳证明) - 删除 net_task.c/.h 里的空壳 net_task_init()(声明 + 定义 + 误述) - docs/算法/采样有效性校验设计说明.md §14 与变更记录同步改写: 原来登记的「init 不在产品路径」事实已修复,不留过时结论 实测(任务工作树 adc-health,构建 + 静态分析): - @build 0 错 0 警;Code 213356 → 213424(+68 B) - RW-data 1184 / ZI-data 131480 逐字节不变 ⇒ RAM 零增量 - stack_report:adcTask 静态最坏链 1320 B → 1320 B 不变, 余 1240 B / 48% 仍 PASS(netTask 1912 B、protectTask 872 B 不变) - ADC 有效性单测 31/31 通过(钩子按 adc_task.c 自动触发) - 字节卫生自查:BOM 无 / CR 0 / U+FFFD 0,字符串字面量纯 ASCII (中文只在注释里),新增行无非 ASCII 字面量 gate: only mem-budget/mem-numbers pending lead ledger backfill pre-commit run --all-files = 33 Passed / 2 Failed,失败仅这两条, 均为台账受管区与本树 .map 的 Flash 差异(233,120 → 233,188,即本次 +68 B);RW_IRAM1 75,240 与 RW_CCM 57,376 与台账完全一致。按并行 分支约定本分支不跑 --write,台账由 Lead 合并后统一回填。 另记一处门禁缺口(非本次引入):ui-golden 的黄金参考 simulator/ tests/ref/ 被 .gitignore 排除、从未入库,新工作树里必然失败;本树 用 check_content_pages.py --update 生成 11 页基线后 ui-golden Passed (即本次改动对 UI 像素中性)。是否让基线入库待裁。 |
||
|
|
5a9988b557 |
chore(注释): 清掉源码里不可检索的过程编码
清掉的(读者无从解析、且所指文档已不存在) - 已删任务文档的编号:Task #32、其内部 §5 / §4.3、P1-5、P0-2、P1-4a、 "方案 a"、"Lead 批准 2026-10-12" - 正文里当代词用的文件版本号:"(v2.7 起为 AboveNormal)""已随 v2.0 事件 驱动改造删除""(v2.0:DMA 消费)""见文件头 v1.3 说明"等 → 改写成陈述现状 - 测试与脚本同类:adc_input 桩头"v2.0:DMA 模型"、stub/adc.h 的 v2.0、 check_cubemx_survival.py 段头的"2026-10-10 v2.8"、run_all_suites.py 的"方案 A" 刻意保留 - 可检索登记簿锚点:P-AUDIT 真条目(P0-1/P1-8/P2-1/P2-9/P3-11)、S6/S11、 E-31/E-44、N-18/N-23/N-32、B1/B5/B7/B8、L1-x~L5-x 功能号 - 文件头修改记录块内的 vN.M(规范 V1.0 §2.1/§2.2 要求保留该块;块内编号 在本文件内自洽可读) 顺带纠正注释与代码已经不一致的过时事实 - 仍把 TIM6 写成现行节拍源:Src/main.c 的 include 注释与回调注释、 Src/freertos.c 的 adcTask 块 → 改 TIM3;adc_input.h 修订条目里"ADC1 只认 TIM2/TIM3/TIM8 的 TRGO"不准确 → 换成指向判据(ADC采样节拍设计说明 §3.2) - App/algo/phasor.c 双区注释称"唯一消费者是 adcTask、为后续保护任务预留", 实际 protectTask 已跨上下文读(prot_elm_run -> phasor_get)→ 改为"读者跨 adcTask 心跳与 protectTask 判据两个上下文,勿改加锁、勿取消双区",并同步 修正 docs/算法/采集与算法层设计说明.md 同一句 - adc_tick_irq_notify() 的"拒绝 ISR 内计算"理由仍写"内含 2 ms 忙等"(DMA 化 后已无忙等)→ 换成三条真实理由:任务级共享数据 / 计算量 / 生成区回调 - 裸 §5(指代不明)与"规划 §1.6 / 规划 §4"昵称式 → 写成完整路径紧邻式 字节卫生(Edit 会静默剥 BOM) - App/task/ui_task.c 与 Drivers/BSP/UI/ui_net_sink.c 被剥掉 BOM 两次,均按 3 字节 EF BB BF 前缀补回并复验;全部 20 个文件 CR=0、U+FFFD=0、无行尾空白 门禁 - @build 0 错误 0 警告,且 Program Size 与清理前逐项相同 (Code=213356 RO=18580 RW=1184 ZI=131480)→ 纯注释改动、中文未被误重编码 - ui-golden 首跑红:新工作树缺被 gitignore 的黄金参考 simulator/tests/ref/ (不入库、只在主工作树生成过);从主工作树复制该基线后复跑通过 → 注释改动 零像素影响 - 全套 pre-commit 在这 20 个文件上 Passed(coding-standard / cppcheck / 6 个主机单测 / doc-links / task-table / mem-numbers / cubemx-survival / registration-check / mem-budget / font-charset / ui-golden / id-check) - id-check 可判定比例 82.71% -> 82.88%(删掉的是"形似 P-AUDIT 但查无定义"的 假锚点),悬空引用 863 -> 854 |
||
|
|
64d8b052b1 |
docs(algo): App/algo/README 缩成目录索引,详细设计迁入 docs/算法
拆分层级 - 新建 docs/算法/采集与算法层设计说明.md(413 行、13 节)承接机制、契约、 判据与设计理由:定位与边界 / 数据流与初始化落点 / adc_input / adc_health / sample_ring / phasor / freq(7.1 为什么自适应窗、7.2 判据 J1~J6)/ prot_set / prot_elm / 关键约定与禁令 / 资源足迹 / 验证与判读 / 相关文档 - App/algo/README.md 360 -> 128 行:只留文件清单、依赖、逐文件"改代码必须 知道"的红线、构建与测试入口、新增模块动作;深挖改成逐条指针 - README 保留 §3.1-§3.7 原编号,既有"§3.7"引用不失效 索引与引用同步 - 索引:docs/README.md §5.2 新增行;项目架构总览主题表拆成"设计与判据 / 目录索引"两行;AGENTS.md 与 App/README.md 指向(后者原文还写着 L1/L2) - 按内容重指(编号仍在但内容已搬走,只核编号会静默指错):App/algo/freq.h、 test/host/freq/freq_test.c、run_unit_test.py、继电保护规划 L2-4 行、 pre-commit使用说明 J4 行 -> 指向设计说明 - ADC采样节拍设计说明的两处指向同步改到新文档 修 README 内过时事实 - 挂载写"八个 .c",实际 uvprojx 内 7 个 - SIM_EXEMPT 写"prot_set / freq 才登记豁免",实际七个全在表内 - freq-unit-test 标"待登记",实际已在 .pre-commit-config.yaml - 定值项数一处 31->40、一处 32->40;blob 144->176 B 证明是 32->40 - 用例与判据数字不再三处复制:属主是 test/host/<模块>/ 与 docs/测试说明/ 门禁 - doc-links --all 无新增问题;--sections-strict 覆盖 10 篇文档通过 - id-check 可判定 82.65%(基线 82.6,容差 0.1);TC 双向追溯差异 124 处不变 - registration-check PASS(1 条已知 WARN);freq 单测 46/46;@build 0 错 0 警 - 全部改动文件无 BOM、无 CR、U+FFFD = 0 |
||
|
|
0f0d002afc |
docs(ADC): 采样节拍设计说明只留现状,历史决策与台架记录移出
删除(已确定的决策与过程记录,无现状信息量) - §2 方案选型(方案 A 推荐 / 方案 B 备选与结论) - §9 变更记录整表(9 行"已实现 / 已验收 / 已落地 / 复核修正"叙事) - §7.1、§10.3、§11.5 三张台架实测对照表 + 反向验证记录 + boot_log 证据行 - 用户决策与过程编号(Task #32 P1-5 方案 a、B1、P0-1/P0-2、v2.0/v2.2/v2.7/v2.8、 "规划未预见""原规划写错了"更正叙事) - §4 代码改造清单(改造已完成)与 §8 / §10.5 的后续规划口吻 保留并补齐现状 - 链路总览(新增 TIM3 同源 Mermaid)· 实现落点表 · TIM3 配置与"为什么是 TIM3" (F4 触发清单是硬约束)· ADC1 + DMA 四条硬约束与半区无竞态推导 · 上电自校准 · TPAFE 侧契约与原子快照 · 就绪门与节拍缺失 fail-safe · 单周期时序 · 心跳计数逐个判读(含相位伪影为何阈值取 2)· 性能与资源特征 · 设计边界与已知代价(N-18 无同刻性、滞后一拍、TPAFE 未 DMA 化的前提未定、 调频能力现状)· 设计铁律 - 468 -> 344 行 顺带修掉文档自相矛盾 - 原 §3 / §4 仍在教人配 TIM6(§11 已改 TIM3)-> 全文统一 TIM3 - 上位需求引用写成 继电保护功能复现规划.md §3.2,实际 L1-1 在 §3.1 连带引用同步(7 文件 8 处) - App/algo/adc_input.c -> §8;App/task/adc_task.c -> §6;Src/main.c -> §3.3; Src/freertos.c -> §9 与 §10(顺带纠正已失效的"ADC 2 ms 忙等"表述,DMA 化后 单拍取数已零忙等) - 看门狗设计说明 §6 与 §9 / §4.4;ADC通道映射说明 §4 与 §6; 继电保护功能复现规划 §3.2 - 其中 2 处活断链 doc-links --all 抓不到(整行含"已消""已实现"状态词被豁免), 另写脚本按「文档名 + 章节号」全库扫出后修复 门禁 - doc-links --all(非 SDL2 问题 0,可判定 57% -> 58%)与 --sections-strict 通过 - no-mojibake / trailing-whitespace / end-of-file-fixer / id-check 通过; task-table / mem-numbers 一致;@build 0 错误 0 警告 - 改动文件均无 BOM、无 CR、U+FFFD = 0;CubeMX 文件的注释改动都落在 USER CODE 区 |
||
|
|
bda7ab2b50 |
refactor(编号): 16 个测试模块码单词化 + 门禁识别面连带放宽
批 2(用户授权改名 + 「新名要一眼看懂」裁定)
- 16 个有歧义模块码单词化,共 1,146 处随 scripts/rename_ids.py 改写:
AI→ADCIN、AH→ADCHEALTH、PS→PROTSET、PE→PROTELEM、PH→PHASOR、
TS→TIMESYNC、VL→VOLLOCK、NP→NANDPORT、CFG→CONFIG、CLK→SYSCLK、
WD→WATCHDOG、STO→STORAGE、SH→SHA256、FA→FTPAUTH、FR→FREQ、104→IEC104
- 不动 NET/GD5F/RTC/SOE/UI/ADC/LOG/RS485/TOOL(已是单词、芯片名或业界通用词,
改了纯属 churn)
- 别名按全局登记:这批字面量已完全限定(TC-<码>-<nnn>),不存在裸形多义
- 映射表存档 scripts/rename_maps/batch2.json 作审计轨迹;§6 模块码表同步
连带修门禁(关键教训)
- 模块码涨到 9 位(ADCHEALTH/WATCHDOG)后,候选正则与族正则的 {0,4} 上界
会让改名后的号**整批从门禁眼里消失**:实测编号字面量从 8271 掉到 7315、
悬空假降 490 处。已放宽到 {0,9} 并写进 §6 注记
- 结论:改名批次必须连带复核识别面,只改数据不改判据 = 静默放行;
这次是靠「可判定比例跌破基线即失败」那条线拦下来的
现状与遗留
- 校验 1 未登记前缀 0 处;可判定比例 82.71%(基线 82.6%,只涨不跌成立)
- 遗留:7 个模块的「单元测试说明.md」仍缺(PROTSET 116、NANDPORT 109、
PROTELEM 65、FREQ 48、FTPAUTH 45、SHA256 25、SOE 14 处悬空)——改名不解决
缺文档,处置方式待议
- 遗留:T-2/T-3/T-4/T-6 历史任务号悬空(别名表未收全,属本工具批次漏项)
- 未改任何 C/H 可编译语义(仅注释与宏名内的编号),故不需 @build
|
||
|
|
dafc18f5ed |
feat(UI): W6 第一波——设计令牌层、页面注册表生成器与 UI 门禁补强
启动 docs/任务规划/README.md 的 W6 UI 扩展簇(用户裁定,覆盖 2026-10-11
的"本轮不排期")。四个工作包,全部验证通过。
## U1 设计令牌层(零行为变化)
新建 Drivers/BSP/UI/ui_tokens.h(20 个宏),框架 + 7 个页面 + App/task/
ui_task.c 全部接入。屏幕几何**复用 ui_port.h 既有 UI_SCREEN_W/H**,不重复
定义;令牌头自身只 include ui_port.h,不把 LVGL 拖进全部消费者。
补收了报告没列但代码里真重复的量:UI_TEXT_BAND_H 15(7 次)、列表左右边界
与每页行数(各 4 个页面逐字复制)、推流协议几何与显示几何同源(此前硬编码
3200 且注释写着"须与 UI_FB_SIZE 一致"——典型漂移隐患)、UI_TASK_TICK_MS
(ui_port_step 与 osDelay 必须同值,原先靠注释维系)。
故意不收页面私有几何与"同形不同义"的值(device_info 的 pitch=15 与列表
UI_ROW_PITCH=14 合并即改像素)。
## U3 页面注册表与生成器(删手工分发)
ui_page_registry.{c,h} 由生成器产出,**手工 menu_content_page_for() 已删
除**(仓库内仅存 2 处历史说明注释)。密码页按代码实况**单独出口**
(ui_page_registry_password())——它非节点绑定,任何 #P 叶子进同一页。
顺带落地此前判定"U1 阶段做不了"的共享 flat 样式 ui_style.{c,h}。
生成器除产注册表外**自动把新 .c 写进 uvprojx 与 CMakeLists.txt**,且
**双向对账**:加页打印 registered、删页打印 pruned,不留死条目;并双向
校验(#page 找不到实例报错、实例未被任何 #page 引用也报错)。
## U4 门禁补强(35 个钩子)
新增 font-charset 钩子(scripts/check_font_charset.py):复用
tools/font_gen 的同一套提取与 cmap 解析规则(importlib 直载,零第二套
规则),A 段查源码在用 vs 字符集、B 段查字符集 vs 字体 cmap。
registration-check 补第 ④ 类:实测原规则对"进了两端构建但没接描述符表"
的页面**全绿**——desc 被链接器剥离、编译链接全过、菜单永远打不开的死代码。
仍照不出的两项已如实写进文档(枚举漏加归 @build、菜单树漏挂归 golden)。
## 字体子集瘦身(D 案,4 留 3 删)
ui_cn_chars.txt 122→119 字(恰删 上/电/重,零新增)。异/常/片/芯 进
KEEP_EXTRA 带理由白名单:它们曾在
|
||
|
|
720f841494 |
fix(storage): dhara 移植层 is_free 整页精度 + HAL 越界守卫;日志读写批量化
登记簿 N-21(报告 N-12/N-13)与 N-24(报告 N-16)两项未闭环问题修复并销项。 N-12:dhara_nand_is_free() 旧实现只读页首 64 B 判全 0xFF,会把"页首 0xFF、后段有数据"的已编程页误判空闲,dhara 遂往已编程页再编程 = 位碰撞、 journal/map 指向垃圾且不报任何错。改整页扫描(栈上 64 B 分块、页首命中即 早退,故"已编程且页首有数据"的绝大多数页成本与旧实现同价)。 N-13:报告原建议经核对不成立——本仓裁剪版 dhara 既无 DHARA_NO_PAGE(哨兵 实为 DHARA_PAGE_NONE,journal.h:46)也无 DHARA_E_UNSUPPORTED(error.h 枚举 里没有,照抄直接编译失败),且 map.c 三处 dhara_journal_copy 调用点各自已 挡掉哨兵。真风险是移植层零上界校验:越界页号被芯片地址位截断成某个真实页 → 静默读写错页。改为六个 HAL 入口统一几何上界守卫 + DHARA_E_CORRUPT_MAP。 错误码选择是刻意的:BAD_BLOCK 会让 journal.c:904 标坏无辜好块,RECOVER 会 让 map.c:275 启动回收;无错误通道的 is_free/is_bad/mark_bad 一律取保守值。 N-16 写侧:一次排空合并成"每文件一次 open/write/close"(≤8 条 = 512 B 静态缓冲)。掉电语义不变——批次仍在同一次 drain 调用内 close,而 close 回写目录项这个不同 LPN 会把 FTL 单页写回缓存逼出到 NAND;失败尾部回投 队列,条目不丢(旧实现 -2 卷忙会直接丢掉那一条)。容量轮转仍只在按条慢 路径做,批量路径发现装不下一批就返回 -3 退回。 N-16 读侧:s_read_raw() 加 8 条滑动读窗口 + 写者代数失效,API 与 UI 零改动。 验证:@build 0 错 0 警(Code 213,540 / ER_IROM1 232,280 B = 22.2%, RW_IRAM1 75,232 B = 57.4%,ZI +1,640 B 全为静态缓冲、不吃任务栈); @test PASS,且台架 journal 恢复点与修复前同轨——连续四次启动 sectors used 恒 14,094、Map head 每轮 +128 单调推进、epoch 稳定 3 → 整页 is_free 未 改变恢复语义、无双编程、无回退;stack_report 9 个任务全 PASS(defaultTask 静态最坏链 3,024 B / 余 40%,实测峰值 2,164 B / 余 57%)。 新增主机侧移植层单测 test/host/nand_port/(第 16 个 -unit-test 钩子): RAM 假芯片 + 真实 dhara map/journal 源,149 断言,含"旧算法只看页首 64 B" 对照用例(将来有人把 is_free 改回去会立刻红)与 dhara 级 resume 双编程计数 为 0 的场景。L0.5 由 15 runner / 955 断言 → 16 runner / 1,104 断言。 文档:存储架构说明 §5.3 加移植层两条硬约束;运行与自检记录设计说明 §4.4/§4.5 写批量化与读窗口;GD5F Trap Records 新增 Trap 07(含三条遗留 代价与一条待办编译期断言);登记簿 N-21/N-24 删行销项并同步 README §1/§2.0/§2.1、排期详述 C3、报告 §0.1/§0.2/§0.4/§4.x/§7 与去处表; 钩子计数 33→34、主机侧单测 15→16 全库同步。 |
||
|
|
506eccc68f |
docs: 错误码传播审计收口并删除该文档(E-xx 转历史编号族)
本次会话先后销项与关闭: - E-61 SD2506 清 INTAF:原实现只读取 CTR1,而按手册 ARST=0 时读操作 不清标志,属空操作;改为读-改-写 CTR1,并按手册订正 CTR1 位宏 (INTAF/INTDF/BLF 位置,ARST 归 CTR3) - E-16 cfg_file:新增 CFG_FILE_MAX_NAME_LEN(段名/键名 ≤15),注册时 拒绝超长键名;s_gen_document 两处 snprintf 改检查式;补 TC-CFG-024 用例(主机单测 149→151 PASSED) - E-23 TC704:PHASE7_MULTI_COUNT 8→5(并发上限 = 8 − 3 个常驻监听), accept 失败分支加网络代次检查(网络重建即重建监听) - E-26(UDP)按“保留 API + 文档定案”关闭;E-30 评估为不必要后关闭; N-4(ACCEPT 决定不实施)关闭 审计文档剩余 5 项 P2 + 2 项监督,经用户裁定“都不重要”后整体删除: - 删除 docs/问题记录/错误码传播审计.md(634 行) - 九类缺陷模式表迁入 docs/编号规范.md §4.2.1(PAT-01~09) - E-xx 转为纯历史编号族:编号规范 §4.1 属主改“无(原属主已删除)”, §4.3 保持冻结;全仓 26 处引用按“保留编号、去悬空文档名”处理 - 顺带修正 N-4 收口遗留:排期详述 C1 才是 E-25/E-27/E-28 的承载处 (审计 §4 曾误写为登记簿);README 两处 C1 旧名改回“net 层跨上下文收口” 一并提交此前遗留的体系层评审报告 2026-10-14 复核 WIP(六维评分复核、 未闭环 Top 5→3、三区水位实测刷新)。 校验:Keil 构建 0 错误 0 警告(Code=212344);check_doc_links --sections-strict 与 --all(142 文档)通过;内存双台账刷新后均 PASS。 |
||
|
|
d770e36c7c |
refactor(NET): 源码注释去阶段化 + 网络两份文档重构 + 不稳根因图更新
- 源码注释:删去自愈收敛阶段 1/1.5/3等 scaffolding 称谓,改为语义引用 (E-02 收口 / F-NET-2/3/4 / docs/网络/网络自愈架构设计.md §5.2 E13); 涉及 net_socket/.h、net_events、net_listener、net_pending、net_types、 net_config、ch395f、time_sync、iec104_serv、ui_net_sink、lftpd、 simulator/sim/net_socket_sim、board/host 测试与探针 - 文档重构:网络自愈架构设计.md 与 Net层阻塞模型架构设计.md 改为现状口径 (删历史节与阶段叙事),NET/README.md、docs/README.md 同步 - 工具与配图:gen_net_instability_svg.py 与 docs/images/网络不稳根因总览.svg 随源码口径一并更新 - 门禁:@build 0 错误 0 警告 |
||
|
|
a12367981d |
fix(N34): E14 丢中断复核——芯片不丢事件;listen 排事件挪至 LISTEN 前+全局读收口+全库归因更正
48 轮直读 SINT 矩阵(8 周期×6 变体)复核历史"丢中断"说法:芯片侧事件 丢失 = 0。归类:drain 读清消费 3/48(drain-int 探针现场抓获)、门控 竞态 2/48、主机同步 1/48、幽灵态 0/48 未复现。 根除性修复:net_listen_locked / net_listener_try 的排事件读清从 listen 后挪至 LISTEN 命令之前——新连接 CONNECT 落进该窗即被本方读清 吞掉,即"数据被吞"的生产侧自伤机制(台架 3/48 为同形态放大版)。 全局读收口:全局中断寄存器唯一读者 = net_poll(I7);生产/测试/台架 游离全局读全部删除,ch395f.h 声明处加护栏注释。 归因更正:17 文件约 40 处"丢中断"措辞改为"事件未收到/读清消费竞态" (机制全部保留,仅归因更正);设计文档 §5.2 新增 E14 锚点;Trap Records TRAP-NET-17/-20/B3 归因更正段;配图生成器与 SVG 重生成。 台架:事件未收到复核探针保留(drain-int / SINT 补读×3 / 超时归类), 下次跑矩阵自动归类;实验注册(main.c/uvprojx)已完全还原。 验证:@build 0 错误 0 警告;ci_local L0 32/0 + gitlint + L0.5 953/953;doc-links --all --sections-strict 通过;@test PASS(无 [ERR],net init 619ms);回归 :7003 300ms×10 = 10/10、:21 n30×50 = 0/50 失败。 |
||
|
|
6394853fef |
feat(N34): 阶段3 net层收敛——单一reconciler+忙等统一+镜像降级+E-02收口
实施方案 docs/网络/N34-自愈审计/实施方案.md §5 项1/2/3/5(项4 U15受E6暂缓): - 3a 合并reconciler:net_listener_pump删除,与net_reconcile_tick合并为 单一100ms tick;判据读驱动状态缓存(唯一刷新点=net_poll每轮全量刷新, E2背书18.1us);去抖分级②=1/③④⑤=2/①=4轮(M3让位窗400ms保留)+冷却1s; 链路态订阅留痕(F-DRV-13);探针去抖删除(F-MS-9) - 3b 忙等统一(P2b):listen/connect open重试与close排空循环改 net_sock_reset_sync(驱动sock_reset:读空RX→CLOSE→排空事件→等 byte0=00H,内置LISTEN态二段CLOSE补发);close不再读清全局中断寄存器 (F-NET-7);net_poll每轮步进活跃复位状态机(驱动契约,防搁浅) - 3c 镜像降级:net_sock_state_t声明为本层会话投影,芯片事实源=驱动缓存 - E-02收口:新API net_drop_conn(拆会话保监听,QUARANTINE语义,幂等; 模拟器双端实现;timeSync 30s预算耗尽接入;主机单测TC-TS-027d) 定案:CH395F close无RST,对内核存活不close的对端停FIN_WAIT_2, 监听恢复受限于对端close(Trap 07补充),兜底=E13 keepalive/TIMEOUT 台架全绿(Code=211348 RW=1104 ZI=154232):@test PASS;[STACK] net 1116/3840;Trap22 :7003 50/50+:21三档各50/50;Trap23 RST10/10+FIN5/5; Trap25 n30 11/11;E-02双PASS;iec104 18/18;对时跨会话连续; ftp_regression 11/11;integrity 15/15 SHA;ci_local L0+L0.5全过。 |
||
|
|
d346e4ee84 |
feat(NET): N34 阶段 1.5 recv 语义主流化——无限默认+具名非阻塞+模式属性
核心语义(实施方案 §3.5): - net_recv 默认无限阻塞:删除 NET_RECV_TIMEOUT_MS(30s 隐藏默认预算), 超时归调用方策略;唤醒源=数据/EOF/close/网络重建(CONNRESET), 会话死亡由对账① ~400ms 判死兜底,无"对端消失永久挂死"窗口 - 新增 net_recv_nb(NET_MSG_DONTWAIT 路径转正具名)与 net_setblocking(fd,on)(阻塞模式挂控制块属性,对齐 O_NONBLOCK/ Python setblocking;直写单字节,net_set_event_cb 先例) - net_types.h net_sock_t 新增 blocking 属性;net_socket() 默认置 1 (close memset 清零后显式重置,同 released_abnormal 纪律) - 原 1s 强制了结看门狗降级为 60s tripwire:只 [ERR] 留痕一次, 绝不伪造 TIMEDOUT 返回值(旧实现掩盖完成路径缺陷) - net_recvfrom 删 30s 自旋超时、同判据对齐(零生产调用者,注释警示) - 文档契约:IWDG required_mask 内任务禁止无限阻塞 recv(BSD 指南 §3.5/§10.1 + net_socket.h 注释) 调用点审计(§3.5.5):零生产调用点采用无限默认——iec104_serv/ ui_net_sink 转 net_recv_nb(受监控任务逐位等价);lftpd/time_sync 已是显式预算 net_recv_to 不动;32 轮盲收兜底未动(阶段 3 E6 门禁) 模拟器双端镜像 net_recv_nb/net_recv_to/net_setblocking(包装层 Sleep(1) 轮询模拟阻塞);差距清单 N-3/N-6 登记义务已履行 门禁与台架: - @build 0/0:Code 209580→209780(+200B) ZI +32B;RAM 受管区官方 脚本同步;ci_local L0 32/32 + L0.5 951/951 - 台架全回归:relisten :7003 50/50、iec104 18/18、对时正常、 ftp_regression 11/11、Trap23 RST 5/5+FIN 5/5、ftp_integrity 20/20 字节一致、n30 0/10、@test PASS - 模拟器 build_sim OK + check_remo_sink 黄金参考 0/25600 位差 队友 p15-recv-semantics 实施,Lead 全量审阅 + 独立复跑门禁与回归 |
||
|
|
b8c6a3dab0 |
refactor(net)!: N34 阶段1 API 面收敛(对账⑤ + 删 3 个手动自愈 API)
BREAKING CHANGE: 删除公开 API net_relisten / net_resync_listen / net_can_accept 与消息类型 NET_MSG_RESYNC_LISTEN / NET_MSG_RELISTEN。 生产调用者为零(仅看门狗文档与 iec104 门控),应用侧无迁移成本; 如有外部消费者须改用对账/pump 自动机制(见下)。 1. 对账①扩展为①②⑤(F-NET-2 缺口,先补缺口再删 API) net_reconcile_tick 新增 bad=5:本层 ESTABLISHED 且芯片 0x05/0x01 (Socket OPEN + TCP LISTEN,静默回收回监听、不发 DISCONNECT) → RESYNC 语义只修本层(state→LISTENING + last_peer_port 转登 + lost_conn_seen 清零 + 取消挂起 recv),**不发任何芯片命令** (纪律同 pump③ U11,run8 实证重下发会 170s 永拒)。 原判据①要求 TCP==CLOSED、②要求本层 LISTENING,均不命中此形态 ——此前生产无人认领(仅手动 API 能修)。 2. 删 net_relisten(net_socket.c 函数 + 消息分派 + 头文件声明) footgun:对健康监听器无条件 open→USE→close 自毁 ~1s(原注释自认); 与 pump(100ms)/D10(30ms) 完全重叠。 3. 删 net_resync_listen(同上;语义并入第 1 条) 4. 删 net_can_accept(net_socket.c + net_socket.h + sim 三处) 只认 ESTABLISHED 的旧门控把"监听器在服役、待 CONNECT"窗口全挡掉, :2404 丢 CONNECT 探针因此从不运行;iec104 门控迁 net_listener_armed。 5. timeSync :8888 会话收尾不再 net_close(同 fd 续 accept,监听跨会话 常驻;原 close→重建每会话一个 Trap 09 沉降窗)。server 脚本注释同步 新契约(PC 侧 2s 宽限后自行关闭)。 6. lftpd 应用层阻塞重试退役:lftpd_inet_listen 5 轮(500ms/2000ms,最坏 10s 阻塞 ftpTask) → 单次 + 失败即 425;cmd_pasv 3×200ms 同删。 就绪屏障已消除 Trap 09 启动形态,客户端自带传输重试语义。 台架实证修正(本提交内二次修复,务必留痕): - net_listener_armed 补齐 **ESTABLISHED 放行**。首版迁移只放行 LISTENING/CLOSED+残留,漏了 ESTABLISHED=单连接模型的"待 accept"电平 → iec104 200ms 任务周期抢不过对账② 的 ~400ms 去抖,对账②先 standalone accept 转 ESTABLISHED 后 armed=0 → 应用整场不 accept,18/18 检查全 FAIL (设备日志证据:sock1 standalone accept 后无 i104 accepted,直至对端 FIN 才由 closed-with-data 救回)。补放行后 18/18 PASS,且耗时 127s→8.3s。 该态 accept 必返 fd,无 RPC 风暴风险。 - 期间顺带验证 M3 无辜:sock1 suspect DISCONNECT on live conn 命中后 defer→对账①→closed-with-data accept 把未 accept 的 RX 数据救回, 正是 M3 设计意图(资产门保护)。 验证(全绿):@build 0/0(Code=209580;含 CH395F 套件+Phase13 全量重编 0/0 的编译验证);@test PASS(回读无差异);iec104 18/18(8.3s); n30 0/50;:21 @0ms 50/50 p50=512;:7003 50/50 p50=517;ftp_regression 11/11;Trap23 RST 5/5 + FIN 5/5;time_sync :8888 连续推送正常(RTC 更新、 无 [ERR])。文档同步:BSD 指南(§3.3/3.6/10.1/10.2/12 + 变更记录)、 函数调用关系、监听生命周期设计说明、IEC104 上行设计说明、模拟器差距 清单、链路延迟测试说明。 门禁说明:doc-links 工作树 junction 伪影按既定口径 SKIP;mem-budget 分支 .map 漂移同前;cppcheck/coding-standard 手跑 Passed。 |
||
|
|
1d96fc9f87 |
feat(soe): B9 动作记录 + 时标 SOE(L4-4/L4-5)+ 104 M_SP_TB_1 自发
- 新增 App/log/soe_rec.{c,h}:64B 定长 SOE 记录纯编解码(CP56Time2a
时标 + 类型 + 元件号 + 单调序号 + 值 + sum8 撕裂校验),零 I/O 零 OS
依赖,主机 L0.5 覆盖(32 断言,含与 iec104 CP56 解码器交叉互证)
- 新增 App/log/soe_store.{c,h}:protectTask 边沿投递(取时标 + 组记录 +
SPSC 待发环/消息队列,零文件系统);defaultTask 经 syslog_drain 尾部
排空落 /log/soe.log(卷锁 try / FA_WRITE|FA_OPEN_APPEND / 校验字节数 /
容量满 unlink 重建,全套照 run.log 实证纪律;无卷损坏归类路径)
- protect_task.c:元件动作/返回、软压板投退、采样闭锁/恢复六类边沿
→ soe_store_post;post 内禁 DBG_*(protect 静态最坏链 872 B 不变,
改前/改后 stack_report 九任务逐字节一致),丢弃留痕挪 drain 侧
- iec104:单点 YX 自发改 M_SP_TB_1(30) 带 CP56 时标(总召/周期保持
M_SP_NA_1,单测两种都断言);link cfg 新增 epoch_ms 时标源回调
(NULL/无效 → IV 位如实置位);serv 绑 sys_clock(秒域时基,
ms 域 = 秒×1000,不造假亚秒)
- 主机单测:test/host/soe/(32 断言)+ iec104 94→97(TB 时标/IV);
iec104_master.py 解析 type 30(B6/B7 流不回归);decode_soe.py
台架解码断言工具(seq 单调/校验和/UTC 交叉)
- 注册:uvprojx + check_registration SIM_EXEMPT 点名(MCU-only 胶水)
- 文档(我方属主区):`App/log/README.md` 增 soe 节(64B 记录/单写者/
post 禁 DBG/UTC 交叉坑);`docs/子系统设计/IEC104上行设计说明.md`
§1 范围行 + §3.2 时标注 + §7 台架行 + §8 第 2 条销项 + 变更记录行
台架腿(bench 锁 B9,release --bench-pass):run_boot_test PASS;
--b7-pre 21/21、--b7-post 13/13(B6/B7 回归 + 确定性动作边沿);
自发 YX 上送 M_SP_TB_1 带 ts(11:00:51 动作 / 11:00:53 复归);
FTP 下载 /log/soe.log 30 条记录 decode PASS(seq 0..28 单调、
ELM_ASSERT 14 条、UTC 交叉一致);定值/压板已恢复默认。
台账 +1088 B(SPSC 环 512 + 静态 FIL 528 + 计数器)随合并由 Lead
回填(ram_baseline --write + check_mem_numbers --write)。
gate: only mem-budget/mem-numbers pending lead ledger backfill
(pre-commit --all-files: 29 Passed / 2 Failed / 0 Skipped;
hygiene self-check OK: no BOM/CRLF/mojibake/trailws/non-ASCII literal)
sync 追平 v2-on-ui(B8 freq + N33 抬栈)后复跑:@build 0/0
(Code=209492 RW=1104 ZI=154184);stack_report 九任务全 PASS、
protectTask 872 B/57% 不变;ci_local L0.5 15 runner 951/951
(freq 46 / soe 32 / iec104 97 / prot_set 90 / prot_elm 47)。
顺带修 protect_task.c 陈旧注释:定值巡检 31 项 → 40 项(B8 后)。
|
||
|
|
0264b49489 |
feat(algo): B8 频率测量层 + 过频/低频保护(L3-5)
新增 App/algo/freq.c/h:由 L2 基波相量导出系统频率。相邻两拍共轭 乘积 P=Z(m)·conj(Z(m-1)) 取角 = 每拍相位增量(免显式解缠绕),再按 自适应窗长 K_eff=round(8·Fs/(2·f_hat))(45~55 Hz 段 73~89 拍)做滑动 平均。定长窗受 20 点矩形窗负序泄漏纹波限制(实测扫频最坏 0.317 Hz; 60 拍 Kay 复数和 0.197 Hz,交叉项和角不按 1/K^2 衰减),自适应窗使 窗长恰为纹波周期 fs/(2f) 整数倍 -> 最坏 0.0101 Hz。推导与两轮弯路 写在 freq.c 文件头。 假值钳制带取 35~65 Hz,刻意宽于系统合理带 40.5~60.5:单拍相位差本身 带 ±5 Hz 泄漏纹波,贴边钳制会非对称丢弃纹波半周 -> 均值偏置(实测 45 Hz 点 +0.16 Hz)。系统合理带由 OF/UF 定值范围在消费侧把关。 幅值门 FREQ_AMP_MIN=50 码(拟定,待 L1-5 标定复核):低于门判无有效 波形,停更新、valid 清零、读数保持 -> 浮空/PT 断线不发散。源优先级 UA(C02)->IA(C01),按名前缀解析、每拍动态回退,切换即废相位基准。 prot_set:尾追加 8 项(PS_ID_COUNT 32->40,编号不回收) OF_EN/OF_HZ/OF_DLY/UF_EN/UF_HZ/UF_DLY/RET_OF/RET_UF。OF/UF 逐项通讯 地址不在本仓库 -> 全部 comm_addr=0 本地项(104 C_SE 不可寻址,待对照 参考表补)。频率返回系数独立(0.99/1.01),勿与电气量 0.95/1.05 共用。 bad_mask 随项数扩为 uint64_t。PROT_SET_BLOB_VER 1->2。 prot_set_store:换代与损坏分流。load 返回 2 = 版本/项数换代(本文件 打 INFO "prot set blob version change, defaults in use"),-1 = 真损坏 (defaultTask 按 CORRUPT 报 ERROR + 自检留痕)。B7 旧档(ver=1/32 项) 升级首启属预期路径,不得报成损坏。语义分流收在属主文件内, default_task.c 不动。 prot_elm:实例表加 src 字段(0=phasor rms,1=freq),PE_OF/PE_UF 尾 追加(PE_COUNT 7->9)。freq 无有效读数按方向填"必不启动"值(过量 0 / 欠量 1e30 -> 滞回比较恒假 -> 元件复位),不整拍跳过——频率源缺失不得 饿死电流/电压类元件(B5 行为不回归)。OF/UF 暂未映射独立 104 遥信点, 动作只经 YX15 保护总聚合可见(送检点表 = B10)。 板端接线:adcTask 在 phasor_run() 之后同拍调 freq_run();心跳/首拍日志 追加 freq(<tag>): f=%ld valid=%u (x0.01)(MicroLIB 无 %f)。app_main 内核前 freq_init()。 主机单测:freq 46 用例(J1 扫频 45~55 Hz <=0.02 Hz 实测最坏 0.0101; J2 噪声 1% <=0.10 实测 0.0160;J3 启动收敛 <=40 ms 实测 20;J4 阶跃 50->51 <=120 ms 实测 98;J5 浮空 valid=0 不发散;J6 跳变 60 ms 内回 ±0.05;另直流 8000 码 / 3-5 次谐波 20%/10% / UA->IA 回退)。 prot_set 90(+TC-PS-011 OF/UF 行 + 64 位 bad_mask bit39 + 旧档拒绝)、 prot_elm 47(+OF/UF 滞回与方向隔离 + run() 测频接线)。回归:phasor 57、iec104 94 全绿。 J4=120 ms 是"精度优先于响应"的显式取舍(Lead 批准):4 周波窗换 0.317->0.0101 Hz,测频响应 98 ms << OF/UF 定时限默认 1000 ms(占 总动作时间 <10%),暂态另有 J6 <=60 ms 兜底。 注册:freq.c 入 uvprojx algo 组 + check_registration.py SIM_EXEMPT (纯算法、模拟器无消费路径,照 prot_set.c 先例)。 @build 0 错误 0 警告(Code=207468 RO=18304 RW=1068 ZI=153084)。 RAM:RW_IRAM1 96096->96728 B(+632 B,73.3%->73.8%)、RW_CCM 不变 57376 B(87.9%)、Flash 224596->226840 B(+2244 B,21.4%->21.6%); 台账随合并由 Lead 回填。stack_report:adcTask 静态最坏链 1320 B / 余量 1240 B(48%)改前后完全不变(freq_run 帧未进最坏链,无需抬栈); protectTask 链 872 B / 余 1176 B(57%)同样不变。 gate: only mem-budget/mem-numbers pending lead ledger backfill -------------------------------------------------------------- 门禁实跑(pre-commit run --all-files,Lead 批准 --no-verify 提交): 28 Passed / 2 Failed,失败仅 mem-numbers 与 mem-budget 两条——均为 docs/内存管理 受管快照与本 .map 不一致(台账由 Lead 每次合并后 --write 回填,避免多分支同改受管表冲突)。其余含 doc-links / coding-standard / no-mojibake / cppcheck / registration-check / 13 条主机单测钩子全 Passed(gitlint 属 commit-msg 阶段,不在该次 --all-files 内)。ci_local L0.5 全绿(freq 46/46 等)。 字节卫生自查(--no-verify 跳过卫生钩子,故手工核):17 个暂存文件 全部 BOM=无 / CR=0(纯 LF)/ U+FFFD=0;自研 .c/.h 去注释后字符串 字面量 100% ASCII(唯一非 ASCII 字面量在 test/host/iec104/iec104_test.c 的既有用例名,非本次改动行;test/ 不在 coding-standard 钩子范围)。 |
||
|
|
dafcf8098b |
test(b6): 台架 @test 闭环复测收口 + 启动行门控修复 + PC 104 主站
B6 台架 @test 闭环复测(B4/B5 验收窗口)完成,DoD 全判据过。
门控修复(首跑 FAIL 实锤的 B5 遗留竞态):
- 现象:protect task start 锚点行字节级交错损坏
(st[art: cycle=220ms elm=70,两次开机同形复现)
- 根因:启动行在控制台写者注册前打印走无锁裸发,与
defaultTask 启动日志交错——违反 2026-10-10 门控纪律
(控制台单写者日志设计说明.md §3.4,adcTask 同款先例)
- 修复:启动锚点行改 dbg_console_writer_ready() 首拍补打
台架与工具:
- .serialtest/config.json:Required 增 protect task start /
i104 listening on 2404 / [STACK] protect|iec104|heap
- test/host/iec104_master.py:纯标准库 104 主站客户端
(STARTDT→总召四组+actterm→C_SE 两段写触发 YX15/16 变位
COT=3→恢复复归→YK11 两段正答→C_RD 读回),往返 18/18
PASS(d3107f3 与 B7+fix 两版固件)
- 复测 @test PASS:锚点完好 +577ms、9/9 Required、零 [ERR]、
回读一致;protect free_min 1220(59%)、iec104 2136(83%)、
新 56KB 堆 min_ever=10000(N-33 抬栈背书就绪)
证据与文档回填:
- boot_log_data 四份快照(含缺陷复现 MISS 件)+ README 登记
- 保护规划 §7 B6 行(B5 台架遗留闭环);控制台单写者 §3.4
纪律示例 + §11 变更记录;IEC104 §7/§8 主站工具就绪;
W1 卡 B6 ✅ + N-33 背书 + B7 台架腿注;登记簿 N-33
- 内存台账:+16 B 构建后 ram_baseline/check_mem_numbers 回填
验证:@build 0 错 0 警(Code=205516);ci_local 全绿
(L0 30 钩子 + L0.5 13 套件 826 断言)。
|
||
|
|
1fe163ba7b |
feat(protect): B7 定值持久化 + 全局软压板 + L5-1 竞态收口(W1 代码腿完成)
- prot_set:新增 PS_GLOBAL_EN(枚举尾追加);值区双缓冲 + 单字交换, prot_set_set_sealed 原子写+封存;selfcheck 改 seqlock 式复核 (提交撞见 = 本轮跳过)→ 收口 B5 登记的 µs 级误锁窗口 - 持久化:新增 App/cfg/prot_set_store.c/h,/prot_set.bin blob (magic+版本+计数+值区+sum32 正/反码对,144 B)走 cfg_store_write_atomic; uvprojx 注册 + 模拟器豁免点名(check_registration 同步) - 写路径:C_SE/YK12 执行段置脏 → iec104Task 投递 SYS_EVT_PROT_SET_SAVE (事件位 bit7)→ defaultTask(配置引擎属主)落盘,写失败脏回置 = 天然 重试;装载 = STORAGE_READY 屏障前整表原子 parse(损坏保出厂默认 + 自检留痕 prot set corrupt;文件缺失 = 首启静默) - YK12 转真:两段式(选择段校验 DPC / 执行段 set_sealed),protectTask 下一拍读退出态 → 复位元件 + 停判据(global plate OUT/IN 边沿日志); 本地定值项 comm_addr=0 显式不可寻址(防 IOA=0 误命中首个本地项) - 单测:prot_set 63 断言(+33:软压板/原子写/脏握手/blob 往返/损坏拒绝/ 伪造自洽越界对抗样本)、iec104 94 断言(+7:YK12 两段转真/置脏/本地项 C_RD EVI) - 文档:IEC104 设计说明 §3.3/§3.4/§7、保护规划 §3.5 L5-1/§7 P4/变更记录、 App/algo 与 App/cfg README、W1 任务卡 B7→🟦(台架腿 🔴 待窗口,随 B6 同窗) - 验证:@build 0 错 0 警(Code=205500,ZI +280 = 双缓冲+blob 缓冲); ci_local 全绿(L0 27 钩子 + L0.5 13 套件 826 断言);ram_baseline 台账 受管区与内存快照已同步;19 个改动文件无 BOM / LF / 零乱码 |
||
|
|
d3107f374f |
docs: 待处理内容.md 解耦为 docs/任务规划/ 文件夹(README 排序权威 + 6 个职责单一文件)
- rename_ref.py 搬迁:git mv + 全库引用改写 33 文件 82 处 - README.md 保留 §0 编号空间 / §1 未闭环一览 / §2 推进顺序权威 / §3 维护约定 - 拆出 6 文件:W1-采集保护收尾(任务卡五字段)、排期详述、暂缓-RS485、 登记簿、测试与架构专项、基线与待确认 - 外部引用重定位 ~50 处:裸「登记簿 §X」、§5.1→基线与待确认 §2.1、 §2.4→暂缓-RS485、§6→基线与待确认 §3、脚本注释 T-x/N-x→登记簿 - 新增并行写纪律:任务分支不改本文件夹,状态列由 Lead 主工作树更新 - 验证:doc-links 141 文档全绿;mem-numbers 一致;refgraph 重生成; @build 0 错误 0 警告;新文件无 BOM / LF / 零乱码 |
||
|
|
90db528032 |
W1 功能主线完成:内存台账三件套(W1-0) + IEC104 上行(B4) + protectTask 板端接线(B5)
W1-0 台账三件套:scripts/ram_baseline.py(四模式)+ ram_baseline.tsv 趋势 + docs/内存管理/RAM预算台账.md + pre-commit mem-budget 钩子(RW_IRAM1/RW_CCM >92% 即 FAIL + Top-10 附表);审查报告 §5.5 三条闭环。 B4 IEC 60870-5-104 上行(被控站,TCP 2404):App/protocol/iec104/ 三模块 (asdu 编解码 / pts 点表+数据源 vtable / link APCI+FSM,纯逻辑零 I/O)+ App/task/iec104_serv.c(iec104Task,NET_READY 屏障 100ms 分片喂位)。 82 断言 L0.5 全绿 + iec104-unit-test 钩子(第 31 钩子); 设计说明 docs/子系统设计/IEC104上行设计说明.md 全量回填。 B5 protectTask(L3 板端接线):App/task/protect_task.c——20ms 判据节拍 prot_elm_run + L5-4 采样故障闭锁(adc_health 电平位→元件复位)+ L5-1 定值 校验和巡检;新增 prot_elm_request_reset() 收口跨上下文复归(104 YK11 落请求、 eval 头部消费);定值/元件初始化移入 app_main_init(内核前)。TC-PE-010 (prot_elm 28 用例)。 门禁与内存:TASK_WD_PROTECT=8 入 required_mask(产品 0x77→0x1F7、HW 层 0x1F5,看门狗单测 39 断言同步);FreeRTOS 堆 48→56KB(.ioc L1 参数 + FreeRTOSConfig.h 同步,RAM预算台账 §6 登记配额 48→56KB)。 ZI 144,008→152,204(+8,196 B = 堆 +8KB,B5 扩容);Code=204,348。 stack_report:protectTask 512 words 静态链 872 B/余 57%、iec104Task 640 words 1456 B/余 43% 均 PASS;RW_IRAM1 73.1% / RW_CCM 87.9%(<92%)。 验证:@build 0 错 0 警;ci_local 全绿(31 钩子 + 13 主机侧单测); doc-links 135 文档 PASS。登记簿 B4/B5 销项、W1 波次完成;保护规划/看门狗 说明/AGENTS(9 任务)/RAM 三文档全部同步。 遗留(验收窗口,非代码空洞):台架第三方 104 主站往返(送检窗口)、 标准源注入动作判据、@test PROT 锚点 + protect 栈水位 + 新堆 min_ever 复测。 |
||
|
|
c5227291bd |
test(fw-stamp): 身份戳覆盖测试宏——头依赖 + suite/dstr 变体串
问题:__DATE__/__TIME__ 只在所属 TU 被重编时才刷新,而 app_main.c 不依赖 test/board/test_config.h → 只切套件宏的增量构建不重编它,测试镜像与产品 镜像顶着同一个 fw build: 戳,@test 的戳校验对"两种构建互换"完全失明 (2026-10-11 N-31 复测实测:两者戳同为 Oct 11 2026 14:44:11,只有 -CmpFile 回读才发现镜像不同)。 修复(App/app/app_main.c,两条防线): - #include "test_config.h" 建立头依赖 → 改 TEST_SUITE_* / ENABLE_DESTRUCTIVE_TESTS 必重编本 TU,戳必刷新(根因修复) - 戳串追加 FW_BUILD_VARIANT = " suite=<TEST_SUITE_NAME> dstr=<on|off>" → 戳内容本身区分构建,时间撞车也能分辨 实测:产品 20:36:11 suite=NONE dstr=off ↔ 测试 20:36:40 suite=CH395F dstr=on ↔ 还原宏后 20:36:55 suite=NONE dstr=off(时间戳每次都变 = 头依赖 真的生效)。@test 全闭环 PASS:戳匹配 + 回读 No difference found + 锚点 x1 + 零 [ERR]。run_boot_test.py 无需改动(戳按"标记后连续可打印 ASCII"抠取,天然吃下新后缀)。 代价:Code 196764 → 196788(+24 B),@build 0 错 0 警。 文档:自动化测试流程.md 补「戳覆盖构建配置」小节与变更记录行;失败模式 表新增一行——戳命中但 suite= 与要跑的套件不符 = 烧的是产品镜像。 门禁:mem-numbers 钩子拦下「RAM 文档快照与 .map 不一致」→ 用 check_mem_numbers.py --write 刷新生成区(ER_IROM1 213,256 → 213,396 B)。 |
||
|
|
d1e6bb4ba7 |
W5波+N-19收口:FTP鉴权落地、Trap25三连定案修复(N-30)、N-20/N-23/N-26
N-19 FTP 鉴权:
- lftpd_auth(USER/PASS 状态机 + 连续5次失败锁60s)+ SHA-256
(user||pwd) 口令哈希;config.ini [ftp] 段 user/pwd_hash/write,
出厂 admin/admin 在用有启动告警;lftpd_log.c 删除并入 lftpd_auth
- ftp_cfg 配置读写;台架 ftp_auth_bench.py 13/13
N-30 / Trap 25(CH395F_Trap_Records.md 四次定案全记录):
- 修复1 closed-with-data accept:客户端发完正常 FIN 后芯片按
FUN_PARA(0x09) §5.52② 保留 Socket+RX 缓冲,旧代码把 CLOSED 一律
relisten 自毁缓冲 → STOR 必挂 425;改为接受"已关但可读"连接排空
- 修复2 丢 CONNECT 中断探针 net_lost_connect_probe + last_peer_port
幽灵甄别(拆链窗口握手完成但中断丢失,双信源去抖补 accept)
- 修复3 send_list/send_nlst 批量单发:背靠背 ~60B 小段毒化芯片 TX
(芯片报 SEND_OK 但对端全丢),整份目录一次性写入
- 证伪存档:固定沉降/Socket 轮换冷却/listen 门控(台架 v7 矩阵)
- 台架工具 test/board/ch395f_reuse_bench.{c,h} + host 脚本存档
(不注册编译;实验分支 n30-chip-bench 保留)
N-20:Error_Handler 死循环降级(记录+复位路径)
N-23:scripts/check_registration.py 双端注册反向校验(pre-commit)
N-26:GD5F NAND 直 DMA 调用方缓冲窗口断言
验证:BUILD_OK 0/0;ftp_regression 连跑 4 轮 11/11(修复前
LIST#4/#7 100% 挂、STOR#2 曾 100% 425);ftp_auth_bench 13/13;
@test 启动标记 PASS;ci_local L0+L0.5 全过;doc-links 通过。
登记簿 N-30 已销项。
|
||
|
|
c936441c83 |
门禁扩容:新增 lv-conf-sync、simulator/ 纳入全部钩子;含 L3 定值/元件框架落地
本轮把"自研代码落在门禁之外"的口子收掉,同时落地 LVGL 特性裁剪与 L3 保护定值/元件框架。 门禁(.pre-commit-config.yaml,26 个钩子) - 新增 scripts/check_lv_conf_sync.py + 钩子 lv-conf-sync:比对两份 lv_conf.h 的**生效值**(未定义则取 lv_conf_internal.h 兜底默认), 抓 MISMATCH / LVGL 不认的宏名 / 同文件重复定义 - 顶层 exclude 删掉 simulator/:其下 21 个 tracked 文件全是本项目自研 代码,生成物(build/、SDL2/、tests/ref/、shot*)已在 .gitignore; doc-links 的 exclude 同步删除 - lv-conf-sync 的 files: 覆盖两端配置 → 只改 simulator/lv_conf.h 也触发 (pre-commit 4.x 已移除 always: true,实测只告警并跳过,无兜底开关) - 新增 prot-set-unit-test / prot-elm-unit-test 两个主机侧单测钩子 - S11(2.3.5) 判定细化:禁的是"用路径找文件",尖括号系统头带子目录 (如 <sys/stat.h>)不再误报;全仓库复核仅 2 处项目代码判定变化 模拟器代码整改(纳入钩子后暴露,全部修代码而非豁免) - cppcheck 4 处:sim_syslog.c 判空分支内解引用 p_epoch(真实 bug)、 2 处 struct tm 未初始化、1 处指针可加 const - coding-standard 61 处:44 处函数左大括号并到右括号同行、8 处补函数 注释、3 处补文件头注释块、2 处 __ 前缀保护宏改 XXX_H、2 处 sprintf 改 snprintf(写入字节数与原来完全一致) LVGL 特性裁剪(F-1/F-2/F-3) - 两端 lv_conf.h 对齐同一特性子集:删 26 个 LVGL 9.3 不存在的选项名、 3 处重复定义,10 项靠默认值隐式生效的改为显式固化 - 实测对镜像体积中性;价值在防漂移,且模拟器 golden 回归跑的正是固件 实际编译的配置 L3 软件侧 - App/algo/prot_set.* Q10 定值模型(范围校验 / 整表 all-or-nothing / 校验和封存-自检-闭锁)+ prot_elm.* 通用"滞回+定时限"元件框架 7 实例 - test/host/prot_set、test/host/prot_elm 主机侧单测;uvprojx 挂载两处 文档同步 - pre-commit使用说明:§2.8 S11 口径、§2.15 lv-conf-sync 详解、新增 §5.5 复盘(教训:exclude 只写真正不该进钩子的路径) - AGENTS.md、UI_设计架构 §1.4 第 10 条、RAM 分析、审查报告刷新与销项 验证 - @build BUILD_OK 0/0(Code=194276 RO=15872 RW=876 ZI=139892) - 模拟器重建:菜单 8 状态像素逐字节一致(池 5368 B)、11 内容页黄金参考 全过(往返 5448 B)、remo sink 0/25600 位差异、--logtest/--cfgtest PASS - 全仓库 cppcheck / coding-standard / no-mojibake --all-files 全过 - check_doc_links --all 129/0;check_mem_numbers --check 内存数字一致 - 端到端:往 simulator/lv_conf.h 注入一行漂移 → 钩子 FAIL(exit 1) |
||
|
|
13a4e61c27 |
L1-6 采样有效性校验:adc_health 判定层 + 告警编排 + 31 用例单测 + 台架闭环
新增 App/algo/adc_health.c/h(纯逻辑判定层,零平台依赖免桩单测): - 静默:两侧帧序号连续 >=100ms 无前进(电平位可自愈,flags() 为 L5-4 闭锁预留) - 丢帧:TPAFE 序号一次前进 >1 计 tgap(与 STM32 侧 adc1_gap 对称,边沿事件) - 单调性:序号倒退锁存位;tick/计数差值法 (int32_t)(a-b) 回绕安全 - 错误增量:FRSTDATA / HAL 错误 / STM32 停摆计数增量,事件位与锁存位编号对齐, 消费者按位图做"每类每次开机留痕一次"编排 adc_task.c v2.9 告警编排(判定与编排分离):严重事件/电平上升沿 DBG_ERROR + SYSLOG_SELFTEST(每类每次开机一次防刷屏),下降沿 DBG_INFO 恢复;gap 不告警 (消费者超拍是已知现象,告警会淹没真故障);心跳行增 tgap 观测字段。 主机单测 test/host/adc_health/ 31 用例全绿(100ms 门限两侧 / 边沿语义 / 倒退锁存 / tick 回绕 / NULL 守卫 / init 幂等),登记 adc-health-unit-test 钩子。 台架 @test PASS:零 [ERR](健康不误报)、tgap=1->2 与 adc1_gap 同步可见、 frames 1000.0 Hz;证据 boot_log_data/20261011_prod_adc_health_boot_log.txt。 抬栈:adc_health_report->syslog_post 控制台回显尾使 adcTask 静态最坏链 832->1080 B(512 words 余 968 B < 1024 B ISR 底线)-> 512->640 words, 复测余 1480 B / 57%,堆 min_ever 7152->6640 B(-512 B 符合预算)。 AGENTS/README 任务表、RAM 方案 §2.3、规划文档 §3.1 L1-6 已同步置完成。 |
||
|
|
54d6d2d5d5 |
docs: 删除 Task #32 停摆分析(已结案),可复用结论并入看门狗设计说明 §11
按登记簿"完成即销项"规则删除 docs/问题记录/UI任务看门狗停摆分析.md (560 行)。结案依据:累计 38 次上板启动 0 复现(原 L2 基线 3/10), P0/P1-4a/P1-5/P2/方案 A 全部落地,方案 B 已评估决定不做。 并入 docs/子系统设计/看门狗设计说明.md 新增 §11(只留可复用部分): - §11.1 三条易误读的判读口径:启动期 MISS start 0x67 是良性 episode; miss= 是累计不是连续(连续数饱和在 WD_MISS_TOLERANCE=8); reset cause 不能区分 IWDG 溢出与台架软件复位 - §11.2 诊断四步:先看掩码缺几位(只缺 1 位 = 定点打击,多位 = 全局 饥饿)→ 逐项量化占空比(实测 10%~13%,否掉"CPU 饱和"直觉)→ 用计数速率反证空转(ring 恰好 1000/s)→ 用 [PROF] 指认占用者 - §11.3 三条结构性脆弱点(uiTask 唯一 BelowNormal/心跳曾依赖 netTask 往返/自定截止期不可恢复)+ 两个顺带修掉的正确性缺陷(无新帧仍压环 ≈3% 频率失配、失败拍静默沿用旧值) - §11.4 [PROF]/[PROF2] 全字段语义 + v2.8 实测基线(netp=0 是真实值、 adcm 峰值来自心跳日志、uip 地板 = LVGL 帧周期)与三机理判读口诀 - §11.5 三条教训:门控类优化必须保留低频兜底;门控会顺手消灭暴露路径; 事件驱动要核对节拍源启动时刻 vs 消费者创建时刻 - §11.6 明确不做的四条及理由(提 uiTask 优先级会掩盖真缺陷、net_* 有界 等待版会串回执、推流搬出 uiTask、推流塞进 netTask) UI 推流门控与方案 B 否决理由收进 RemoDispBus 协议说明 §3(该处原本已有 摘要,改为自洽不再回指);就绪门控 API 的约束已在 BSD Socket 指南 §10.1。 引用改指 12 处:ui_task.c、task_prof.c/.h、ui_net_sink.c/.h、docs/README、 RemoDispBus、看门狗设计说明 R7 行、ADC 采样节拍设计说明、BSD Socket 指南 ×2、项目审查报告 N-10 ×2。 ⚠ ui_task.c / ui_net_sink.c / ui_net_sink.h 是带 BOM 文件,Edit 剥掉了 BOM,已按原样补回 3 字节 EF BB BF(未整文件重写)。 验证:check_doc_links --all 通过(127 个文档,无悬空引用); @build 0 错 0 警,Code=257660 与删除前一字不差(纯注释改动)。 |