1d4b6a17ce
台架一手证据(boot_log_data/20261026_prod_console_interleave_evidence.txt):两次 「仅复位不重烧」启动里,[PROT] 未标定 INFO 行内分别多出 3 个和 1 个字节,而紧邻其后 的 [NAND_FTL] 行正好缺自己行首同样数量的字节("[20" 与 "[")——串口 framing 错不会 让行变长,字节按原序出现在邻居里 ⇒ 两个写者并发逐字节写 USART1->DR。写者对: protectTask 的未标定闭锁边沿 × defaultTask 的 storage_bring_up(),两者都落在 dbg_console_writer_attach() 之前(attach 排在存储 bring-up 之后),该窗口 s_con_writer_up == 0 ⇒ 任何任务的整行都走零互斥裸发。这是控制台单写者设计说明在册 O1 的**第二个实例**;2026-10-12 那次只补了"自愿门控",而自愿门控挡不住业务边沿留痕 (业务无法预知某条边沿落在哪个窗口),所以这次被同一窗口第二次咬到。 修法是**非阻塞整行独占**:con_tx_try_claim/release 只在几条指令的临界区里 test-and-set,绝不把 7.8 ms 的逐字节发送包进关中断区、绝不等待;IPSR 上下文与调度 器未启动两种情况显式放行(崩溃遗言必须能出去;早期本就单执行流,一条不丢);同任务 按深度嵌套。抢不到独占的那条行**原文入环**延后发——前缀与时间戳在 DBG_* 调用点就 格式化进调用方缓冲,本模块与 drain 都不补前缀、不重打时间戳,所以延后发出的行与当场 直发逐字节相同;[ERR] 只在「抢不到独占且环也放不下」时才红,按 3 次启动命中 2 次的 频率,让路若计 [ERR] 就会把静默缺陷换成常红门禁。顺带堵掉第二处洞:drain 每轮先取 凭证,拿不到就让位且 tail 不推进(旧写法 attach 可以撞上别人已发出的半行)。 新导出 dbg_console_tx_begin()/tx_end() 供 task-26 收口故障钩子的多段裸发。 否决过的两条路写进文档 §4.4.1:提前 attach 会把等串口塞进 mount/mkfs 时序敏感段 或让生产者在整个 bring-up 里堵在满环上;整段进环会让「无看门狗窗口」死机时一个字都 不出(2026-10-02 那几轮正是靠 bring-up 期流式日志取证的)。 判据:test/host/console_log 127 → 152 全绿(M 族 TC-CONLOG-170..179 共 +25,既有 127 条零删除)。唯一换钉法的是 TC-CONLOG-015——旧断言钉的正是缺陷机理本身(裸发 0 次临界区 = 零互斥),现改钉「恰 2 次几条指令的临界区 + 每个上线字节都在临界区之外 + 零等待」;硬红线由假 USART 在每个上线字节处记录临界区深度水位恒 0 来机器守住。四处 注入反证各自转红 11 / 5 / 1 / 3 条并逐字节还原复跑;覆盖率 console_log.c 199/200 行 → 256/257 行、16/16 → 21/21 函数。邻域复跑:task_prof 27/27、sys_log_mcu 137/137、 iec104_serv 37/37。CONLOG 游标抬到 179。 台架复验判据(**本笔尚未上机**,下一轮请台架跑):连续 3~5 次「仅复位不重烧」启动 日志 [ERR] 零命中,且 [PROT] 未标定与 [NAND_FTL] Initializing 两行都完整。 成本:.bss +5 B、Flash 估 +100~150 B,零新增 DBG_* / 零新增缓冲 / 零堆 / 零内核对象。 文档:控制台单写者日志设计说明.md 升 v1.6(O1 改「已处置」含两实例与字节账、新增 §4.4.1、§3.4 并发区间、§4.4 取消「不加锁」口径、§7 失效表、§11 变更记录、API 表)。
App/ — 应用层
自研代码(非 CubeMX 生成、非第三方库)。本目录是项目的应用层:任务编排、业务逻辑、 日志与配置引擎、工具函数。所有文件遵循
docs/代码规范/嵌入式C语言代码规范_V1.0.md。
职责
Src/main.c(CubeMX 初始化)→ app_main_init(本目录 app/app_main.c)→ osKernelStart →
6 个 FreeRTOS 任务(见 task/)。osKernelStart 之前全是内核启动前代码,禁止调用任何
FreeRTOS/CMSIS-RTOS API(见 AGENTS.md「平台约束」)。
目录结构(按职责分层)
| 目录 | 内容 | README |
|---|---|---|
app/ |
应用入口与全局:app_main.c/h(初始化入口)、app_cfg.h(裁剪决策占位说明,当前无宏)、sys_events.h(就绪事件) |
app/README.md |
cfg/ |
配置引擎:/config.ini 解析 + 原子持久化(旧二进制档已废弃,2026-10-10) |
cfg/README.md |
sync/ |
时间同步任务:time_sync.c/h |
sync/README.md |
algo/ |
采集与算法层(L1/L2/L3):语义取数 + 有效性判定 + 采样环/相量/测频 + 定值模型 + 保护元件框架 | algo/README.md(索引);设计 → docs/算法/采集与算法层设计说明.md |
log/ |
日志子系统:syslog(NAND)+ 控制台单写者日志 | log/README.md |
task/ |
FreeRTOS 任务实现(6 个任务) | task/README.md |
util/ |
通用工具:CRC / 环形缓冲 / 墙钟时间 | util/README.md |
protocol/ |
通信协议(预留,当前为空) | protocol/README.md |
关键约束
- 配置引擎单任务收敛:
cfg/为静态态、属主是 defaultTask;UI 保存请求经SYS_EVT_CFG_SAVE事件唤醒,netTask/uiTask 不得直接触碰配置引擎 - syslog 唯一写者:
/log/*只由 defaultTask 写入 - 新增任务/缓冲/栈前必须先核算 RAM 余量(
docs/内存管理/)
相关文档
- 架构全景:
docs/架构设计/项目架构总览.md - 启动顺序:
docs/架构设计/项目启动顺序管理.md - 配置引擎:
docs/子系统设计/配置文件设计说明.md - 日志:
docs/子系统设计/控制台单写者日志设计说明.md、docs/子系统设计/运行与自检记录设计说明.md