86 Commits

Author SHA1 Message Date
wandering1 2525c2d948 docs(104): 端口口径统一成「工厂默认」,登记「改后立即重 bind」待办
用户裁定两条:① 剩余裸写端口的地方加「工厂默认」限定词,不改固件行为;
② 生效语义按需求口径「保存即生效」定,现实现(端口下次重 bind 才生效)是
要改的一侧 → 建任务登记,本笔不动代码行为。

限定词(24 处 / 17 文件):AGENTS 数据主线、App/protocol/README、根 README
文档索引、Src/freertos.c 三处任务注释、docs/README、项目启动顺序管理、存储
架构说明、软件架构与运行时规格(2)、RAM 使用分析、产品需求设计文档(5)、
项目架构总览(3)、test/host/README、iec104_master 流程注释、IEC104 上行设
计说明、继电保护功能复现规划。配图两张同批重跑:gen_arch_svg.py 与
gen_memory_svg.py(脚本与产物同一笔)。

两处陈旧计数(都做过双源核证):
- 测试开发标准流程 像素层「60 内容页」→ 内容页黄金参考 66 张(64 页);
  双源 = simulator/tests/ref/shot_*.bin 实数 66 与 check_content_pages.py
  的 PAGES 66 条(含两个 _p2)。
- .pre-commit-config.yaml 的 uinav-selftest 注释「18 张黄金参考」→ 写成
  「接线当时 18 张、现 66 张」:git log -S 定到 6a904c1b(2026-10-25),那
  天 ref 目录确实 18 张,写时为真,但它描述的是钩子现有行为,属当前态。

