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
|
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
|
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
|
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
|
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
|
3763e699dc
|
控制台改单写者发送:defaultTask唯一发串口其余任务写环形缓冲,杜绝日志交错与脏指针入UART;溢出钩子加指针窗口校验、崩溃上报改显式长度
|
2026-09-24 23:47:23 +08:00 |
|
wandering1
|
a7d4339e6f
|
CCM扩容FreeRTOS堆+DMA阈值1024防栈缓冲进CCM+HardFault现场报告与栈/内存钩子+修defaultTask栈溢出+LVGL绘制缓冲护栏+存储套件05/06与恢复模式
|
2026-09-21 00:47:58 +08:00 |
|
wandering1
|
01ad5e476f
|
增加文件系统
|
2026-07-21 00:30:59 +08:00 |
|
wandering1
|
a08d26bcb0
|
freeRTOS支持
|
2026-07-19 13:09:06 +08:00 |
|
wandering1
|
17109d9baf
|
TCP可以正常使用
|
2026-07-19 00:59:56 +08:00 |
|
wandering1
|
c841bf4668
|
关键芯片都驱动,且测试成功
|
2026-07-18 16:09:06 +08:00 |
|
wandering1
|
b1d05091de
|
Initial commit: 项目初始化
|
2026-06-05 11:56:47 +08:00 |
|