口径修正与登记:
- 页面扩充详细方案「通讯设置 = 无配置模型(端口与 CA 都是 #define)」→ 标
  「当时」,并写明现已在 /config.ini 的 [comm] 段可配、UI 通讯设置页可改。
- 产品需求 §通讯配置:删掉「改后需重启生效」这句把两件事混为一谈的话,改成
  需求要求「保存即生效」+ 现实现(公共地址重启、端口下次重 bind)+ 指向登记簿。
- docs/任务规划/登记簿.md §1 新增「104 端口改后立刻重 bind」:含隐性耦合
  —— .serialtest/config.json 的必检锚点写死 listening on 2404,端口一改串口
  回归必假失败;改行为时要么锚点只查 listening on,要么由脚本注入端口。

复扫(旧形态归零判据)剩 20 处未带限定词,逐条定性为刻意不改:默认值定义处、
出厂模板与断言、usage 与 argparse default、UI 黄金参考显示值、台架主站地址
(同数不同义)、串口锚点、叙事句、引用关系图坐标。逐条理由见一次性台账。

门禁:check_doc_links --sections-strict 对 16 篇改动 .md 逐个 rc=0;
check_mermaid --all 31 文件 62 围栏新发 0;check_nested_comment --all 449
文件新发 0;check_bom_drift --all 99 个名单内文件无漂移;
check_generated_fresh PASS(25 生成器 / 21 一致 / 4 只减不增基线);字节体检
无新增 BOM / CR / U+FFFD / 行尾空格(三连空行与 HEAD 逐项相同 = 存量)。
/keil-build 0 错 0 警,Program Size Code=246720 RO=29836 RW=2052 ZI=149708
与凭证同码:本笔只碰注释与配图文字,无固件行为变更。
2026-10-30 15:40:27 +08:00
wandering1 7708f12c10 fix(ui/screenlink): 按键应答扣到按键后画面,反馈典型 250-450 ms 降至 70-135 ms
按键召唤答的是按键前的旧帧:uiTask 还没消化键答案就发走了,新画面
只能等下一次周期召唤(280 ms/轮)才带得出——真机反馈 250-450 ms 的
主构成(根因账本 docs/子系统设计/屏板链路设计说明.md §7.1)。

改动(用户批准范围 A+B+C;屏板固件未动,决策三不变):
- sb_link:按键召唤改为只入队不起发;uiTask 同拍重绘并组帧成功后交
  凭据(sb_link_key_rendered),TIM3 1 kHz 的 sb_link_ms_tick 以 ≤1 ms
  放行新帧。140 ms 截止(SB_KEY_RESP_MAX_MS,+59.6 ms 线上 <205 ms
  屏板放弃线)保底发旧帧,"一召一答"契约不破;线忙时同旧丢单、
  不留扣件。起发两中断源(USART1 IDLE/TIM3)共用 sb_tx_kick,
  "判忙→占位"在 PRIMASK 临界区原子完成。
- ui_task:排空注键挪到组帧之前,注键→即派即绘→组帧同拍闭环;
  组帧返回 BSP_OK 才交重绘凭据(BUSY 拍帧还没反映按键)。
- ui_port:注键单槽改 8 深环(连按不再互相覆盖,满丢最旧+计数);
  新增 ui_port_service_keys:同拍 lv_indev_read + lv_refr_now,
  省掉 indev ≤20 ms + 刷新 ≤20 ms 两段等待。
- ui_menu_view:菜单移动选中只失效新旧两行带(黄金参考零像素变化),
  滚动/异常回退整框失效。
- simulator:窗口循环 sleep 扣除本轮已耗时(原先无条件睡满
  lv_timer_handler 返回值,叠加 Windows Sleep 15.6 ms 粒度放大观感)。
- 串口 TX 上报新增 dfok/dfold(凭据放行新帧数/超时保底旧帧数):
  dfold 连涨 = uiTask 被饿 ≥140 ms 的直接现场证据。

验证:test/host/sb_link 164/164(新增 18 条:不立刻起发/凭据放行/
140 ms 截止保底/忙时不留扣件/陈旧凭据不放行等边界);菜单 8 状态 +
内容页 66 张黄金像素 PASS;Keil @build 0 错误 0 警告(两次);
BOM 99 文件无漂移、代码规范、doc-links 本次文件零问题、cppcheck PASS。
文档:屏板规划文档已被主干收编进设计说明,延迟账本落
docs/子系统设计/屏板链路设计说明.md §7.1,并同步 §4 口径、§8 接口、
§9.1 单测台账 146→164、§10 坑账本补条。

RAM 台账(分支不跑 --write,并行分支提交约定):本笔盖戳行
RW_IRAM1 94,336 B (72.0%) / RW_CCM 57,376 B (87.9%),较上一台账行
+4,400 B——为距上次台账构建以来分支累计差(含批 3 状态灯等未盖戳
提交),非全部本笔引入;本次自身增量按对象计为 ui_port.o +12 B
(8 深键环+丢计数+indev 指针)与 sb_link/o 数十字节级。
gate: only mem-budget/mem-numbers pending lead ledger backfill
(合并落主干后 Lead 统一 --write 回填受管区)。
2026-10-30 09:50:31 +08:00
wandering1 dab0d8ba17 feat(屏板): 帧 B 组帧 + 中断起发 TX DMA + 按键队列 + 离线判定(批 2)
批 2 五项全部落地(docs/任务规划/屏板链路.md §3):
- 2-1 sb_link_frame_update():uiTask 渲染后按需组帧,不留 3200 B 影子
  副本,直接拿活显存与帧内点阵段 memcmp;组完自校验,过了才置 ready。
  静态 4208 B 帧缓冲实测落 RW_IRAM1(0x20006d98),不在 CCM。
- 2-2 空闲中断校完 6 B 召唤帧直接点 TX DMA(sb_tx_kick),不排队不攒批;
  busy 期间再来的召唤丢帧并计数,绝不叠发(屏板收帧一次 IDLE 一包)。
- 2-3 按键走环形队列(中断入、任务出),uiTask 按 §4.3 表映射 UI_KEY_*
  后调 ui_port_queue_key;9/10(RESET/FACTORY)按决策四先丢弃并留痕。
- 2-4 HAL_UART_TxCpltCallback 在 rs485.c 加第三行转发(三个全局回调
  落点收一处,防日后重复定义);busy 冻结帧缓冲,错误中断按 gState
  收拾被打断的 TX,防残留 busy 把链路永久锁死。
- 2-5 连续 >=10 s 无有效召唤帧才判离线(不按 500 ms——屏板约 5000 s
  自复位有 1 s 空窗),恢复即清标志;CRC 错帧静默丢弃并计数。

实测:台架 40 s(PC 顶替屏板,--key-fixed 2 持续改画面)rx=143 ok=143
keys=143 crc=0 / tx=143 done=143 drop=0 abor=0 fb=144 bad=0;脚本一停
10 s 准点出 OFFLINE。组帧耗时 509 µs 典型 / 709 µs 峰值——原 0.3 ms
判据系估算,已按实测在规划文档改口为 1 ms 并给出压降路径(未做)。

附带:rs485_on_rx 补 CODE-RULE-09 文档块(本轮改 rs485.c 触发整文件
重扫被拦);CRC 循环计数改 32 位(消掉 ARMCC 每轮 UXTH);bench 脚本
加 --reply/--key-fixed/--dump,并写明 CH340 收不了 700 kbaud 连续流、
--reply 收不全 4208 B 不是固件问题。

主机单测 146/146 PASSED(+65);Keil 0 错误 0 警告;ci_local 全绿
(SKIP=nested-comment,worktree 限制,主树脚本另查 0 新发)。
Code=238,936 B / RW_IRAM1 65.5 % / RW_CCM 87.9 %。
2026-10-29 20:59:36 +08:00
wandering1 7c8669e52a feat(屏板): USART1 700 kbaud + 收中断传输层 sb_link(1-2/1-3)
批 1 的 1-2 / 1-3:把屏板(DTU-LCD)发来的 6 B 帧 A 在 USART1 上稳定收下来。

1-2 波特率:.ioc 不保存任何 UART 的波特率(只有
USART1.IPParameters=VirtualMode),GUI 里改也不落盘,所以只能在
Src/usart.c 的 USER CODE BEGIN USART1_Init 2 区覆盖 huart1.Init.BaudRate
后重调一次 HAL_UART_Init(第二次调用时 gState 已非 RESET,HAL 只重算
BRR、不再跑 MspInit,GPIO/DMA/NVIC 不会被重配)。开机日志实测
BRR=0x0078,与理论值 84 MHz/(16x700 kHz)=7.5 逐位相符,误差 0%。

1-3 收中断:新建 Drivers/BSP/ScreenLink/sb_link.c/h——16 B 缓冲 + IDLE
中断断帧、帧 A 校验、错误中断里按 RM0090 清 ORE/NE/FE/PE、周期统计上报。
HAL_UARTEx_RxEventCallback / HAL_UART_ErrorCallback 是全局单例(唯一实现
在 rs485.c),故只在那里各加一行转发,按句柄过滤放在 sb_link 内。

台架实测(PC + USB 转 TTL 顶替屏板,COM6@700000)撞出两个真问题:
- 错误回调里无条件重挂 -> 出现 err=160 / rearm=160 同步增长,看着像每帧
  都重挂失败。真因是 HAL 把 NE/FE/PE 归为非阻塞型(接收照跑、RxState 仍是
  BUSY_RX),此时 ReceiveToIdle_IT 只会返回 HAL_BUSY。改为仅当
  RxState == HAL_UART_STATE_READY(ORE 那类阻塞型)时才重挂。
- 日志字面量里带中文 -> ARMCC #870-D invalid multibyte character
  sequence。字面量一律纯 ASCII,中文只写注释。

验证:主机单测 81/81 PASSED(test/host/sb_link/,其中按 RM0090 的清除语义
把"必须 SR->DR 顺序才清得掉 ORE"钉成断言);Keil 0 错误 0 警告;台架
rx == 发送帧数、ok == rx、crc=0、len=0、size=6、keys 随按键帧递增;先用
错波特率灌 64 B 垃圾(len=31、bits=0x06)后自动恢复且 rearm=0。
新增 test/host/screenlink_bench.py 作为可复跑的屏板激励(--key / --glitch-baud)。
2026-10-29 20:13:18 +08:00
wandering1 593c5d0c84 refactor(编号): 采集链分层 L1/L1.5/L2/L2.5/L3/L4/L5 → 语义名(批次 1)
用户裁定(2026-10-28):L1/L1.5/L2/L2.5/L3 这套层号「谁能看懂」,改用语义名。
映射(同一批定稿,含 L4/L5):
  L1   → 语义取数与有效性
  L1.5 → 标定折算
  L2   → 全周傅氏相量
  L2.5 → 测频与遥测快照
  L3   → 保护判据
  L4   → 出口与记录
  L5   → 动作留痕

实测规模:384 站点 / 62 文件(App/algo、App/task、test/host 六个套件、docs/算法、
产品需求、架构总览、启动顺序、ADC 采样节拍、IEC104 上行、采集短板评测、内存管理、
AGENTS.md、README.md、docs/README.md、.pre-commit-config.yaml 与 scripts 里的注释)。

改法(不是全局替换,逐模式有上下文规则):
- 先吃同位语再落裸词:L1 有效性校验 → 语义取数与有效性校验、L2 相量层 → 全周傅氏
  相量层、L3 保护 → 保护判据、L2.5 遥测快照 → 测频与遥测快照,避免「保护判据保护判据」
  这类重复(第一版就是这么坏掉的,已整体回滚重做)。
- .c/.h 只改注释:先把字符串字面量切出去(引号数为奇数的跨行注释按整行处理),
  C 字符串里的 L2-in ring 之类原样保留——AGENTS 铁律「字符串字面量必须纯 ASCII」。
- 层内条目号(L1-3 / L2-3 这类)**本批不动**,属批次 2;另外三族(UI 菜单层级
  L0~L3、链路延迟分段 L1~L8、CubeMX 防丢失三层)也不动,属批次 3。
- 顺手修的措辞:范围写法 L1~L3 → 「分层(语义取数与有效性 → 保护判据)」、
  CI 段「不含 L1/L2/L3」→「不含采集链分层」、目录地图里同一处并列表述。

验证:@build 0 错 0 警(Code=236456,与改前逐字节同尺寸——纯注释改动);
内存布局配图已按新脚本重生成(自检通过);doc-links --all --sections-strict 通过
(195 文档);mojibake / bom-guard / coding-standard / 新编号门禁自查 全 rc=0;
git diff --check 干净。
2026-10-28 13:04:02 +08:00
wandering1 1166ab1c2e fix(adc): 挂 DMA 前关闭 ADC,消除乒乓缓冲 +2 格相位旋转
问题:ADC1 在 MX_ADC1_Init() 里使能,而 DMA 在 app_main_init() 步骤
4b 才挂载,中间隔着 GD5F 全片 BBT 扫描(数秒)。台架同一次开机内用
无 DMA 单通道逐路取真值、与 DMA 路径对照,得 9/9 完美置换:乒乓缓冲
从 rank 3 开始搬,槽 i 装的是 rank ((i+1) mod 9)+1,整体错开 2 格。
表象是"接地 AIN2、UB 却读到别的通道的值",极易误判为映射表写错或
注入点标签不对。

修法:新增 adc1_disable()(Src/adc.c 的 USER CODE BEGIN 1),在
app_main_init() 步骤 4b-pre 调用,把 ADC 置为关闭态,使能动作交给
HAL_ADC_Start_DMA() 内部完成(它自己 __HAL_ADC_ENABLE + 等 Tstab
约 20 us,紧接着开 CR2.DMA 并启流),使能与搬运之间不留可观测间隔。
顺序不可调换:本调用必须严格早于 adc_input_init()。

台架验证:在 MX_ADC1_Init() 末尾关闭 4/4 次、在 4b-pre 调本 API
3/3 次,均 UB=0;同开机对照差值 <=4 码(修前 7/7 次 UB=783~786)。

文档:ADC采样节拍设计说明.md 新增 4.5 节(9 行证据表、判据陷阱、
根因与修法)与设计铁律第 8 条。

台账:Flash 261,764 -> 261,928 B(+164,新增函数),RAM 无变化;
CubeMX 存活审计基线重建(adc1-calibration-impl / adc1-dma-link
两项漂移均属本次有意改动,锚点已逐条复核在位)。
2026-10-27 20:42:06 +08:00
wandering1 b7c0889cc7 refactor(编号·批次二): 代码与测试侧 215 处保护功能号改成功能名,零行为改动
用户裁定「不要用字母加数字的编号,语义标识是最好的」后的批次二代码半(道 ui-param 执行,逐文件站点数与
自证见其交付)。唯一口径 = 映射表 ci-artifacts/lprot_map.tsv 的功能名列原文,**零自造同义词**;L2.5 与
L-TEST 经实测各 0 处(不是本族),TC 族一字未动。

固件 22 文件 128 处(adc_task.c 21、phasor.c 22、phasor.h 13…),主机测试 13 文件 87 处(pha
sor_test.c
57…);设计文档指针新增 19 行,另 16 只文件本来就写着规划文档 ⇒ 不重复加。

**两条只有真改过 215 处才会踩到的坑,都写进注释规范实践**:
· 指针**不能接在原句尾部**——那会替原文一个未闭合的半括号封口,实测咬坏 App/algo/sample_ring.h 这类
  跨行句 ⇒ 指针一律**单独成行**;
· 号删掉会留下**叠词**(「自检失败闭锁 闭锁判定」「定值校验和 定值巡检」)⇒ 复扫并收口 4 处,措辞只用
  映射名本身;具体对象需要留住时写成「自检失败闭锁(采样故障闭锁)」。

自证(不靠嘴说):改前把 35 只文件原文备份到仓外 temp,逐文件比 `/*`、`*/` 计数、三类括号计数、行数增量
恰等于指针行数、全角括号增删相等、残留号 0 ⇒ **35/35 通过**;Lead 复核后跑权威 @build **0 错 0 警**,
Program Size `Code=233900 RO=26104 RW=1536 ZI=136808` —— **与三条道各自改前改后测的四数逐
字节同数**,
这就是「只动注释与文本」的机器证据;八套主机单测 exit 0,cppcheck 按钩子参数零发现,coding-standard 0。

文件头「修改记录」里的号**一并换名、不还原**(Lead 裁定):这些号是全仓退役的,留一个查无此号的引用比
留一条改过名的条目更坏——「冻结历史不回改」保护的是**别替历史改口**,不是保护一个再也查不到的字符串;
id-check 对变更记录行本就豁免,两种选择都不影响门禁。
2026-10-27 08:59:26 +08:00
wandering1 b1494eb10c feat(固件): 标定值语义 setter + 卷锁 fail-open 自检留痕 + 控制台编号写法整理
三批同笔的理由:它们是同一份权威构建(Linker run 04:5x,Code=233,900 / RW=1,536)里的内容,中间态从未
单独编译过,拆开提任何一段都没有对应的构建凭证。按道分述如下。

**① 算法层(ui-maint):写值与置脏成对,不留可单独调用的置脏口**。新增 run_par_cal_k_set() /
run_par_cal_b_set(),被拒时副本不动也不置脏(= 不承诺持久化);104 的 run_par_104_write() k/b 两支
同批改调 setter,函数内自己碰 s_dirty 的两处删净——**消除两份置脏逻辑才是本段的目的**。刻意**没有**新增
公开 run_par_mark_dirty():作者的理由我采纳并原文保留——「一旦存在就一定有人只调它」,与今天删掉的零消费
者接口是同一失效机理。另新增合法域唯一出口 run_par_db_range()、粗守上限 RUN_PAR_K_MAX_UV、毫→工程换算
单点 s_milli_to_eng(),并改正了头文件里「除以 1000 唯一在此」那条在加 db_range 后会变假陈述的说法。
**顺带满足 task-43 第①项**:adc_cal 落盘口的缺口由本段 setter 解决(写值必置脏),task-43 剩余项 = 可诊断
性与文档。

**② 日志层(log-maint):卷锁 fail-open 的 defaultTask 侧边沿留痕**。syslog_drain() 尾部紧跟既有
s_quiet_
drop 差值块之后读 vol_lock_get_stats(),水位新增才算一个 episode、每上电一条,投 SYSLOG_SELFTEST,文本
vollock failopen=%lu。三条硬约束都落了且**有牙**:失败调用点零改动(wdev.log 自己也要这把非递归卷锁);
不打错级、**不打 [ERR]**(断言里 g_sys_err_count == 0 就是机器判据,把「改成 DBG_ERROR」注入后四条用例
全红);锁层只自增、唯一写者消费。作者一度按我的要求准备造 obs_first_ms/obs_last_ms 字段,我撤了那条
要求——记录自带 ts 就是被观测时刻,**再造一个时间戳字段等于造第二个「看起来像发生时刻」的东西**。
成本 .bss +48 B、**零栈增量**(缓冲全静态),已由本笔权威构建的 after 表证实:9 条链全 PASS,
iec104Task 1,464 / margin 1,096、defaultTask 3,040 与提交态逐项一致。

**③ 控制台与中断(log-maint,纯注释/文档)**:b623a406 之后的编号写法整理,把裸形态号改为可校验形式,
零代码行为改动。

实测:@build 0 错误 0 警告;run_par 67/67、sys_log_mcu 141/141、console_log 套件零回归
覆盖率只增不减
(sys_log_mcu.c 410/413 = 99.3%、函数 22/22);cppcheck / coding-standard /
doc-links / bom / mojibake /
nested-comment 全 0;编号五项式错误差值 0、不可判定绝对数 **1,156**(上限 1,166 未动,本笔没吃余量)。
台账随本笔回填:ram_baseline --write 与 mem-numbers --write 同批(RW_IRAM1 80,920 B 61.7%
/
RW_CCM 57,376 B 87.9% / ER_IROM1 260,004 B 24.8%)。
2026-10-27 05:10:11 +08:00
wandering1 b623a406ad fix(栈·存储·UI 收尾): 断掉临界区↔断言幻影环回到 1,464,标定门控单点化,卷锁五态可观测
这四笔在主树里已经互相纠缠(同一次 @build 编译、同一份 .htm 度量),拆成四笔就不
存在任何一个被真编过的中间态,所以合一笔入库;下面按模块分段陈述,作者与出证归属
逐段写明。

—— 一、崩溃证据路径的整行独占收尾(log-maint-writer,task-26)——
上午那笔 1d4b6a17 之后,stack_report 报 iec104Task 静态最坏链 1,544 / margin 1,016,
低于 1,024 的 ISR 底线。真因不是新增局部缓冲,而是本模块与内核临界区之间新长出
一条环:taskEXIT_CRITICAL ⇒ vPortExitCritical ⇒ configASSERT ⇒ vApplicationAssertFailed
⇒ dbg_console_write_raw ⇒ 回到本模块。armlink 把这一整坨计入**每一个含临界区的
任务链**(vApplicationAssertFailed 的 Max Depth 由约 40 B 涨到 128 B + In Cycle),
所以九条链同涨约 80 B——同涨本身就排除了任何单个调用方。
改法两处:① 本模块三处窗口(取凭证 / 还凭证 / 整行入环)改用 CON_CRIT_ENTER/EXIT
(PRIMASK 保存恢复到局部变量;注释写全为什么不能直接 __enable_irq()——嵌套时会
替别人打开任务级临界区——以及屏蔽面变宽是有意为之);② 异常/终点钩子里那对
自证空转的 begin/end 摘掉(异常态 begin 放行但不持有、end 是幂等空操作,调它只有
成本没有收益),任务态 STALL 行保留 begin/end,这个区分写进两处注释与文档 §4.4.1。
实测四棵树逐个 .htm 解析(身份钉 tree + Linker run 时刻 + 产物来源):A=77779d49
链 1,456;B=1d4b6a17 链 1,464 / margin 1,096 PASS;C=含未提交钩子接线的工作树
1,544 / 1,016 FAIL;D=本轮修复后(Linker run 22:52)回到 **1,464 / 1,096 PASS**,
九条链齐降 80 B。断环图证:vPortExitCritical 由 136 B + In Cycle 变 8 B 且不再
In Cycle,con_tx_release 子树 152→8;Error_Handler 回到 280 + In Cycle = A 树同值
(既有发送环无人拆动)。顺带删掉 Src/freertos.c 崩溃路径里最后一个 HAL_Delay(200)
(该文件真实调用现为 0)。
测试:console_log 152→**153** 条(只增不减);换钉不删防——015 现在钉「PRIMASK
窗口 2 次、深度 1、内核临界区 0 次」,新钉 015c 绝不等待,160 注入点搬到
con_pm_hook,176 强化到未调度路径连 PRIMASK 窗口都不开;红线水位
con_pm_at_tx_max 与 con_uart_crit_at_tx_max 双 0;判据⑦(延后的行与当场直发逐
字节相同)170b/171/178 仍全绿。作者自报并纠正一处:换钉时曾把 TC-CONLOG-015b 改
编号,而 015b 在生产注释与文档里都被引用——已恢复「编号不退役、语义搬过去」。
覆盖率 App/log/console_log.c 199/200 → 256/257 行、21/21 函数(只增)。

—— 二、未标定闭锁判据收成单点访问器(ui-param-writer,task-16)——
「UA/UN/IA 三相 VALID 全置位才允许跑判据」这条门控原先在两处各自镜像实现
(protect_task.c 的 s_cal_locked 与 ui_data_feed.c 的 feed_cal_block),改一处另一处
静默失效且无门禁可照。现新增 adc_cal_prot_blocked() 落在 App/algo/adc_cal,DTU_BENCH
特例收进一处;两个消费者同批改调、本地副本删除。作者还查实并纠正了我先前一句
错判:全仓 App/app→App/task 的 include 实为 0 条,故访问器不能落在 protect_task。
新增 TC-ADCCAL-018 八条(含冷启动即闭锁),adc_cal 套件 99/99。

—— 三、共享卷锁五态可观测性(ui-param-writer,task-17)——
原状比登记簿写的更糟:五个可区分态(未调用 / try 超时 / 分片超时 / fail-open /
未持锁却 release)生产侧零留痕,且 vol_lock.c 的返回值注释与代码相反——
fail-open(锁没建成、互斥已失效却在读写盘)被返 1 **谎报成取到锁**,而那正是
vol_lock.h 记录的台架实证故障(并发写坏 FTL → 喂狗点饥饿 → IWDG 误复位)的前置。
锁层加四个 volatile 计数(16 B 静态,零新局部、零新 callee、零日志、零 FatFs)与
不取锁的 vol_lock_get_stats();13 处 try 调用点一字未动。**刻意不在锁层记时刻**:
记时刻要读 tick,等于给 defaultTask 取锁链添帧——诊断不值那几个字节;消费方若
自盖时间戳,那只能是被观测到的时刻而非发生时刻,.h 里已写明不得写成首次/末次。
四套本地假件各加 s_last_wait_to(字段名逐字一致),把「喂狗点取锁一律 timeout=0」
与「ftpTask 分片一律 100 ms」从注释纪律升级成会 FAIL 的断言;红-绿反证:临时把
sys_log_mcu.c 的 0u 改 50u → TC-SYSLOG-010/012 双红,把 lftpd_io.c 的 100u 改 0u →
TC-LFTPIO-034 红,两处按原串改回并用 SHA-256 证明逐字节还原。TC-VOLLOCK-015~019
共 45/45(无新桩)。

—— 四、UI 死接口清理(ui-maint-writer,task-6 收尾)——
删掉 ui_data_maint_ready():全仓零消费者、只有它自己的用例在读。**更值得记的是
它为什么能活过一整轮评审**:头注释写的是「页面用它决定这页能不能操作」,而页面
从来没用过它——注释陈述的是意图,评审读的是意图,门禁读的是可达路径,两者都不
反驳「意图未实现」。作者对「连用例一起删」做了显式抗命:TC-UIDATA-025 的 13 条里
只有 4 条读那个死口,另 9 条钉的是真防线(六口未注入安全返回 / 残表整表拒绝 /
被拒不覆盖已生效的好表),故删冗余的 025a、把 025i/025k/025m 换成用 reset_req()
的可观察返回值判定,性质不丢。ui_data 套件 244 → 243(净减 1),黄金 40 页与
池 5448 B 未变(该刀零像素影响,参考图无 diff)。

—— 门禁与未跑项(本笔如实留账)——
cubemx-survival 基线已 --write(漂移 6 项全部是上述意图内区域:断言/栈溢出钩子
实现、看门狗模块行等),基线文件同笔入库,随后 --check 通过。
本笔未跑的钩子只有两条:mem-numbers 与 mem-budget——磁盘 .map 出自 22:52 那次
构建、含尚未入库的 UI 与工具改动,与 HEAD 台账必然不同码;按仓库既有约定允许
--no-verify + 正文留证,回填在紧随的台账一笔统一做(含 ram_baseline --update 与
覆盖率基线两条 [NOTE]:ui_data.c 65→316、iec104_comm.c 36/36)。
两条已挂着的账:① id-check 不可判定引用 1,162 / 上限 1,166,**余量只剩 4**,
主要吃进者是我今天推进的 UI 那笔(68 条文本断言的注释引用),账在 Lead;
② 崩溃注入腿(故意复位)台架复验未跑,需先由代码道提交触发器,且判据只判原子性
不判 [ERR]=0——IPSR 路径的主张归主机侧套件,硬件照不出来。

产物身份(按 D 表要求钉死,避免数字与树脱钩):本笔包含的固件树就是那张 D 表对应的
那一棵——MDK-ARM/.../STM32F407-Demo.htm 的 mtime = 2026-10-26 22:52:12(.htm/.map 按
约定不入库,故把时刻写进正文)。提交前在本树复跑 stack_report.py:exit 0,
iec104Task 1,464 / margin 1,096(42%)PASS、defaultTask 3,040 / 2,080(40%)PASS,
与 D 表逐项一致;本次运行不含任何未提交固件源码之外的新改动。
2026-10-26 23:31:05 +08:00
wandering1 0f7b5a87fb chore(编号): 存量编号全量转语义短语,门禁识别面与语料同批重打
登记簿、文档与代码注释里的存量字母加数字编号(N-x / S-x / T-x / E-x / A-x / 卡号)
一律改写为语义短语,净删 2,028 处引用;删除基线与待确认、并行分道方案、排期详述、
采集保护收尾 4 篇(内容已并入 docs/任务规划/README 与登记簿)。

门禁机器与三张账同批重打:check_ids.py 新增变更记录行豁免与第二根护栏
undecidable_total_ceiling;check_test_traceability.py 只加 stdout/stderr UTF-8
reconfigure(TC_RE 未动);check_cubemx_survival.py 的 --write 固定 newline=LF;
id_registry / id_aliases(+19 条 retired-to-phrase)/ id_known_backlog 重打。

test/ 56 个文件同步 TC 标签语义化,其中 18 个 TU 改了 CHECK / printf 里的标签文字,
是本批唯一改变构建产物的文件集合。

为什么合成一笔、不拆四笔(实测撞闸,非偏好):pre-commit 跑钩子前会 stash 未 staged
部分,拆开后中间提交必然是「新规则 + 旧语料」——实跑可判定 85.15% < 基线 86.00%、
不可判定 1,453 > 上限 1,166,编号门禁直接拦下。编号识别面与它描述的语料只能同码移动。

实跑基线(工作区全量):754 文件 / 8,230 处编号字面量 / 可判定 7,079 = 86.01%
(基线 86.0%,容差 0.1pp)/ 不可判定绝对数 1,151(上限 1,166)/ 校验 1-6 错误级 0 /
告警 = 悬空 2(App/algo/freq.c 的 S2,属 §4.4 同号不同义)+ 孤儿 50。

基线从 84.0 抬到 86.0 的理由见 docs/门禁说明/id-check.md §7.6:本批真删了 2,028 处
引用,可判定面随真实内容上升,不是把分母做小。同批新增排除 docs/硬件平台/ 语料,使
识别面少 264 处——芯片手册位号与网表料号不属编号空间(registry 有 excluded_paths_note)。

⚠ 余量只剩 0.11pp(约 10 处)与绝对数 15 处:把「可判定的引用」改成散文会立刻撞第二
根护栏。另遗留一项:id_aliases 里 retired 的 N / S / T / A 别名没有 scope(U1~U5 有),
今后有人新写一个 A-4,校验 3 不会响,只能靠人,建议下批补 scope。

固件不变证据:115 个 .c/.h 剥注释并归一字符串后与 HEAD 逐字节全等,残留代码差异 0;
App / Src / Drivers 的字符串字面量零改动。@build 0 错误 0 警告;40/40 主机套件、2,889
断言全通过;覆盖率 line 89.2% / func 92.6%;pre-commit 48 钩子 --all-files 全绿;
check_doc_links --all 通过(176 文档,章节引用无法判定 0);逐字节卫生核过:14 个带
BOM 文件与 HEAD 一致、0 个 CR、0 个 U+FFFD,字符串字面量纯 ASCII。

.cubemx_survival_baseline.json 的 watchdog-module 哈希 56bf27 变 2bb051 属合法:
Src/freertos.c 的 USER CODE 区内只有注释文字随编号改写,代码未变。

同批带上体积同码凭证与 RAM 台账行(@build 之后盖戳):RW_IRAM1 79,008 B / 60.3%,
RW_CCM 57,376 B / 87.9%,阈值 92%。
2026-10-26 12:28:14 +08:00
wandering1 e7f28502bc refactor(NET): netMsgQueueHandle 收进 net_socket 私有,改为创建后绑定
结构债 S-2 的最后一步——**该族的 24 处手写跨模块裸 extern 就此全部清零**。

队列对象仍由 CubeMX 在 `MX_FREERTOS_Init()` 创建(**创建点不可外移**:
`osKernelInitialize()` 之前的任何创建类 API 会杀死启动,见
`docs/架构设计/项目启动顺序管理.md`);改为创建后立刻在 `Src/freertos.c` 的
`USER CODE BEGIN RTOS_QUEUES` 区调用 `net_msg_queue_adopt(netMsgQueueHandle)`,
把句柄交给唯一使用者。`net_socket.c` 内改用 `static osMessageQueueId_t
s_net_msg_queue`(21 处引用改名),BSP 对该全局变量的裸 `extern` 消失——现在
`netMsgQueueHandle` 只出现在生成文件自己的两处(定义 + 创建)。

两个刻意的设计决定:
① **不新建第二个队列**。自建队列 + 删 `.ioc` 里的 netMsgQueue 也能收口,但要
   CubeMX 重生成(Ask-first),过渡期还会同时存在两个队列,白占 CCM 堆里
   8 × `net_msg_t` 的空间——CCM 正是当下 87.9% 的红线。故选"创建后绑定"。
② `adopt()` **拒绝重复绑定、保留首次句柄**。真出现两处绑定时,静默换句柄会让
   已入队的请求留在旧队列里永不处理;拒掉第二个反而更容易暴露。绑定前的判空
   是真实防线:丢了那一行,后果是"所有 net_* 请求被丢弃、网络全线静默不通",
   不是崩溃。

**防回退**:`check_cubemx_survival.py` 新增存活项 `net-msgq-adopt`(region
`RTOS_QUEUES`、`must_contain=["net_msg_queue_adopt"]`),易失清单 29 → 30 项全部
到位;基线已重建(有意的 USER CODE 区改动,按脚本文档流程 `--write`)。

**体量**:`Code` 213,204 → **213,236 B(+32)**、`ER_IROM1` **231,816 B(22.1%)**;
`RW +4 / ZI −4` → `RW_IRAM1` 恒 **75,264 B(57.4%)**、`RW_CCM` 恒 **57,376 B
(87.9%)**、`RW+ZI` 总量 132,688 B 不变(没有多占一个字节 RAM)。

**验证**:`@build` 0 错 0 警告;`@test` PASS——624 ms 到 `net init: OK`、`i104:
listening on 2404`、无 `[ERR]`/Fault、`heap free=15800 min_ever=8464` 逐项不变。
另在真机跑了一次 FTP 控制通道往返:220 → `USER admin` 331 → `PASS admin` 230
→ `PWD` 257 → `TYPE I` 200 → `QUIT` 221。每条命令都是一次过队列的
net_recv/net_send,证明绑定路径真在跑;`.map` 里 `freertos.o(MX_FREERTOS_Init)
refers to net_socket.o(i.net_msg_queue_adopt)` 证明镜像含该行。

⚠ **顺带揪出一条测试工具漂移(本次未修,等定夺)**:
`test/host/ftp_up_dl_test.py:123/126` 仍写死 `USER anonymous` /
`PASS test@test.com`,而设备自 N-19(2026-10-11)起按 `/config.ini [ftp]` 校验
admin/admin(SHA-256 `pwd_hash`)→ 该脚本必然登录失败。它是手工工具、不在任何
pre-commit 钩子里,所以 11 天没人发现,而 `docs/测试说明/FTP_Test_Guide.md` 把它
列为"推荐入口"。建议加 `--user/--password`(默认 admin/admin),并连
`ftp_speed_test.py` 一起核。

数字联动:两份 `data/` 快照重跑、`ram_baseline --update/--write`、
`check_mem_numbers --write`、FLASH 与任务栈两张配图常量重算并重新生成(逐文本按
字号与锚点复查越界 = 0)、报告 §1.3/§5.1/§5.4 与部署文档 §3.3 同步。报告 §0.4 的
S-2 行按「完成即销项」改写为已闭环,§9 拆出独立 S-2 行标 ✅。

门禁:`@build` 0/0、`@test` PASS、`layer-deps` / `cubemx-survival` / `mem-numbers`
(本次改到台账受管区,scan 已过)/ `mem-budget`(57.4% / 87.9%)/ `task-table` /
`doc-links --all`(146 文档 0 问题)/ `id-check --strict`(增量拦截通过、可判定
82.84%、存量债 640)全绿;14 个文件字节卫生 BOM 无 / CR 0 / U+FFFD 0 / 无尾空格。
未推送。
2026-10-22 20:01:40 +08:00
wandering1 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。未推送。
2026-10-22 19:09:20 +08:00
wandering1 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
2026-10-21 11:39:53 +08:00
wandering1 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 区
2026-10-21 11:39:52 +08:00
wandering1 8cd815d046 docs(ram): N-33 销项回填——台账登记抬栈 +1536 B,M1 台架闭环达成
- RAM预算台账 §6:defaultTask 1024→1280 / timeSyncTask 512→640 words,
  堆内用量 +1536 B(配额 56 KB 不变);min_ever 预算 8464 = 实测吻合
- RAM使用分析 §2.3:N-33 注记 + 表更新(default 3016/2104 41%、
  timeSync 1264/1296 50%、netTask 复测 1944(N32 监听模块化后链)、
  adcTask 复测 1320)
- Src/freertos.c 栈注释:netTask 1872→1944、adcTask 补 2026-10-12 复测值
- W1 卡:N-33 销项删行;M1 判据全满足 ✅ 达成;mermaid 台架道清空、
  M1((✅));B8/B9 行转 🟦(worktree 进行中,方案已审)
- 登记簿:N-33 行删除(证据已沉淀两份内存文档 + W1 卡 §1 指针)
- 合并侧已完成:merge c95a9cd(done N33,9 任务 0 FAIL + @test PASS)
- 验证:doc-links 全绿(142 文档)
2026-10-12 18:36:04 +08:00
wandering1 51bc325b57 fix(stack): N-33 抬栈收口 defaultTask/timeSyncTask 栈余量(2 FAIL -> 0 FAIL)
既有债收口(非新引入):B7 定值持久化把 defaultTask 静态最坏链推到
3016 B、timeSyncTask 推到 1264 B,两者跌破 stack_report 判据
(余量 >= max(1024 B ISR, 配置 x 30%))。本轮只抬栈,不动调用链。

前基线(stack_report,9 任务):
- defaultTask  cfg 4096 B / 静态 3016 B / 余 1080 B (26%)  FAIL
- timeSyncTask cfg 2048 B / 静态 1264 B / 余  784 B (38%)  FAIL
- 其余 7 任务 PASS(net 2112/1728、ftp 1456/2640、ui 1336/15048、
  test 736/7456、adc 1320/1240、iec104 1456/1104、protect 872/1176)

改动:
- defaultTask 1024 -> 1280 words(4096 -> 5120 B):余 2104 B / 41%
- timeSyncTask 512 -> 640 words(2048 -> 2560 B):余 1296 B / 50%
- 后基线:9 任务 0 FAIL(stack_report 退出码 0)

堆开销(任务栈来自 FreeRTOS 堆,.map 静态数字不变):
- defaultTask +1024 B、timeSyncTask +512 B,合计 +1536 B
- 台架背书基线 heap free=17936 / min_ever=10000 B(B6),抬后
  min_ever 预计 ~8464 B,仍远高于 3072 B 告警线

防丢失(CubeMX 存活 L1 纪律):
- STM32F407-Demo.ioc 的 FREERTOS.Tasks01 同步改 1024 -> 1280
  (.ioc 是 CubeMX 生成任务栈值的事实源,未跑重生成)
- Src/freertos.c 生成区 .stack_size 与 .ioc 保持一致
- USER CODE BEGIN Variables 核算注释块补 N-33 依据(栈值理由唯一落点)
- .cubemx_survival_baseline.json 经 --write 重建(仅 ioc-task-stacks 一行)

task-table 生成区随栈变更再生成(README.md + AGENTS.md 的
TASK_TABLE 锚点区各 2 行,锚点区外无任何改动)。

验证:@build 0 错误 0 警告(Program Size 与改前逐字节一致);
ci_local 全绿(L0 + L0.5,826/826 断言);stack_report 前后各跑一次。
台架 @test 与串口 [STACK] 水位复测在提交后单独跑。
2026-10-12 17:47:15 +08:00
wandering1 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 复测。
2026-10-12 12:36:23 +08:00
wandering1 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 已销项。
2026-10-11 18:50:24 +08:00
wandering1 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 已同步置完成。
2026-10-11 01:28:20 +08:00
wandering1 9bbe117f97 adc: 节拍源 TIM6->TIM3 + ADC1 走 DMA 乒乓双缓冲,消除 2 ms 忙等(P1-5 单拍硬上界办结)
用户选定最彻底方案(B2):DMA + 定时器 TRGO 硬件触发 + 消费上一拍
已完成的半区。对应 P1-5 拆出的"单拍硬上界",现已办结。

硬件事实更正(查 CubeMX 器件库 + 本仓 HAL 头证实):F4 上 ADC1 的
外部触发清单里没有 TIM6/TIM7 TRGO(只接 DAC)。故 1 kHz 节拍源由
TIM6 改为 TIM3(PSC 83 / ARR 999,TRGO=UPDATE),同一个更新事件
同时 ① ISR 脉冲 TPAFE CONVST ② 经 TRGO 触发 ADC1 一轮 9 通道
③ 置位 ADC_WAKE_FLAG 唤醒 adcTask。TIM6 从 .ioc 整体移除。

代码:
- Src/tim.c/h:新增 MX_TIM3_Init(含 MasterSlaveMode),删 htim6
- Src/adc.c:ExternalTrigConv=T3_TRGO + EDGE_RISING +
  DMAContinuousRequests=ENABLE;MspInit 挂 hdma_adc1(DMA2_Stream4
  循环模式)。DDS 位关掉 = 一轮只发一次请求,静默丢 8 路
- Src/dma.c:DMA2_Stream4 NVIC 优先级 6(CubeMX 换流会把它重置为 0,
  优先级 0 会抢占 FreeRTOS 临界区,违反"外设中断 ≥5")
- Src/main.c:周期回调加 TIM3 分支;stm32f4xx_it.c 向量同步
- App/algo/adc_input.c:stm32_scan() → stm32_take(),逐通道
  PollForConversion 全删;乒乓半区由完成计数奇偶推出(只读一个
  32 位量 → 与 ISR 无竞态);STM32 侧数据固定滞后 1 拍
- App/task/adc_task.c:心跳日志拆出四类计数

观测性:adc1_seq(完成计数)/ adc1_gap(seq 前进 >1 = 丢帧)/
adc1_err(连续 ≥2 拍无新帧 = 停摆)/ adc1_hw(HAL 错误回调)。
单拍无新帧是消费者相位伪影(DMA 完成落在唤醒后 ≈67 µs),不计故障。

验证:
- 主机单测 79 → 101 全绿;反向验证四连均咬(半区奇偶取反 11 条、
  停摆拍置 valid 4 条、STALL_RUN_MAX 改 1 为 6 条、gap 阈值 1 条)
- @build 0 错 0 警,Code 256872 → 257660
- @test PASS:adcp 122 µs → 8 µs、adc1_err=0、adc1_hw=0、
  adc1_gap=27/20002 拍、adc1_seq 与 seq 恒定偏移 2
- stack_report 7/7 PASS,adcTask 832 B / 余 59%(不变)
- cubemx-survival 新增 5 项审计(TIM3 分支 / T3_TRGO / DDS /
  DMA 挂载 / 流优先级),28 通过 0 失败

文档:ADC 采样节拍设计说明新增 §11;看门狗停摆分析 §4.4 与 §8 收口;
算法规划 L1-1/L1-3、通道映射、测试说明、各 README 同步。
2026-10-11 00:31:33 +08:00
wandering1 9231a3c22c adcTask 事件驱动消费(P1-5 方案 a)+ 补 F4 ADC 上电自校准 + 修正 2 ms 忙等过期表述
P1-5 方案 a(事件驱动消费,Task #32):
- TIM6 1 kHz ISR 除触发 CONVST 外再调 adc_tick_irq_notify(),置位
  ADC_WAKE_FLAG;adcTask 循环尾改 osThreadFlagsWait(osWaitForever),
  删除 ADC_TASK_BEAT_MS 定时轮询
- adcTask 优先级 Normal(24) -> AboveNormal(32)(Src/freertos.c USER CODE 区)
- 补消费者就绪门(规划未预见):TIM6 在 app_main_init 就启动,比调度器
  早约 100 ms,未就绪时 ISR 不得 osThreadFlagsSet
- 实测 6 次上板:idle 由 1~649 降到 0/20000 拍,frames 1000.0 Hz,
  seq-frames=7 正是就绪窗口;UI 侧 uip/uiw/uis 无退化

补 STM32F4 ADC 上电自校准(此前项目从未做过):
- 核查证实裁剪版 HAL 无 HAL_ADCEx_Calibration_Start、裁剪版 CMSIS 头无
  ADC_CR2_CAL -> 按 RM0090 13.3.6 在 Src/adc.c 的 USER CODE 区手写
  adc1_calibrate(),MX_ADC1_Init() 末尾调用
- 新增 cubemx-survival 审计项 adc1-calibration-call / -impl(清单 21->23)
- 实测校准前后同一拍 STM32 侧 6 路同向偏移 +10~+63 LSB,TPAFE 侧不变

修正两处过期表述(实测反证):
- 原文 9 通道全超时最坏 = 18 ms 连占 有误:stm32_scan() 在首个超时处即
  Stop+return,单拍上界 = 一次超时约 2~3 ms
- adcm 约 2.1 ms 的峰值归因由 ADC 采集改判为每 10 s 一次的心跳日志;
  6 次对照 adcp = 122 us(无超时)/ 2209 us(超时 1 次)
- 同步修正 adc_task.c 两处过期注释;新发现超时拍 STM32 侧静默沿用
  上一拍值的正确性代价,硬化排序记入 4.4 / 10.4(未实施)

验证:@build 0 错 0 警(Code 256728 -> 256868);@test 6/6 PASS;
stack_report 7 任务全 PASS(adcTask 832 B / 余 59%);18 钩子全绿
2026-10-10 22:41:19 +08:00
wandering1 970e574433 feat(adc): 1 kHz 采样节拍改由 TIM6 硬件定时器触发
- CubeMX 加 TIM6(PSC=83 / ARR=999 / ARR 预装载 / NVIC 抢占优先级 6)
- Src/main.c 回调加 TIM6 分支触发 CONVST(USER CODE 区)
- app_main.c 用 HAL_TIM_Base_Start_IT(&htim6) 替换单次触发
- adc_task.c 退化为纯消费者(1 ms 轮询仅作消费节奏)
- @build 0 错 0 警;台架 @test 验收待做
- 同步 ADC采样节拍设计说明 / 继电保护复现规划 / AGENTS / TPAFE README
2026-10-10 15:24:02 +08:00
wandering1 883c9dd0cc feat(adc): B1 实现 ADC 采集链路(adcTask + 看门狗)
B1(ADC 采集链路)落地,消化 P1-1:
- adc_task.c:空桩 -> 真实消费者。每 1ms 触发一次 CONVST,
  用 tpafe5160_snapshot() 原子取数(AGENTS 铁律)+ 帧统计 +
  每 10s 心跳日志。只取数,不做保护运算。
- Src/freertos.c:手工创建 adcTask(512 words / Normal,落
  USER CODE 保护区,同 timeSyncTask 先例)。
- task_watchdog:新增 TASK_WD_ADC;required_mask 产品 0x37 ->
  0x77、ENABLE_HW_LAYER_TESTS 0x35 -> 0x75。
- default_task.c:栈水位探针增列 adcTask(extern + 表项)。
- 脚本:stack_report.py 增 ROOTS/RUNTIME_ALIAS;gen_task_table
  增 adcTask(README/AGENTS 任务表已 --write)。
- 单测:watchdog_test.c beat_all/掩码断言同步(39 断言全绿)。
- 文档:待处理内容/看门狗设计/RAM 方案/继保规划 同步。

验证:@build 0 错 0 警;stack_report 静态最坏链 504B(余 75%);
pre-commit 全绿。剩 @test 实机闭环。
2026-10-10 14:33:32 +08:00
wandering1 e89fe54a97 重写看门狗设计说明为现状说明:删立项前旧描述、补FTL心跳路由与取证机制、修掩码与复位归因 2026-10-10 10:57:31 +08:00
wandering1 0779d3a075 栈整改不抬栈:删旧档迁移、FIL静态化、日志行缓冲按模块收紧、钩子脱离HAL,defaultTask链5312→2776B 2026-10-10 10:17:00 +08:00
wandering1 29df7bf8fb 4 个 Fault Handler 迁入 USER CODE BEGIN 0(L3→L2):生成区恢复 CubeMX 原样,重生成零 diff
CI / L0 静态门禁 (pre-commit) (push) Has been cancelled
CI / L0.5 主机侧单测 (MSVC) (push) Has been cancelled
2026-10-10 02:02:58 +08:00
wandering1 e2e1d0fd42 IWDG 延后启动改走宏改名(L3→L2):生成调用变空操作,重生成后不再需要手工删 2026-10-10 01:30:47 +08:00
wandering1 53bd9af02e 对齐 CubeMX 输出:提交第三方与生成文件的文件末尾空行(85 文件,零逻辑变化) 2026-10-10 01:05:15 +08:00
wandering1 5eed2151de CubeMX 生成 ADC1(9 通道)+ 复原重生成定制,FreeRTOS 加固迁 L1、钩子落 USER CODE 4/5,门禁豁免生成文件空白改写 2026-10-10 00:53:20 +08:00
wandering1 ed463716f6 netTask 栈 1024→960:按静态最坏链核算并同步 .ioc/README/审计基线
静态最坏链 2664B(日志主导:链上 5 帧各含 192B __con_line + 尾部 696B)
3840B 配置下余量 1176B(30.6%),过 stack_report 规则
net_drain_chip_rx scratch 静态化实测仅省 16B 栈、反增 256B BSS,已回退
.ioc FREERTOS.Tasks01 同步 960(L1 记账,重生成不丢)
2026-10-09 17:14:52 +08:00
wandering1 e0b02d397c 修复 P2 全部 10 项:错误传播/竞态/门控/文档失真
待办池 docs/待处理内容.md §3.2 的 10 个 P2 全部闭环;逐项落代码 + 注释说明。

P2-1  cfg_file: 受管键行超 CFG_LINE_TEST_MAX 拒绝保存(防重复键行)
P2-2  ch395f: DMA 失败传播状态 + 锁存通道故障 + 读不拷不可信数据
P2-7  net_select: LISTENING 不再恒判可读(消除 select 忙轮询地雷)
P2-8  time_sync: 核实 L3 pending 改写已闭环(net_recv_to 分片 + 总预算)
P2-9  sys_log: 挂载改幂等 + 卷锁,defaultTask 2s 重试建 /log
P2-10 sys_log: s_read_raw 纳入卷锁 try(读者/写者 unlink 互斥)
P2-11 net_task: RECONFIG 改 osEventFlagsWait 原子取走 + 清除
P2-12 app_cfg: APP_*_ENABLE 如实标注为未接线占位,删“开关”说法
P2-13 freertos: 产品构建 vTaskDelete(testTask) 回收 8KB CCM 栈
P2-15 download.bat: 先删旧日志 + 增“未产出日志”判定

P2-13 用 USER CODE 区回收而非生成区 #if 门控:生成区改动会被 CubeMX
重生成覆盖,本方案重生成不丢。P2-12 因产品定义 B0 未定、APP_NET_ENABLE
无单一接线点,按修复建议备选(删“开关”说法)处理。

验证:@build 0 错 0 警;主机单测 watchdog 39/39 + sys_clock 100/100 +
cfg_file 149/149(新增 TC-CFG-044);pre-commit --all-files 17/17。
2026-10-04 08:30:30 +08:00
wandering1 3cc08f5d53 实机测试规划改造为执行判据说明:删除一次性台架窗口状态(§0.5取证记录)与规划框架,A1~A4代码状态按代码核对改写,16处外部引用重指向模块文档 2026-10-02 23:46:27 +08:00
wandering1 930215f81a 修复IWDG超时未配置与dhara resume回滚:看门狗误复位与复位后写入全部丢失,台架全量自检PASS 2026-10-02 20:48:30 +08:00
wandering1 8a18e388c7 四个 Fault 全部采集现场:MemManage/BusFault/UsageFault 由空死循环升级
原状:HardFault 已有崩溃采集,但 MemManage / BusFault / UsageFault 仍是空
while(1) —— 这三类故障发生时日志完全静默,且因 SHCSR 默认未使能,实际会
被升级成 HardFault,报告出笼统的 "HARDFAULT"、看不出根因。

改动:

- Src/stm32f4xx_it.c:三个 Handler 升级为手工 __asm 版(取 MSP/PSP 帧指针)
  -> B 到 per-fault C 入口 fault_entry_{mem,bus,usage} -> hard_fault_report()。
  hard_fault_report 增加 tag 参数,日志统一为
  "[ERR] <TAG> PC=.. LR=.. xPSR=.. R0-R3=.. CFSR=.. HFSR=..[/BFAR][/MMFAR]"。
  生成实体经 #define X X_Gen 改名保留,链接器各移除 2 字节(.map 已验)。
  三个各带独立锚点 MEMFAULT/BUSFAULT/USAGEFAULT-ANCHOR。
- 新增 fault_handler_enable()(USER CODE BEGIN 1 区):使能 SHCSR 的
  MEMFAULTENA/BUSFAULTENA/USGFAULTENA。声明入 Inc/stm32f4xx_it.h,调用在
  app_main_init() 第一行(纯寄存器写,不依赖日志/时钟)。
- 刻意不启用 CCR.UNALIGN_TRP / CCR.DIV_0_TRP:会把普通 bug 升级成死机,
  对本项目弊大于利(说明写进函数注释)。

实现约束(本轮踩坑):ARMCC 的 __asm 块取不到 C 的数据符号(ADR r1, xxx_tag
报 A1516E: Bad symbol,去 static 也无效),也无法给 C 函数传字符串参数,
故故障名必须由 C 侧 per-fault 入口带上。

配套:

- check_cubemx_survival.py:新增 fault-handlers-3 / fault-handler-enable 两项,
  UNPROTECTED_LEGACY 清掉三个 Fault(WARN 2->1),清单 16 -> 18 项。
- AGENTS.md:新增"4 个 Fault 全部采集"条目;ARMCC 汇编条目补 A1516E 第 3 坑;
  校验标记补 [ERR](四个 Fault 日志都以它开头 -> 一律判 FAIL,刻意)。
- 看门狗设计说明.md:§6.1 补 4 条 Fault 标记与 @test 禁项关系;
  §10.2 L3 清单与四个 Fault 采集小节;§11 结论表与变更记录。
- 待处理内容.md:新增 N-03d(已完成),N-03c 补第二次重生成结论。

验证:@build 0 错误 0 警告(Flash +156 B,RAM 无变化);pre-commit 13 钩子
全通过;审计 18 通过 / 1 警告 / 0 失败。
2026-09-29 09:16:19 +08:00
wandering1 67d26ac37a 修正 CubeMX 重生成防丢失机制:审计脚本实测有效,恢复 5 处被覆盖定制
第二次重生成验证了审计机制,并证伪了上一轮的一处假设:

- 审计脚本 check_cubemx_survival.py 准确检出全部 5 处覆盖(16 项中 5 FAIL),
  机制有效;Src/main.c 复位原因锁存(USER CODE BEGIN Init 区)完好,
  是"USER CODE 区有效"的正向证据。
- 关键发现:CubeMX 本次换了一代中断函数模板(旧 HardFault_Handler /
  HardFault_Report 自造区 → 新函数体内 HardFault_IRQn 0 / W1_HardFault_IRQn 0),
  "生成区之外的自造标记区"同样不被保留,旧假设被证伪。

恢复方案(第二次升级):

- stm32f4xx_it.c:报告实现迁入 USER CODE BEGIN 0(区名从未变过的标准保护位);
  Handler 本体改为生成区整函数替换,用 #define HardFault_Handler
  HardFault_Handler_Gen 把生成实体改名保留,链接器自动移除(.map 实证
  Removing ... (2 bytes)),向量表指向手工 __asm 版(0x080001a1,18 字节)。
- iwdg.c:去掉 HAL_IWDG_Init() 调用,补 IWDG-DEFER-START-ANCHOR 锚点注释。
- FreeRTOSConfig.h:恢复 FREE_RTOS_CONFIG_HARDENING 块(两个加固宏)。
- freertos.c:补回两处任务栈中文注释(栈值未丢,.ioc 已同步)。

配套:

- check_cubemx_survival.py:hardfault-handler 改 wholefile + 锚点检查;
  UNPROTECTED_LEGACY 清单更新。
- AGENTS.md:新增"CubeMX 换模板"与"ARMCC 内联汇编语法"两条铁律,
  以及"uvprojx 被 Keil 自动改写不入库"条目。
- 看门狗设计说明.md:§10.1 补第二次重生成验证结论与模板换代发现,
  §10.2 L2/L3 全面改写(自造区名不可依赖)。

验证:@build 0 错误 0 警告;pre-commit 13 钩子全通过;审计 16 通过 / 2 警告 / 0 失败。
2026-09-29 07:52:39 +08:00
wandering1 7feeea6c56 实现独立看门狗:CubeMX 配置 IWDG + 任务心跳位图,恢复三处被覆盖定制
经 CubeMX 图形界面启用 IWDG(Prescaler=64 / Reload=1249,标称 2498ms /
最坏 1701ms),并落地心跳位图判定、各任务埋点、RCC_CSR 复位原因上报与
configASSERT 改造。重生成覆盖的既有定制已全部恢复。

P0(开机死循环):HAL_IWDG_Init() 内部立即启动看门狗,而 CubeMX 把
MX_IWDG_Init() 插在 app_main_init() 之前——该段 NAND/RTC/ADC 初始化耗时
数秒无喂狗点,按 2.5s 超时必然复位。改 Src/iwdg.c 为只填参数不启动,
启动移交 task_wd_start(),由 defaultTask 在存储 bring-up 完成后调用。

恢复的三处定制(重生成覆盖):
- Src/stm32f4xx_it.c:HardFault_Handler 崩溃现场采集被打回空 while(1)
- Inc/FreeRTOSConfig.h:栈溢出检测与堆失败钩子两个宏被整块删除
- Src/freertos.c:三处任务栈实测记录中文注释丢失(数值未丢)

新增:
- App/util/task_watchdog.{c,h}:心跳位图 + 抽样判定 + IWDG 延后启动
- time_sync.c 长等待切片:net_recv_to 单次可睡满 30s 预算,切成 200ms 片
- Src/main.c 复位原因锁存(读后即清 RMVF,防残留误判)

埋点:defaultTask(唯一喂狗者)/ netTask(含 PHY 等待循环)/ uiTask /
timeSyncTask。ftpTask 首期剔除掩码,待二期改 lftpd。

门禁:build 0 错误 0 警告;pre-commit 10 钩子全通过;Flash +2956B / RAM +40B。
2026-09-29 07:22:04 +08:00
wandering1 22559365b9 整理 App 与 test 目录:按职责分子目录并同步全库引用 2026-09-26 12:52:39 +08:00
wandering1 39bd06adea 为自建代码目录补齐 README,建立目录级导航体系
- 新增 26 份目录 README:App/(+log,task,util,protocol)、Drivers/BSP/(+8子系统)、
  Src/、Inc/、scripts/、tools/(+6子工具)、test/、MDK-ARM/、simulator/(+sim,tests)
- 每份含:定位、文件清单表、关键约束/陷阱、指向 docs 权威文档
- 第三方库与生成代码目录排除(CMSIS/HAL/Middlewares/Lib/SDL2)
- docs/文档规范.md 新增 §1.1b 代码目录 README 约定;根 README 目录结构加入说明
2026-09-26 12:25:36 +08:00
wandering1 d0cbeb6b5b 控制台日志实现迁出HAL生成文件至App/log并新增设计说明;defaultTask任务体迁至App/task,freertos.c恢复纯CubeMX接线形态 2026-09-25 01:32:09 +08:00
wandering1 e7d6318250 控制台写者循环节奏500ms改50ms:日志时延收紧到50ms内,LED心跳与配置2s轮询改tick基准保持等效 2026-09-24 23:54:48 +08:00
wandering1 3763e699dc 控制台改单写者发送:defaultTask唯一发串口其余任务写环形缓冲,杜绝日志交错与脏指针入UART;溢出钩子加指针窗口校验、崩溃上报改显式长度 2026-09-24 23:47:23 +08:00
wandering1 1d2a53bbc9 E-31修复:dhara resume失败按错误分类(仅真空白判新卷),mount失败自检上报+主循环有界重试 2026-09-21 18:38:23 +08:00
wandering1 bbdd059e25 修复就绪屏障位被消费致FTP永不监听;新增栈可观测(水位探针+静态调用图报告)并补FTP实测 2026-09-21 04:26:52 +08:00
wandering1 2ef1e1f0dd 同步CubeMX 6.18重生成的HAL/CMSIS/FreeRTOS vendor与工程配置(.ioc/.uvprojx/.mxproject及生成Src/Inc)基线 2026-09-21 01:26:09 +08:00
wandering1 a7d4339e6f CCM扩容FreeRTOS堆+DMA阈值1024防栈缓冲进CCM+HardFault现场报告与栈/内存钩子+修defaultTask栈溢出+LVGL绘制缓冲护栏+存储套件05/06与恢复模式 2026-09-21 00:47:58 +08:00
wandering1 d77747ec43 移除FTL全部临时诊断代码(raw持久性测试/bind dump/proglog/探针窗口/指纹/扫描)保留硬化项 2026-09-20 13:31:15 +08:00
wandering1 6084af8fe6 修复无限重格式化真根因:探针名.fschk在FF_USE_LFN=0下恒返FR_INVALID_NAME且误入重格式化集合 2026-09-20 13:03:47 +08:00
wandering1 32283de45b mkfs全程erase/prog逐条追踪窗口(proglog/eraselog):定位绑定页内容被改写的元凶 2026-09-20 11:20:46 +08:00
wandering1 66fc48cd98 新增map绑定转储诊断(dhara_map_find+裸读绑定页):跨boot对比定界树分歧与数据丢失 2026-09-20 10:48:47 +08:00
wandering1 93a789f87b 重格式化前清空FTL map树(nand_ftl_format):根治新旧树混合致复位后FAT探针失败的重格式化死循环 2026-09-20 05:36:10 +08:00