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 列导致新列被备注框盖住的问题。
This commit is contained in:
@@ -7,6 +7,9 @@
|
||||
* 创建日期:2026-10-11
|
||||
* 修改记录:
|
||||
* v1.0 2026-10-11 王建锋 创建:L1-6 采样有效性校验
|
||||
* v1.1 2026-10-21 王建锋 新增 adc_health_age_stale():无模块状态的帧年龄
|
||||
* 纯判据(参照系由调用方自存),供 protectTask 的
|
||||
* 兜底新鲜度门使用,见 adc_health.h 同名声明
|
||||
*/
|
||||
|
||||
#include "adc_health.h"
|
||||
@@ -166,6 +169,43 @@ void adc_health_check(const adc_health_in_t *in, adc_health_status_t *out) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:帧年龄判定(无模块状态,保护侧兜底门专用)
|
||||
* 入口参数:见 adc_health.h 同名声明
|
||||
* 返 回 值:1 - 已陈旧;0 - 新鲜或仍在建立基线
|
||||
* 限定条件:任意任务上下文;不读写本模块任何 static(与 check() 的关键区别)
|
||||
* 函数说明:三步——建基线 → 有前进即刷新参照系 → 原地不动才量"距最后一次前进"。
|
||||
* 倒退也按"有变化"处理(本函数不判单调性,那归 ADC_HF_SEQ_BACKWARD)。
|
||||
*/
|
||||
uint8_t adc_health_age_stale(adc_health_age_t *a_p_age, uint32_t a_cur_seq,
|
||||
uint32_t a_now_ms, uint32_t a_age_ms) {
|
||||
if (a_p_age == 0) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
/* 1) 首拍建基线:此刻序号往往已非 0(TIM3 比调度器早约 100 ms 就在生产帧),
|
||||
* 没有"上一拍"就没有参照系——开机窗口内绝不允许把保护锁掉 */
|
||||
if (a_p_age->primed == 0u) {
|
||||
a_p_age->primed = 1u;
|
||||
a_p_age->seq = a_cur_seq;
|
||||
a_p_age->adv_ms = a_now_ms;
|
||||
return 0u;
|
||||
}
|
||||
|
||||
/* 2) 有任何前进(含跨多帧、含跨回绕、含倒退)即算新鲜,并刷新参照系 */
|
||||
if (a_cur_seq != a_p_age->seq) {
|
||||
a_p_age->seq = a_cur_seq;
|
||||
a_p_age->adv_ms = a_now_ms;
|
||||
return 0u;
|
||||
}
|
||||
|
||||
/* 3) 序号原地不动:只看"距最后一次前进多久",含等号(与 stall 判据同边界) */
|
||||
if ((uint32_t)(int32_t)(a_now_ms - a_p_age->adv_ms) >= a_age_ms) {
|
||||
return 1u;
|
||||
}
|
||||
return 0u;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:读当前电平故障位
|
||||
* 入口参数:无
|
||||
|
||||
@@ -14,6 +14,13 @@
|
||||
* 创建日期:2026-10-11
|
||||
* 修改记录:
|
||||
* v1.0 2026-10-11 王建锋 创建:L1-6 采样有效性校验(静默/丢帧/单调性/错误增量)
|
||||
* v1.1 2026-10-21 王建锋 新增 adc_health_age_stale()(无模块状态的帧年龄
|
||||
* 纯判据,参照系由调用方自存)与 ADC_HF_STALE 位:
|
||||
* 判定层的 stall/backward 位只在 adcTask 每拍跑
|
||||
* check() 时才可能置起,节拍源停摆会把本任务卡在
|
||||
* osThreadFlagsWait 上 → 那些位永远是 0,而相量冻在
|
||||
* 最后一帧仍被 protectTask 用于判据。该纯判据让保护侧
|
||||
* 能用**自己的时基 + 中断侧计数器**独立判"数据还新不新"
|
||||
*/
|
||||
|
||||
#ifndef ADC_HEALTH_H
|
||||
@@ -51,6 +58,13 @@ extern "C" {
|
||||
#define ADC_HE_FRSTDATA (1uL << 3) /* 本次 FRSTDATA 计数有增量 */
|
||||
#define ADC_HE_HW_ERR (1uL << 5) /* 本次 HAL 错误计数有增量 */
|
||||
|
||||
/* 兜底新鲜度位(bit8,与判定层 bit0..bit7 位段错开)
|
||||
* ⚠ 本位**不由本模块置位**:由 protectTask 调 adc_health_age_stale() 独立观测后
|
||||
* OR 进闭锁位图。因此它不进 sticky、不进 adc_task 编排层的 logged 位图、
|
||||
* 也不由本模块打日志——留痕走 protect 侧既有的闭锁边沿日志与 SOE。
|
||||
* 位段纪律见 docs/算法/采样有效性校验设计说明.md §14 */
|
||||
#define ADC_HF_STALE (1uL << 8) /* 帧年龄超限(电平,序号恢复前进即清) */
|
||||
|
||||
/* 计数快照(由调用方采集,本模块不触碰任何驱动/外设) */
|
||||
typedef struct {
|
||||
uint32_t tpafe_seq; /* tpafe5160_frame_seq() */
|
||||
@@ -71,6 +85,15 @@ typedef struct {
|
||||
uint32_t tpafe_stall_ms; /* TPAFE 当前静默时长(0=正常) */
|
||||
} adc_health_status_t;
|
||||
|
||||
/* 帧年龄参照系(adc_health_age_stale() 用)。状态**归调用方所有**,所以多个观察者
|
||||
* 各判各的、互不污染——这是它与本模块其余接口的关键区别(check() 用的是模块级
|
||||
* 单写者状态,只能有一个每拍调用者) */
|
||||
typedef struct {
|
||||
uint32_t seq; /* 上次看到的序号 */
|
||||
uint32_t adv_ms; /* 最后一次看到序号前进的时刻(与调用方时基同源) */
|
||||
uint8_t primed; /* 0 = 尚未建立基线(首拍只记录、不判定) */
|
||||
} adc_health_age_t;
|
||||
|
||||
/*
|
||||
* 函数功能:采样有效性校验初始化(幂等,内核启动前可调)
|
||||
* 入口参数:无
|
||||
@@ -91,6 +114,23 @@ void adc_health_init(void);
|
||||
*/
|
||||
void adc_health_check(const adc_health_in_t *in, adc_health_status_t *out);
|
||||
|
||||
/*
|
||||
* 函数功能:帧年龄判定(无模块状态,供与消费者存活解耦的兜底门使用)
|
||||
* 入口参数:a_p_age - 调用方自存的参照系
|
||||
* a_cur_seq - 本次读到的序号(须是**中断侧**递增的计数器,如
|
||||
* tpafe5160_frame_seq() / adc_input_stm32_seq())
|
||||
* a_now_ms - 本次时基(与 a_p_age->adv_ms 取同一个任务的 tick)
|
||||
* a_age_ms - 判老门限(ms)
|
||||
* 返 回 值:1 - 已陈旧(调用方应据此闭锁);0 - 新鲜,或仍在建立基线
|
||||
* 限定条件:任意任务上下文;零内核依赖、零共享状态 → 主机侧免桩可直接单测
|
||||
* 函数说明:差值口径与 adc_health_check() 一致((int32_t) 差值,计数与 tick
|
||||
* 回绕均安全)。首次调用只建基线并返回 0;序号有任何前进即返回 0
|
||||
* (一次前进多帧属消费者超拍,不是故障);倒退不在此判老,单调性
|
||||
* 破坏归 ADC_HF_SEQ_BACKWARD 管。参数错返回 0——宁可不锁,不可误锁。
|
||||
*/
|
||||
uint8_t adc_health_age_stale(adc_health_age_t *a_p_age, uint32_t a_cur_seq,
|
||||
uint32_t a_now_ms, uint32_t a_age_ms);
|
||||
|
||||
/*
|
||||
* 函数功能:读当前电平故障位
|
||||
* 入口参数:无
|
||||
|
||||
+36
-1
@@ -13,6 +13,13 @@
|
||||
* 线程约定:prot_elm_run / prot_set_selfcheck 仅本任务上下文(prot_elm.h);
|
||||
* 跨上下文复归(104 YK11)经 prot_elm_request_reset 落请求。
|
||||
* 创建日期:2026-10-12(B5)
|
||||
* 修改记录:
|
||||
* v1.0 2026-10-12 王建锋 创建:L5-4 采样故障闭锁 + L5-1 定值巡检 + 判据节拍
|
||||
* v1.1 2026-10-21 王建锋 ①之外增加**兜底新鲜度门**:本任务用自己的时基直接
|
||||
* 看两个中断侧计数器是否还在前进(ADC_HF_STALE)。
|
||||
* adc_health 的 stall 位依赖 adcTask 每拍跑 check(),
|
||||
* 节拍源一停本任务就再没有任何人判"数据新不新",
|
||||
* 而相量冻在最后一帧上还会被本任务继续用于判据
|
||||
*/
|
||||
#include "protect_task.h"
|
||||
|
||||
@@ -22,17 +29,33 @@
|
||||
#define DBG_LINE_BUF_MAX 128U
|
||||
#include "dbg_log.h"
|
||||
|
||||
#include "adc_input.h" /* adc_input_stm32_seq():DMA 完成计数(中断侧写) */
|
||||
#include "adc_health.h"
|
||||
#include "console_log.h" /* dbg_console_writer_ready():启动锚点行门控(B6) */
|
||||
#include "prot_elm.h"
|
||||
#include "prot_set.h"
|
||||
#include "soe_store.h" /* B9:动作/复归边沿 → SOE 投递(零 FS,队列异步) */
|
||||
#include "task_watchdog.h"
|
||||
#include "tpafe5160.h" /* tpafe5160_frame_seq():帧序号(BUSY EXTI 写) */
|
||||
|
||||
/* L5-4 采样故障电平闭锁位:stall(可自愈)+ backward(锁存)都须停判据。
|
||||
* 锁存类(FRSTDATA/HW_ERR 等)不在此列——它们是一次性事件痕迹,不构成
|
||||
* "当前测量不可信";持续 stall/backward 才是。 */
|
||||
#define PROT_HF_LOCK_MASK (ADC_HF_TPAFE_STALL | ADC_HF_STM32_STALL | ADC_HF_SEQ_BACKWARD)
|
||||
#define PROT_HF_LOCK_MASK (ADC_HF_TPAFE_STALL | ADC_HF_STM32_STALL | \
|
||||
ADC_HF_SEQ_BACKWARD | ADC_HF_STALE)
|
||||
|
||||
/* 兜底新鲜度门限。判定层的 stall 是 100 ms,但那是"每拍都在跑的观察者"的口径;
|
||||
* 本门每 20 ms 才观测一次,最坏比判定层晚一整周期 → 取 100 + 20 = 120 ms,让
|
||||
* "判定层先报(带日志与自检留痕)、本门兜底(判定层死了也报)"的时序阶梯成立。
|
||||
* 排查时 hf 里 0x1/0x2 与 0x100 的先后,本身就是"判定层当时活着吗"的答案。 */
|
||||
#define PROT_STALE_AGE_MS (ADC_HEALTH_STALL_MS + PROTECT_TASK_CYCLE_MS)
|
||||
|
||||
/* 兜底门的参照系:两条车道各存一份。⚠ primed 标志也必须各自独立——若共用一个,
|
||||
* 先被观测的那条会把它置 1,另一条首拍就拿 adv_ms = 0 去算年龄 → 开机即误锁。
|
||||
* 状态放调用方而不是复用 adc_health 的模块级状态:那个是"每拍一次、单写者"的
|
||||
* 契约,两个任务同写会互相刷新差值基线,把现有判定层一起弄坏。 */
|
||||
static adc_health_age_t s_age_tp; /* TPAFE 车道 */
|
||||
static adc_health_age_t s_age_a1; /* STM32 车道 */
|
||||
|
||||
static uint32_t s_prev_active; /* 上拍动作位图(边沿日志用) */
|
||||
static uint8_t s_prev_hf_lock; /* 上拍采样闭锁态(边沿日志用) */
|
||||
@@ -89,6 +112,18 @@ void protect_task(void *argument) {
|
||||
uint32_t now = osKernelGetTickCount();
|
||||
uint32_t hf = adc_health_flags();
|
||||
|
||||
/* 兜底新鲜度门(L5-4 的独立通道):节拍源停摆时 adcTask 会永久阻塞在
|
||||
* osThreadFlagsWait(那是刻意的 fail-safe),check() 不再执行 → stall 位
|
||||
* 永远是 0。这里用本任务自己的时基直接读两个**中断侧递增**的计数器,
|
||||
* 与 adcTask 的存亡无关;两者都只要 TIM3 还在触发就会前进。
|
||||
* STM32 车道只更新参照系、不额外置位:任一侧老了就同一个位闭锁。 */
|
||||
if (adc_health_age_stale(&s_age_tp, tpafe5160_frame_seq(), now,
|
||||
PROT_STALE_AGE_MS) != 0u) {
|
||||
hf |= ADC_HF_STALE;
|
||||
}
|
||||
(void)adc_health_age_stale(&s_age_a1, adc_input_stm32_seq(), now,
|
||||
PROT_STALE_AGE_MS);
|
||||
|
||||
/* 启动锚点行:控制台写者注册后首拍补打(2026-10-10 门控纪律,adcTask
|
||||
* 首帧同款)。写者注册前 con_append 走无锁裸发,与 defaultTask 启动日志
|
||||
* 逐字节交错——B6 台架实证:本行曾损坏为 "st[art: cycle=220ms elm=70"
|
||||
|
||||
+194
-172
@@ -5,204 +5,226 @@
|
||||
<text x="40" y="178" font-size="12" font-weight="700" fill="#334155">判定层写出的三张位图(adc_health.c)</text>
|
||||
<text x="40" y="220" font-size="12" font-weight="700" fill="#0f172a">flags 电平位</text>
|
||||
<text x="40" y="238" font-size="10" fill="#64748b">adc_health_flags(),当前活跃</text>
|
||||
<rect x="310" y="200" width="112" height="46" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.55"/>
|
||||
<rect x="310" y="200" width="94" height="46" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.55"/>
|
||||
<text x="320" y="219" font-size="11" font-weight="700" fill="#0d9488">bit0</text>
|
||||
<text x="320" y="236" font-size="10" fill="#334155">TPAFE_STALL</text>
|
||||
<rect x="426" y="200" width="112" height="46" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.55"/>
|
||||
<text x="436" y="219" font-size="11" font-weight="700" fill="#0d9488">bit1</text>
|
||||
<text x="436" y="236" font-size="10" fill="#334155">STM32_STALL</text>
|
||||
<rect x="542" y="200" width="112" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="552" y="219" font-size="11" font-weight="700" fill="#e11d48">bit2</text>
|
||||
<text x="552" y="236" font-size="10" fill="#334155">SEQ_BACKWARD</text>
|
||||
<rect x="658" y="200" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="668" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit3</text>
|
||||
<text x="668" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="774" y="200" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="784" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit4</text>
|
||||
<text x="784" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="890" y="200" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="900" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit5</text>
|
||||
<text x="900" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1006" y="200" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1016" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="1016" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1122" y="200" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1132" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1132" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1250" y="200" width="340" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1262" y="225" font-size="11" fill="#475569">protectTask 每 20 ms 读它做 L5-4 闭锁;不看事件位</text>
|
||||
<rect x="408" y="200" width="94" height="46" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.55"/>
|
||||
<text x="418" y="219" font-size="11" font-weight="700" fill="#0d9488">bit1</text>
|
||||
<text x="418" y="236" font-size="10" fill="#334155">STM32_STALL</text>
|
||||
<rect x="506" y="200" width="94" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="516" y="219" font-size="11" font-weight="700" fill="#e11d48">bit2</text>
|
||||
<text x="516" y="236" font-size="10" fill="#334155">SEQ_BACKWARD</text>
|
||||
<rect x="604" y="200" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="614" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit3</text>
|
||||
<text x="614" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="702" y="200" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="712" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit4</text>
|
||||
<text x="712" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="800" y="200" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="810" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit5</text>
|
||||
<text x="810" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="898" y="200" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="908" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="908" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="996" y="200" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1006" y="219" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1006" y="236" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1094" y="200" width="94" height="46" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.55"/>
|
||||
<text x="1104" y="219" font-size="11" font-weight="700" fill="#0d9488">bit8</text>
|
||||
<text x="1104" y="236" font-size="10" fill="#334155">STALE</text>
|
||||
<rect x="1204" y="200" width="320" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1216" y="217" font-size="11" fill="#475569">protectTask 每 20 ms 读它做 L5-4 闭锁;bit8 由</text>
|
||||
<text x="1216" y="232" font-size="11" fill="#475569">本任务自己判老后 OR 入(判定层不写)</text>
|
||||
<text x="40" y="276" font-size="12" font-weight="700" fill="#0f172a">sticky 锁存位</text>
|
||||
<text x="40" y="294" font-size="10" fill="#64748b">adc_health_sticky(),直到 init 才清</text>
|
||||
<rect x="310" y="256" width="112" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<rect x="310" y="256" width="94" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="320" y="275" font-size="11" font-weight="700" fill="#e11d48">bit0</text>
|
||||
<text x="320" y="292" font-size="10" fill="#334155">TPAFE_STALL</text>
|
||||
<rect x="426" y="256" width="112" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="436" y="275" font-size="11" font-weight="700" fill="#e11d48">bit1</text>
|
||||
<text x="436" y="292" font-size="10" fill="#334155">STM32_STALL</text>
|
||||
<rect x="542" y="256" width="112" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="552" y="275" font-size="11" font-weight="700" fill="#e11d48">bit2</text>
|
||||
<text x="552" y="292" font-size="10" fill="#334155">SEQ_BACKWARD</text>
|
||||
<rect x="658" y="256" width="112" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="668" y="275" font-size="11" font-weight="700" fill="#e11d48">bit3</text>
|
||||
<text x="668" y="292" font-size="10" fill="#334155">FRSTDATA</text>
|
||||
<rect x="774" y="256" width="112" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="784" y="275" font-size="11" font-weight="700" fill="#e11d48">bit4</text>
|
||||
<text x="784" y="292" font-size="10" fill="#334155">STM32_ERR</text>
|
||||
<rect x="890" y="256" width="112" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="900" y="275" font-size="11" font-weight="700" fill="#e11d48">bit5</text>
|
||||
<text x="900" y="292" font-size="10" fill="#334155">HW_ERR</text>
|
||||
<rect x="1006" y="256" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1016" y="275" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="1016" y="292" font-size="10" fill="#334155">不入锁存</text>
|
||||
<rect x="1122" y="256" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1132" y="275" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1132" y="292" font-size="10" fill="#334155">不入锁存</text>
|
||||
<rect x="1250" y="256" width="340" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1262" y="281" font-size="11" fill="#475569">只留痕不闭锁:曾停摆/曾出错必须可追溯</text>
|
||||
<rect x="408" y="256" width="94" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="418" y="275" font-size="11" font-weight="700" fill="#e11d48">bit1</text>
|
||||
<text x="418" y="292" font-size="10" fill="#334155">STM32_STALL</text>
|
||||
<rect x="506" y="256" width="94" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="516" y="275" font-size="11" font-weight="700" fill="#e11d48">bit2</text>
|
||||
<text x="516" y="292" font-size="10" fill="#334155">SEQ_BACKWARD</text>
|
||||
<rect x="604" y="256" width="94" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="614" y="275" font-size="11" font-weight="700" fill="#e11d48">bit3</text>
|
||||
<text x="614" y="292" font-size="10" fill="#334155">FRSTDATA</text>
|
||||
<rect x="702" y="256" width="94" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="712" y="275" font-size="11" font-weight="700" fill="#e11d48">bit4</text>
|
||||
<text x="712" y="292" font-size="10" fill="#334155">STM32_ERR</text>
|
||||
<rect x="800" y="256" width="94" height="46" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-opacity="0.55"/>
|
||||
<text x="810" y="275" font-size="11" font-weight="700" fill="#e11d48">bit5</text>
|
||||
<text x="810" y="292" font-size="10" fill="#334155">HW_ERR</text>
|
||||
<rect x="898" y="256" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="908" y="275" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="908" y="292" font-size="10" fill="#334155">不入锁存</text>
|
||||
<rect x="996" y="256" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1006" y="275" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1006" y="292" font-size="10" fill="#334155">不入锁存</text>
|
||||
<rect x="1094" y="256" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1104" y="275" font-size="11" font-weight="700" fill="#94a3b8">bit8</text>
|
||||
<text x="1104" y="292" font-size="10" fill="#334155">不入锁存</text>
|
||||
<rect x="1204" y="256" width="320" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1216" y="281" font-size="11" fill="#475569">只留痕不闭锁:曾停摆/曾出错必须可追溯</text>
|
||||
<text x="40" y="332" font-size="12" font-weight="700" fill="#0f172a">events 事件位</text>
|
||||
<text x="40" y="350" font-size="10" fill="#64748b">adc_health_check() 出参,仅当拍有效</text>
|
||||
<rect x="310" y="312" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<rect x="310" y="312" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="320" y="331" font-size="11" font-weight="700" fill="#94a3b8">bit0</text>
|
||||
<text x="320" y="348" font-size="10" fill="#334155">—</text>
|
||||
<rect x="426" y="312" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="436" y="331" font-size="11" font-weight="700" fill="#94a3b8">bit1</text>
|
||||
<text x="436" y="348" font-size="10" fill="#334155">—</text>
|
||||
<rect x="542" y="312" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="552" y="331" font-size="11" font-weight="700" fill="#94a3b8">bit2</text>
|
||||
<text x="552" y="348" font-size="10" fill="#334155">—</text>
|
||||
<rect x="658" y="312" width="112" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="668" y="331" font-size="11" font-weight="700" fill="#d97706">bit3</text>
|
||||
<text x="668" y="348" font-size="10" fill="#334155">FRSTDATA</text>
|
||||
<rect x="774" y="312" width="112" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="784" y="331" font-size="11" font-weight="700" fill="#d97706">bit4</text>
|
||||
<text x="784" y="348" font-size="10" fill="#334155">STM32_ERR</text>
|
||||
<rect x="890" y="312" width="112" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="900" y="331" font-size="11" font-weight="700" fill="#d97706">bit5</text>
|
||||
<text x="900" y="348" font-size="10" fill="#334155">HW_ERR</text>
|
||||
<rect x="1006" y="312" width="112" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="1016" y="331" font-size="11" font-weight="700" fill="#d97706">bit6</text>
|
||||
<text x="1016" y="348" font-size="10" fill="#334155">TPAFE_GAP</text>
|
||||
<rect x="1122" y="312" width="112" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="1132" y="331" font-size="11" font-weight="700" fill="#d97706">bit7</text>
|
||||
<text x="1132" y="348" font-size="10" fill="#334155">STM32_GAP</text>
|
||||
<rect x="1250" y="312" width="340" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1262" y="337" font-size="11" fill="#475569">adc_health_report() 的唯一输入:按位分三级处置</text>
|
||||
<rect x="408" y="312" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="418" y="331" font-size="11" font-weight="700" fill="#94a3b8">bit1</text>
|
||||
<text x="418" y="348" font-size="10" fill="#334155">—</text>
|
||||
<rect x="506" y="312" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="516" y="331" font-size="11" font-weight="700" fill="#94a3b8">bit2</text>
|
||||
<text x="516" y="348" font-size="10" fill="#334155">—</text>
|
||||
<rect x="604" y="312" width="94" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="614" y="331" font-size="11" font-weight="700" fill="#d97706">bit3</text>
|
||||
<text x="614" y="348" font-size="10" fill="#334155">FRSTDATA</text>
|
||||
<rect x="702" y="312" width="94" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="712" y="331" font-size="11" font-weight="700" fill="#d97706">bit4</text>
|
||||
<text x="712" y="348" font-size="10" fill="#334155">STM32_ERR</text>
|
||||
<rect x="800" y="312" width="94" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="810" y="331" font-size="11" font-weight="700" fill="#d97706">bit5</text>
|
||||
<text x="810" y="348" font-size="10" fill="#334155">HW_ERR</text>
|
||||
<rect x="898" y="312" width="94" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="908" y="331" font-size="11" font-weight="700" fill="#d97706">bit6</text>
|
||||
<text x="908" y="348" font-size="10" fill="#334155">TPAFE_GAP</text>
|
||||
<rect x="996" y="312" width="94" height="46" rx="8" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.55"/>
|
||||
<text x="1006" y="331" font-size="11" font-weight="700" fill="#d97706">bit7</text>
|
||||
<text x="1006" y="348" font-size="10" fill="#334155">STM32_GAP</text>
|
||||
<rect x="1094" y="312" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1104" y="331" font-size="11" font-weight="700" fill="#94a3b8">bit8</text>
|
||||
<text x="1104" y="348" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1204" y="312" width="320" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1216" y="337" font-size="11" fill="#475569">adc_health_report() 的唯一输入:按位分三级处置</text>
|
||||
<text x="40" y="394" font-size="12" font-weight="700" fill="#334155">消费者侧的掩码与记忆位图</text>
|
||||
<text x="40" y="436" font-size="12" font-weight="700" fill="#0f172a">PROT_HF_LOCK_MASK</text>
|
||||
<text x="40" y="454" font-size="10" fill="#64748b">protect_task.c 编译期常量</text>
|
||||
<rect x="310" y="416" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<rect x="310" y="416" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="320" y="435" font-size="11" font-weight="700" fill="#7c3aed">bit0</text>
|
||||
<text x="320" y="452" font-size="10" fill="#334155">闭锁</text>
|
||||
<rect x="426" y="416" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="436" y="435" font-size="11" font-weight="700" fill="#7c3aed">bit1</text>
|
||||
<text x="436" y="452" font-size="10" fill="#334155">闭锁</text>
|
||||
<rect x="542" y="416" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="552" y="435" font-size="11" font-weight="700" fill="#7c3aed">bit2</text>
|
||||
<text x="552" y="452" font-size="10" fill="#334155">闭锁</text>
|
||||
<rect x="658" y="416" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="668" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit3</text>
|
||||
<text x="668" y="452" font-size="10" fill="#334155">不闭锁</text>
|
||||
<rect x="774" y="416" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="784" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit4</text>
|
||||
<text x="784" y="452" font-size="10" fill="#334155">不闭锁</text>
|
||||
<rect x="890" y="416" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="900" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit5</text>
|
||||
<text x="900" y="452" font-size="10" fill="#334155">不闭锁</text>
|
||||
<rect x="1006" y="416" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1016" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="1016" y="452" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1122" y="416" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1132" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1132" y="452" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1250" y="416" width="340" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1262" y="433" font-size="11" fill="#475569">命中即 prot_elm_init() 复位元件 + 本拍不 eval;SOE</text>
|
||||
<text x="1262" y="448" font-size="11" fill="#475569"> 类型 5/6</text>
|
||||
<rect x="408" y="416" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="418" y="435" font-size="11" font-weight="700" fill="#7c3aed">bit1</text>
|
||||
<text x="418" y="452" font-size="10" fill="#334155">闭锁</text>
|
||||
<rect x="506" y="416" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="516" y="435" font-size="11" font-weight="700" fill="#7c3aed">bit2</text>
|
||||
<text x="516" y="452" font-size="10" fill="#334155">闭锁</text>
|
||||
<rect x="604" y="416" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="614" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit3</text>
|
||||
<text x="614" y="452" font-size="10" fill="#334155">不闭锁</text>
|
||||
<rect x="702" y="416" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="712" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit4</text>
|
||||
<text x="712" y="452" font-size="10" fill="#334155">不闭锁</text>
|
||||
<rect x="800" y="416" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="810" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit5</text>
|
||||
<text x="810" y="452" font-size="10" fill="#334155">不闭锁</text>
|
||||
<rect x="898" y="416" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="908" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="908" y="452" font-size="10" fill="#334155">—</text>
|
||||
<rect x="996" y="416" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1006" y="435" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1006" y="452" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1094" y="416" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="1104" y="435" font-size="11" font-weight="700" fill="#7c3aed">bit8</text>
|
||||
<text x="1104" y="452" font-size="10" fill="#334155">闭锁</text>
|
||||
<rect x="1204" y="416" width="320" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1216" y="433" font-size="11" fill="#475569">命中即 prot_elm_init() 复位元件 + 本拍不 eval;</text>
|
||||
<text x="1216" y="448" font-size="11" fill="#475569">SOE 5/6 带位图</text>
|
||||
<text x="40" y="492" font-size="12" font-weight="700" fill="#0f172a">serious 严重事件</text>
|
||||
<text x="40" y="510" font-size="10" fill="#64748b">adc_task.c 的 adc_health_report()</text>
|
||||
<rect x="310" y="472" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<rect x="310" y="472" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="320" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit0</text>
|
||||
<text x="320" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="426" y="472" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="436" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit1</text>
|
||||
<text x="436" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="542" y="472" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="552" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit2</text>
|
||||
<text x="552" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="658" y="472" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="668" y="491" font-size="11" font-weight="700" fill="#7c3aed">bit3</text>
|
||||
<text x="668" y="508" font-size="10" fill="#334155">FRSTDATA</text>
|
||||
<rect x="774" y="472" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="784" y="491" font-size="11" font-weight="700" fill="#7c3aed">bit4</text>
|
||||
<text x="784" y="508" font-size="10" fill="#334155">STM32_ERR</text>
|
||||
<rect x="890" y="472" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="900" y="491" font-size="11" font-weight="700" fill="#7c3aed">bit5</text>
|
||||
<text x="900" y="508" font-size="10" fill="#334155">HW_ERR</text>
|
||||
<rect x="1006" y="472" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1016" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="1016" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1122" y="472" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1132" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1132" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1250" y="472" width="340" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1262" y="497" font-size="11" fill="#475569">三类计数增量恒应为 0 → 每次 DBG_ERROR + 自检留痕</text>
|
||||
<rect x="408" y="472" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="418" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit1</text>
|
||||
<text x="418" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="506" y="472" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="516" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit2</text>
|
||||
<text x="516" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="604" y="472" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="614" y="491" font-size="11" font-weight="700" fill="#7c3aed">bit3</text>
|
||||
<text x="614" y="508" font-size="10" fill="#334155">FRSTDATA</text>
|
||||
<rect x="702" y="472" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="712" y="491" font-size="11" font-weight="700" fill="#7c3aed">bit4</text>
|
||||
<text x="712" y="508" font-size="10" fill="#334155">STM32_ERR</text>
|
||||
<rect x="800" y="472" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="810" y="491" font-size="11" font-weight="700" fill="#7c3aed">bit5</text>
|
||||
<text x="810" y="508" font-size="10" fill="#334155">HW_ERR</text>
|
||||
<rect x="898" y="472" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="908" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="908" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="996" y="472" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1006" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1006" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1094" y="472" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1104" y="491" font-size="11" font-weight="700" fill="#94a3b8">bit8</text>
|
||||
<text x="1104" y="508" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1204" y="472" width="320" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1216" y="497" font-size="11" fill="#475569">三类计数增量恒应为 0 → 每次 DBG_ERROR + 自检留痕</text>
|
||||
<text x="40" y="548" font-size="12" font-weight="700" fill="#0f172a">gap 丢帧事件</text>
|
||||
<text x="40" y="566" font-size="10" fill="#64748b">同一函数里的丢帧分支</text>
|
||||
<rect x="310" y="528" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<rect x="310" y="528" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="320" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit0</text>
|
||||
<text x="320" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="426" y="528" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="436" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit1</text>
|
||||
<text x="436" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="542" y="528" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="552" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit2</text>
|
||||
<text x="552" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="658" y="528" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="668" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit3</text>
|
||||
<text x="668" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="774" y="528" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="784" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit4</text>
|
||||
<text x="784" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="890" y="528" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="900" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit5</text>
|
||||
<text x="900" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1006" y="528" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="1016" y="547" font-size="11" font-weight="700" fill="#7c3aed">bit6</text>
|
||||
<text x="1016" y="564" font-size="10" fill="#334155">TPAFE_GAP</text>
|
||||
<rect x="1122" y="528" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="1132" y="547" font-size="11" font-weight="700" fill="#7c3aed">bit7</text>
|
||||
<text x="1132" y="564" font-size="10" fill="#334155">STM32_GAP</text>
|
||||
<rect x="1250" y="528" width="340" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1262" y="545" font-size="11" fill="#475569">刻意不告警:超拍是常态(启动突发期即累计 23 次),只累</text>
|
||||
<text x="1262" y="560" font-size="11" fill="#475569">计</text>
|
||||
<rect x="408" y="528" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="418" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit1</text>
|
||||
<text x="418" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="506" y="528" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="516" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit2</text>
|
||||
<text x="516" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="604" y="528" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="614" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit3</text>
|
||||
<text x="614" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="702" y="528" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="712" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit4</text>
|
||||
<text x="712" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="800" y="528" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="810" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit5</text>
|
||||
<text x="810" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="898" y="528" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="908" y="547" font-size="11" font-weight="700" fill="#7c3aed">bit6</text>
|
||||
<text x="908" y="564" font-size="10" fill="#334155">TPAFE_GAP</text>
|
||||
<rect x="996" y="528" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="1006" y="547" font-size="11" font-weight="700" fill="#7c3aed">bit7</text>
|
||||
<text x="1006" y="564" font-size="10" fill="#334155">STM32_GAP</text>
|
||||
<rect x="1094" y="528" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1104" y="547" font-size="11" font-weight="700" fill="#94a3b8">bit8</text>
|
||||
<text x="1104" y="564" font-size="10" fill="#334155">—</text>
|
||||
<rect x="1204" y="528" width="320" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1216" y="545" font-size="11" fill="#475569">刻意不告警:超拍是常态(启动突发期即累计 23 次),</text>
|
||||
<text x="1216" y="560" font-size="11" fill="#475569">只累计</text>
|
||||
<text x="40" y="604" font-size="12" font-weight="700" fill="#0f172a">s_health_logged</text>
|
||||
<text x="40" y="622" font-size="10" fill="#64748b">编排层记忆位图(每类一次留痕)</text>
|
||||
<rect x="310" y="584" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<rect x="310" y="584" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="320" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit0</text>
|
||||
<text x="320" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="426" y="584" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="436" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit1</text>
|
||||
<text x="436" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="542" y="584" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="552" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit2</text>
|
||||
<text x="552" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="658" y="584" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="668" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit3</text>
|
||||
<text x="668" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="774" y="584" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="784" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit4</text>
|
||||
<text x="784" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="890" y="584" width="112" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="900" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit5</text>
|
||||
<text x="900" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="1006" y="584" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1016" y="603" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="1016" y="620" font-size="10" fill="#334155">不记</text>
|
||||
<rect x="1122" y="584" width="112" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1132" y="603" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1132" y="620" font-size="10" fill="#334155">不记</text>
|
||||
<rect x="1250" y="584" width="340" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1262" y="601" font-size="11" fill="#475569"> |= (serious | rise):用同一位号把 SYSLOG 压成每类</text>
|
||||
<text x="1262" y="616" font-size="11" fill="#475569">每次开机一条</text>
|
||||
<rect x="408" y="584" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="418" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit1</text>
|
||||
<text x="418" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="506" y="584" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="516" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit2</text>
|
||||
<text x="516" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="604" y="584" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="614" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit3</text>
|
||||
<text x="614" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="702" y="584" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="712" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit4</text>
|
||||
<text x="712" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="800" y="584" width="94" height="46" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.55"/>
|
||||
<text x="810" y="603" font-size="11" font-weight="700" fill="#7c3aed">bit5</text>
|
||||
<text x="810" y="620" font-size="10" fill="#334155">记过</text>
|
||||
<rect x="898" y="584" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="908" y="603" font-size="11" font-weight="700" fill="#94a3b8">bit6</text>
|
||||
<text x="908" y="620" font-size="10" fill="#334155">不记</text>
|
||||
<rect x="996" y="584" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1006" y="603" font-size="11" font-weight="700" fill="#94a3b8">bit7</text>
|
||||
<text x="1006" y="620" font-size="10" fill="#334155">不记</text>
|
||||
<rect x="1094" y="584" width="94" height="46" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-opacity="0.35"/>
|
||||
<text x="1104" y="603" font-size="11" font-weight="700" fill="#94a3b8">bit8</text>
|
||||
<text x="1104" y="620" font-size="10" fill="#334155">不记</text>
|
||||
<rect x="1204" y="584" width="320" height="46" rx="8" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
|
||||
<text x="1216" y="601" font-size="11" fill="#475569"> |= (serious | rise):用同一位号把 SYSLOG 压成</text>
|
||||
<text x="1216" y="616" font-size="11" fill="#475569">每类每次开机一条</text>
|
||||
<rect x="310" y="106" width="16" height="16" rx="4" fill="#f0fdfa" stroke="#0d9488" stroke-width="1.6"/>
|
||||
<text x="332" y="118" font-size="12" fill="#475569">电平位(可自愈)</text>
|
||||
<rect x="458" y="106" width="16" height="16" rx="4" fill="#fff1f2" stroke="#e11d48" stroke-width="1.6"/>
|
||||
@@ -214,5 +236,5 @@
|
||||
<rect x="970" y="106" width="16" height="16" rx="4" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.6"/>
|
||||
<text x="992" y="118" font-size="12" fill="#475569">不适用</text>
|
||||
<rect x="40" y="682" width="1500" height="44" rx="10" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.45"/>
|
||||
<text x="56" y="709" font-size="11" fill="#7c2d12">bit3 / bit4 / bit5 在 events 与 sticky 中刻意用同一位号 → 消费者能把事件位直接套在锁存位图上做每类一次留痕;bit8 以上全 32 位保留未用。详见 docs/算法/采样有效性校验设计说明.md</text>
|
||||
<text x="56" y="709" font-size="11" fill="#7c2d12">bit3 / bit4 / bit5 在 events 与 sticky 中刻意用同一位号 → 消费者能把事件位直接套在锁存位图上做每类一次留痕;bit8 = 保护侧兜底门专用(判定层不写它)。详见 docs/算法/采样有效性校验设计说明.md</text>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,172 @@
|
||||
[+0ms] [----/--/-- --:--:--][APP] boot: syslog init OK
|
||||
[+0ms] [----/--/-- --:--:--][APP] fw build: Oct 21 2026 14:36:36 suite=NONE dstr=off
|
||||
[+10ms] [----/--/-- --:--:--][APP] reset cause: software (NVIC_SystemReset) (CSR=0x14000000)
|
||||
[+21ms] PREVRUN seg=2 seq=2099812320 t=118563808
|
||||
[+21ms] TICKRUN uw=118563818 n=118563818 duw=10
|
||||
[+32ms] [----/--/-- --:--:--][RTC] sd2506_init: OK
|
||||
[+32ms] [----/--/-- --:--:--][APP] SD2506 init: OK (ret=0)
|
||||
[+42ms] [2026-10-21 15:40:36][CLK] sys_clock_init: RTC initial time 2026-10-21 15:40:36
|
||||
[+42ms] [2026-10-21 15:40:36][CLK] sys_clock_init: wall clock base = unix 1792597236, base_tick=140
|
||||
[+53ms] [2026-10-21 15:40:36][APP] RS485 init: OK (UART4, DE=PA15)
|
||||
[+74ms] [2026-10-21 15:40:36][NAND] Resetting NAND...
|
||||
[+84ms] [2026-10-21 15:40:36][NAND] Reading NAND ID...
|
||||
[+84ms] [2026-10-21 15:40:36][NAND] NAND ID: MID=0xC8, DID=0x52
|
||||
[+96ms] [2026-10-21 15:40:36][NAND] Scanning bad blocks...
|
||||
[+232ms] [2026-10-21 15:40:36][NAND] BBT scan: 0 bad blocks found
|
||||
[+232ms] [2026-10-21 15:40:36][NAND] Enabling ECC...
|
||||
[+242ms] [2026-10-21 15:40:36][NAND] Unlocking block protection...
|
||||
[+242ms] [2026-10-21 15:40:36][NAND] Locating BBT pool...
|
||||
[+253ms] [2026-10-21 15:40:36][NAND] Loading persisted BBT...
|
||||
[+253ms] [2026-10-21 15:40:36][NAND] NAND init OK
|
||||
[+263ms] [2026-10-21 15:40:36][APP] NAND init: OK
|
||||
[+263ms] [2026-10-21 15:40:36][ADC] Init OK
|
||||
[+263ms] [2026-10-21 15:40:36][APP] ADC init: OK
|
||||
[+274ms] [2026-10-21 15:40:36][APP] ADC input layer init: OK
|
||||
[+274ms] [2026-10-21 15:40:36][APP] phasor layer init: OK (inst=5)
|
||||
[+284ms] [2026-10-21 15:40:36][APP] freq layer init: OK
|
||||
[+284ms] [2026-10-21 15:40:36][APP] protection init: OK (set=40 elm=9)
|
||||
[+295ms] [2026-10-21 15:40:36][APP] SD2506 ID: 2512153425482405
|
||||
[+295ms] [2026-10-21 15:40:36][APP] SD2506 time: 2026-10-21 15:40:37 (week 3)
|
||||
[+305ms] [2026-10-21 15:40:36][APP] SD2506 temp: 25 C
|
||||
[+305ms] [2026-10-21 15:40:36][APP] SD2506 battery: 3.12 V
|
||||
[+315ms] [2026-10-21 15:40:36][APP] App init OK
|
||||
[+315ms] [2026-10-21 15:40:36][NAND_FTL] Initializing NAND FTL...
|
||||
[+419ms] [2026-10-21 15:40:36][NAND_FTL] Map resumed: 14094/97504 sectors used
|
||||
[+419ms] [2026-10-21 15:40:36][NAND_FTL] Map head=38176 tail=16200 epoch=3
|
||||
[+430ms] [2026-10-21 15:40:36][NAND_FTL] NAND FTL ready (capacity: 97504 pages = 190 MB)
|
||||
[+514ms] [2026-10-21 15:40:36] [FS] FATFS mounted
|
||||
[+576ms] [2026-10-21 15:40:36][SYSLOG] runlog boot entry: power on
|
||||
[+586ms] [2026-10-21 15:40:36][CFG] register: section 'network' (4 keys)
|
||||
[+586ms] [2026-10-21 15:40:36][CFG] register: section 'ftp' (3 keys)
|
||||
[+596ms] [2026-10-21 15:40:36][CFG] load: OK (523B, heap free 16552B)
|
||||
[+607ms] [2026-10-21 15:40:36][NET_CFG] load: OK ip=192.168.1.100
|
||||
[+607ms] [2026-10-21 15:40:36] [CFG] prot set loaded (/prot_set.bin)
|
||||
[+628ms] [2026-10-21 15:40:36][ADC_TASK] first: UA=11428 UB=1079 UC=919 UN=11452 IA=11452 IB=1027 IC=1005 IN=951 T=984
|
||||
[+638ms] [2026-10-21 15:40:36][ADC_TASK] phasor(first) C01-IA-F1: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+649ms] [2026-10-21 15:40:36][ADC_TASK] phasor(first) C02-UA-F1: Re=0 Im=3 rms=3 (x0.1)
|
||||
[+659ms] [2026-10-21 15:40:36][ADC_TASK] phasor(first) C03-UN-F1: Re=3 Im=1 rms=3 (x0.1)
|
||||
[+659ms] [2026-10-21 15:40:36][ADC_TASK] phasor(first) C04-IA-F2: Re=0 Im=3 rms=3 (x0.1)
|
||||
[+670ms] [2026-10-21 15:40:36][ADC_TASK] phasor(first) C05-IA-F5: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+681ms] [2026-10-21 15:40:36][ADC_TASK] freq(first): f=0 valid=0 (x0.01)
|
||||
[+681ms] [2026-10-21 15:40:36][NET_TASK] === Network Init ===
|
||||
[+681ms] [2026-10-21 15:40:36][PROT] protect task start: cycle=20ms elm=9
|
||||
[+691ms] [2026-10-21 15:40:36][NET] ch395f ver=0x4A fun_para=0x08
|
||||
[+702ms] MISS start snap=0x000001E7 req=0x000001F7 t=800
|
||||
[+702ms] [2026-10-21 15:40:36][WD] [WD] armed: timeout ~2498ms (worst ~1701ms), miss_tol=800ms
|
||||
[+713ms] [2026-10-21 15:40:36][NET_TASK] net init: OK
|
||||
[+713ms] [2026-10-21 15:40:36][NET_TASK] MAC: 3C:AB:72:53:2B:12
|
||||
[+723ms] [2026-10-21 15:40:36][NET_TASK] IP_INF: IP=192.168.1.100 GW=192.168.1.1 MASK=255.255.255.0
|
||||
[+733ms] [2026-10-21 15:40:36][UI_TASK] UI task: started, wait net ready
|
||||
[+2727ms] [2026-10-21 15:40:38][NET_TASK] PHY: 100M FULL
|
||||
[+2738ms] [2026-10-21 15:40:38][NET_TASK] netTask: started (single-socket mode)
|
||||
[+2769ms] [2026-10-21 15:40:38] [FTP] using factory default password
|
||||
[+2800ms] [2026-10-21 15:40:38][TIME_SYNC] time_sync: TCP listen on :8888 (sock=0)
|
||||
[+2832ms] [2026-10-21 15:40:38][I104] i104: listening on 2404
|
||||
[+2842ms] [2026-10-21 15:40:38] [FTP] waiting for connection...
|
||||
[+2853ms] [2026-10-21 15:40:38][UI_TASK] UI task: net ready, init port
|
||||
[+2853ms] [2026-10-21 15:40:38][UI_TASK] UI task: ui_port_init enter
|
||||
[+2863ms] [2026-10-21 15:40:38][UI_PORT] theme: mono dark_bg=true applied
|
||||
[+2863ms] [2026-10-21 15:40:38][UI_TASK] UI port init: OK
|
||||
[+2874ms] [2026-10-21 15:40:38][UI_TASK] UI task: ui_menu_init enter
|
||||
[+2874ms] [2026-10-21 15:40:38][UI_MENU] menu build start: total=15136 free=12692 big=12692
|
||||
[+2884ms] [2026-10-21 15:40:38][UI_MENU_VIEW] view init: root frame w=66 h=107
|
||||
[+2895ms] [2026-10-21 15:40:38][UI_MENU] menu build done: total=15020 free=11828 big=11816 used=3192
|
||||
[+2905ms] [2026-10-21 15:40:38][UI_TASK] UI menu init: OK
|
||||
[+2905ms] [2026-10-21 15:40:38][UI_STANDBY] standby: ready (idle=60000ms)
|
||||
[+2916ms] [2026-10-21 15:40:38][UI_TASK] UI standby: ready (idle=60s)
|
||||
[+2968ms] [2026-10-21 15:40:38][UI_TASK] UI net sink: started (port 7003)
|
||||
[+2968ms] MISS start snap=0x000001E7 req=0x000001F7 t=3071
|
||||
[+2968ms] [PROF] t=3075 uic=0 uip=0 uipn=0 uil=0 uiw=0 uis=0 uisn=0 adc=2655 adcm=2286 adcn=0 gl=0
|
||||
[+2979ms] [PROF2] t=3075 defd=130915 defs=14 netp=3013 netn=577 adcp=11 adcq=0 gl=0
|
||||
[+4936ms] [PROF] t=5040 uic=176 uip=21760 uipn=2849 uil=11000 uiw=11852 uis=1292 uisn=0 adc=4619 adcm=2286 adcn=0 gl=0
|
||||
[+4947ms] [PROF2] t=5040 defd=130915 defs=14 netp=3013 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+5356ms] [2026-10-21 15:40:41] [STACK] default peak_used=2152/5120 free_min=2968 (57%)
|
||||
[+5367ms] [2026-10-21 15:40:41] [STACK] net peak_used=1116/3840 free_min=2724 (70%)
|
||||
[+5367ms] [2026-10-21 15:40:41] [STACK] ftp peak_used=740/4096 free_min=3356 (81%)
|
||||
[+5378ms] [2026-10-21 15:40:41] [STACK] ui peak_used=4016/16384 free_min=12368 (75%)
|
||||
[+5388ms] [2026-10-21 15:40:41] [STACK] timesync peak_used=616/2560 free_min=1944 (75%)
|
||||
[+5388ms] [2026-10-21 15:40:41] [STACK] adc peak_used=952/2560 free_min=1608 (62%)
|
||||
[+5399ms] [2026-10-21 15:40:41] [STACK] iec104 peak_used=540/2560 free_min=2020 (78%)
|
||||
[+5410ms] [2026-10-21 15:40:41] [STACK] protect peak_used=620/2048 free_min=1428 (69%)
|
||||
[+5410ms] [2026-10-21 15:40:41] [STACK] heap free=15800 min_ever=8464
|
||||
[+5462ms] [2026-10-21 15:40:41][ERR][PROT] sampling FAULT -> protection blocked (hf=0x00000100)
|
||||
[+5555ms] MISS start snap=0x000001B7 req=0x000001F7 t=5656
|
||||
[+5555ms] [PROF] t=5660 uic=222 uip=67678 uipn=10394 uil=10999 uiw=11852 uis=1292 uisn=0 adc=5019 adcm=2286 adcn=0 gl=0
|
||||
[+5566ms] [PROF2] t=5660 defd=130915 defs=38287 netp=3013 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+5757ms] [2026-10-21 15:40:41][PROT] sampling recovered -> protection resumed
|
||||
[+6959ms] [PROF] t=7056 uic=344 uip=67678 uipn=6848 uil=11000 uiw=11852 uis=1292 uisn=0 adc=6235 adcm=2286 adcn=0 gl=0
|
||||
[+6959ms] [PROF2] t=7056 defd=130915 defs=38944 netp=4997 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+8972ms] [PROF] t=9074 uic=526 uip=67678 uipn=9857 uil=10999 uiw=11852 uis=1292 uisn=0 adc=8253 adcm=2286 adcn=0 gl=0
|
||||
[+8982ms] [PROF2] t=9074 defd=130915 defs=38944 netp=4997 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+10322ms] [2026-10-21 15:40:46][ADC_TASK] frames=9601 idle=0 skip=65 seq=9606 frst_err=0 ring=9536 adc1_rc=0 adc1_err=0 adc1_seq=9604 adc1_gap=65 adc1_hw=0 tgap=1
|
||||
[+10332ms] [2026-10-21 15:40:46][ADC_TASK] phasor(hb) C01-IA-F1: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+10343ms] [2026-10-21 15:40:46][ADC_TASK] phasor(hb) C02-UA-F1: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+10343ms] [2026-10-21 15:40:46][ADC_TASK] phasor(hb) C03-UN-F1: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+10354ms] [2026-10-21 15:40:46][ADC_TASK] phasor(hb) C04-IA-F2: Re=3 Im=-1 rms=3 (x0.1)
|
||||
[+10364ms] [2026-10-21 15:40:46][ADC_TASK] phasor(hb) C05-IA-F5: Re=0 Im=-2 rms=2 (x0.1)
|
||||
[+10364ms] [2026-10-21 15:40:46][ADC_TASK] freq(hb): f=0 valid=0 (x0.01)
|
||||
[+10974ms] [PROF] t=11076 uic=702 uip=67678 uipn=5857 uil=10999 uiw=11852 uis=1292 uisn=0 adc=10254 adcm=2286 adcn=0 gl=0
|
||||
[+10984ms] [PROF2] t=11076 defd=130915 defs=38944 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+12996ms] [PROF] t=13094 uic=884 uip=67678 uipn=9850 uil=10999 uiw=11852 uis=1292 uisn=0 adc=12272 adcm=2286 adcn=0 gl=0
|
||||
[+13007ms] [PROF2] t=13094 defd=130915 defs=38944 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+15014ms] [PROF] t=15112 uic=1066 uip=67678 uipn=9849 uil=10999 uiw=11852 uis=1292 uisn=0 adc=14290 adcm=2286 adcn=0 gl=0
|
||||
[+15025ms] [PROF2] t=15112 defd=130915 defs=38944 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+15770ms] [2026-10-21 15:40:51][PROT] elm UV-UA asserted=1 picked=1
|
||||
[+17016ms] [PROF] t=17113 uic=1243 uip=67678 uipn=1848 uil=11000 uiw=11852 uis=1292 uisn=0 adc=16291 adcm=2286 adcn=0 gl=0
|
||||
[+17016ms] [PROF2] t=17113 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+17433ms] [2026-10-21 15:40:53] [STACK] default peak_used=2152/5120 free_min=2968 (57%)
|
||||
[+17433ms] [2026-10-21 15:40:53] [STACK] net peak_used=1116/3840 free_min=2724 (70%)
|
||||
[+17444ms] [2026-10-21 15:40:53] [STACK] ftp peak_used=740/4096 free_min=3356 (81%)
|
||||
[+17454ms] [2026-10-21 15:40:53] [STACK] ui peak_used=4016/16384 free_min=12368 (75%)
|
||||
[+17454ms] [2026-10-21 15:40:53] [STACK] timesync peak_used=616/2560 free_min=1944 (75%)
|
||||
[+17465ms] [2026-10-21 15:40:53] [STACK] adc peak_used=952/2560 free_min=1608 (62%)
|
||||
[+17475ms] [2026-10-21 15:40:53] [STACK] iec104 peak_used=540/2560 free_min=2020 (78%)
|
||||
[+17475ms] [2026-10-21 15:40:53] [STACK] protect peak_used=624/2048 free_min=1424 (69%)
|
||||
[+17486ms] [2026-10-21 15:40:53] [STACK] heap free=15800 min_ever=8464
|
||||
[+19045ms] [PROF] t=19144 uic=1421 uip=67990 uipn=9849 uil=10997 uiw=11852 uis=1292 uisn=0 adc=18322 adcm=2286 adcn=0 gl=0
|
||||
[+19055ms] [PROF2] t=19144 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+20322ms] [2026-10-21 15:40:56][ADC_TASK] frames=19600 idle=0 skip=85 seq=19606 frst_err=0 ring=19515 adc1_rc=0 adc1_err=0 adc1_seq=19604 adc1_gap=85 adc1_hw=0 tgap=2
|
||||
[+20333ms] [2026-10-21 15:40:56][ADC_TASK] phasor(hb) C01-IA-F1: Re=-2 Im=0 rms=2 (x0.1)
|
||||
[+20343ms] [2026-10-21 15:40:56][ADC_TASK] phasor(hb) C02-UA-F1: Re=0 Im=-1 rms=1 (x0.1)
|
||||
[+20343ms] [2026-10-21 15:40:56][ADC_TASK] phasor(hb) C03-UN-F1: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+20354ms] [2026-10-21 15:40:56][ADC_TASK] phasor(hb) C04-IA-F2: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+20365ms] [2026-10-21 15:40:56][ADC_TASK] phasor(hb) C05-IA-F5: Re=-1 Im=0 rms=1 (x0.1)
|
||||
[+20365ms] [2026-10-21 15:40:56][ADC_TASK] freq(hb): f=0 valid=0 (x0.01)
|
||||
[+21070ms] [PROF] t=21176 uic=1600 uip=67990 uipn=6848 uil=10999 uiw=11852 uis=1292 uisn=0 adc=20353 adcm=2286 adcn=0 gl=0
|
||||
[+21081ms] [PROF2] t=21176 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+23093ms] [PROF] t=23194 uic=1782 uip=67990 uipn=9858 uil=10999 uiw=11852 uis=1292 uisn=0 adc=22371 adcm=2286 adcn=0 gl=0
|
||||
[+23103ms] [PROF2] t=23194 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+25111ms] [PROF] t=25212 uic=1964 uip=67990 uipn=9849 uil=10999 uiw=11852 uis=1292 uisn=0 adc=24389 adcm=2286 adcn=0 gl=0
|
||||
[+25121ms] [PROF2] t=25212 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+27128ms] [PROF] t=27230 uic=2146 uip=67990 uipn=9848 uil=10999 uiw=11852 uis=1292 uisn=0 adc=26407 adcm=2286 adcn=0 gl=0
|
||||
[+27138ms] [PROF2] t=27230 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+29152ms] [PROF] t=29248 uic=2328 uip=67990 uipn=9849 uil=10999 uiw=11852 uis=1292 uisn=0 adc=28425 adcm=2286 adcn=0 gl=0
|
||||
[+29152ms] [PROF2] t=29248 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+30326ms] [2026-10-21 15:41:06][ADC_TASK] frames=29599 idle=0 skip=107 seq=29606 frst_err=0 ring=29492 adc1_rc=0 adc1_err=0 adc1_seq=29604 adc1_gap=107 adc1_hw=0 tgap=3
|
||||
[+30337ms] [2026-10-21 15:41:06][ADC_TASK] phasor(hb) C01-IA-F1: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+30337ms] [2026-10-21 15:41:06][ADC_TASK] phasor(hb) C02-UA-F1: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+30348ms] [2026-10-21 15:41:06][ADC_TASK] phasor(hb) C03-UN-F1: Re=0 Im=0 rms=0 (x0.1)
|
||||
[+30358ms] [2026-10-21 15:41:06][ADC_TASK] phasor(hb) C04-IA-F2: Re=0 Im=-1 rms=1 (x0.1)
|
||||
[+30358ms] [2026-10-21 15:41:06][ADC_TASK] phasor(hb) C05-IA-F5: Re=0 Im=1 rms=1 (x0.1)
|
||||
[+30369ms] [2026-10-21 15:41:06][ADC_TASK] freq(hb): f=0 valid=0 (x0.01)
|
||||
[+31170ms] [PROF] t=31276 uic=2506 uip=67990 uipn=8849 uil=10936 uiw=56623 uis=56617 uisn=0 adc=30452 adcm=2286 adcn=0 gl=0
|
||||
[+31181ms] [PROF2] t=31276 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+33190ms] [PROF] t=33294 uic=2688 uip=67990 uipn=9849 uil=10994 uiw=56623 uis=56617 uisn=0 adc=32470 adcm=2286 adcn=0 gl=0
|
||||
[+33201ms] [PROF2] t=33294 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+35214ms] [PROF] t=35312 uic=2870 uip=67990 uipn=9856 uil=10999 uiw=56623 uis=56617 uisn=0 adc=34488 adcm=2286 adcn=0 gl=0
|
||||
[+35224ms] [PROF2] t=35312 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+37231ms] [PROF] t=37330 uic=3052 uip=67990 uipn=9849 uil=10997 uiw=56623 uis=56617 uisn=0 adc=36506 adcm=2286 adcn=0 gl=0
|
||||
[+37242ms] [PROF2] t=37330 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+39251ms] [PROF] t=39348 uic=3234 uip=67990 uipn=9849 uil=10999 uiw=56623 uis=56617 uisn=0 adc=38524 adcm=2286 adcn=0 gl=0
|
||||
[+39251ms] [PROF2] t=39348 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+40326ms] [2026-10-21 15:41:16][ADC_TASK] frames=39598 idle=0 skip=115 seq=39606 frst_err=0 ring=39483 adc1_rc=0 adc1_err=0 adc1_seq=39604 adc1_gap=115 adc1_hw=0 tgap=4
|
||||
[+40336ms] [2026-10-21 15:41:16][ADC_TASK] phasor(hb) C01-IA-F1: Re=-1 Im=0 rms=1 (x0.1)
|
||||
[+40336ms] [2026-10-21 15:41:16][ADC_TASK] phasor(hb) C02-UA-F1: Re=0 Im=-1 rms=1 (x0.1)
|
||||
[+40347ms] [2026-10-21 15:41:16][ADC_TASK] phasor(hb) C03-UN-F1: Re=-1 Im=1 rms=1 (x0.1)
|
||||
[+40358ms] [2026-10-21 15:41:16][ADC_TASK] phasor(hb) C04-IA-F2: Re=3 Im=0 rms=3 (x0.1)
|
||||
[+40358ms] [2026-10-21 15:41:16][ADC_TASK] phasor(hb) C05-IA-F5: Re=2 Im=0 rms=2 (x0.1)
|
||||
[+40368ms] [2026-10-21 15:41:16][ADC_TASK] freq(hb): f=0 valid=0 (x0.01)
|
||||
[+41275ms] [PROF] t=41376 uic=3412 uip=67990 uipn=7849 uil=10934 uiw=56623 uis=56617 uisn=0 adc=40551 adcm=2286 adcn=0 gl=0
|
||||
[+41286ms] [PROF2] t=41376 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
[+43296ms] [PROF] t=43394 uic=3594 uip=67990 uipn=9849 uil=10999 uiw=56623 uis=56617 uisn=0 adc=42569 adcm=2286 adcn=0 gl=0
|
||||
[+43307ms] [PROF2] t=43394 defd=130915 defs=40473 netp=5012 netn=0 adcp=11 adcq=0 gl=0
|
||||
@@ -20,6 +20,7 @@
|
||||
| 构建标识 | 建议含:产品 / 测试套件(`prod_none` / `suite_ch395f` …)+ 负载(`idle` / `v5_30min` / `ftp_stress`) |
|
||||
| 随文件登记 | 在下方 §3 清单登记日期、构建、负载、关键 `[STACK]` 水位(如 defaultTask 峰值) |
|
||||
| 入库门槛 | **只存有对照价值的快照**——常规 `@test` 通过日志不必入库 |
|
||||
| 故障注入日志 | 含**刻意产生**的 `[ERR]` 行(如兜底门闭锁)的日志用自定义标记集采集:`--required` 加闭锁/复归两行、`--forbidden` 去掉 `[ERR]` 保留 `FAIL;ERROR;HardFault`。此类日志的 PASS 只代表注入行为符合预期,不代表标记集等价于日常门禁 |
|
||||
|
||||
## 3. 清单
|
||||
|
||||
@@ -35,6 +36,7 @@
|
||||
| 2026-10-12 | 同 PASS 固件(B7+fix)/ **PC 主站 2404 往返**(复测) | 同上全链 18/18 PASS——B7 `set_sealed`+持久化写路径下 C_SE→YX 联动仍成立(B5 遗留"104 YX 联动"腿闭环) | `20261012_B6_iec104_roundtrip_log.txt` |
|
||||
| 2026-10-12 | 同 PASS 固件 / **B7 定值持久化 + 软压板 YK12 台架腿**(`test/host/iec104_master.py --b7-pre/--b7-post/--b7-mark/--b7-check`,中间 ST-LINK 复位) | pre **21/21**:C_SE 写 7.5+C_RD 回读、YK12 两段 OFF → 0.05 A 低定值**不动作**(保护退出)、YK12 ON → YX15/16 立即动作(COT=3)、收尾留压板退出;post **13/13**:**压板退出态跨复位保持**(开机日志 `global plate OUT -> protection disabled` + 低定值仍不动作)、重启后 YK12 ON 即动作(联动在位);mark/check **4/4+4/4**:**非默认定值 7.5 跨复位保持**(C_RD=7.500,与出厂默认可区分);开机日志两次 `[CFG] prot set loaded (/prot_set.bin)` | `20261012_B7_iec104_persist_log.txt` / `20261012_B7_persist_boot_log.txt` |
|
||||
| 2026-10-12 | `prod`(B9 `1d96fc9` sync 追平 B8/N33 后重跑,merge `6cbf400` 覆盖代码)/ **B9 SOE 动作记录 + 时标台架腿** | `@test` **PASS**:锚点 `protection init: OK (set=40 elm=9)`、`freq layer init: OK`、`freq(hb): f=0 valid=0`(浮空不发散)、**`prot set blob version change (ver=1 cnt=32), defaults in use`**(B8 换代 INFO ≠ CORRUPT 实证)、零 `[ERR]`、`protect` 828/2048(59%,与静态 872 相符);主站回归 `--b7-pre` **21/21** + `--b7-post` **13/13** 不回归,**自发 YX = M_SP_TB_1 带 CP56 时标**(动作/复归/重启后联动三段,iv=0);FTP 下载 `/log/soe.log` **56 条** `test/host/soe/decode_soe.py --max-elm 16` **PASS**(boot 段内 seq 严格 +1、ELM_ASSERT 26、CP56↔epoch UTC 交叉一致);`.bin` 为原始 64 B 记录可复解码 | `20261012_B9_prod_boot_log.txt` / `20261012_B9_iec104_soe_pre_log.txt` / `20261012_B9_iec104_soe_post_log.txt` / `20261012_B9_soe_pre.bin` + `20261012_B9_soe_after_post.bin` / `20261012_B9_soe_decode_pre.txt` + `20261012_B9_soe_decode_post.txt` |
|
||||
| 2026-10-21 | `prod` + **兜底新鲜度门停 TIM3 注入探针**(`task/adc-health-design-doc`,探针已撤)/ 开机 + 45 s | `protect` **620/2048(69%)**、`adc` 与 heap 水位同前;`[ERR][PROT] … blocked (hf=0x00000100)` +5462ms、`recovered` +5757ms、`health:` 0 次、`reset cause:` ×1 | `20261021_probe_stale_gate_boot_log.txt` |
|
||||
|
||||
## 4. 关联
|
||||
|
||||
|
||||
+83
-13
@@ -34,9 +34,9 @@
|
||||
- [12. 现场判读手册](#12-现场判读手册)
|
||||
- [13. 自测问题(读完能不能真的懂)](#13-自测问题读完能不能真的懂)
|
||||
- [14. 改它之前必读](#14-改它之前必读)
|
||||
- [15. 相关文档](#15-相关文档)
|
||||
- [15. 兜底新鲜度门(保护侧独立通道)](#15-兜底新鲜度门保护侧独立通道)
|
||||
- [16. 相关文档](#16-相关文档)
|
||||
- [变更记录](#变更记录)
|
||||
|
||||
---
|
||||
|
||||
## 1. 三分钟建立心智模型
|
||||
@@ -312,7 +312,8 @@ else { 清电平位 } /* 只有 stall 类有 else 分支,SEQ_BACKWARD 没有
|
||||
| 5 | `ADC_HF_HW_ERR` / `ADC_HE_HW_ERR` | 锁存 + 事件 | `stm32_hw_errs` 有变化 | 仅 `adc_health_init()` |
|
||||
| 6 | `ADC_HE_TPAFE_GAP` | 仅事件 | 本次 TPAFE `d > 1` | 出参,不落状态 |
|
||||
| 7 | `ADC_HE_STM32_GAP` | 仅事件 | `stm32_gaps` 有变化 | 出参,不落状态 |
|
||||
| 8..31 | 保留 | — | 未使用 | — |
|
||||
| 8 | `ADC_HF_STALE` | 电平(**由 protectTask 置位**,判定层不写) | 帧年龄 >= 120 ms(§15) | 序号恢复前进 |
|
||||
| 9..31 | 保留 | — | 未使用 | — |
|
||||
|
||||
**位号对齐是刻意设计**:bit3 / bit4 / bit5 在 `events` 与 `sticky` 里编号相同,编排层因此可以
|
||||
拿事件位直接去操作「已留痕位图」,一行搞定每类每次开机只留痕一次:
|
||||
@@ -367,7 +368,7 @@ if (((serious | rise) & ~s_health_logged) != 0u) { /* 位图当去重键 */
|
||||
|
||||
| 故障位置 | 谁先发现 | 多久 | 结果 |
|
||||
|---|---|---|---|
|
||||
| TIM3 节拍源停 | **不是本层**:`adcTask` 永久阻塞在 `osThreadFlagsWait`,没人跑判定 | 100 ms 抽样 + 连续 800 ms 缺席起停喂 | IWDG 溢出复位(标称 2498 ms,LSI 偏快约 1701 ms) |
|
||||
| TIM3 节拍源停 | 本层**看不见**(`adcTask` 永久阻塞,没人跑判定)→ 由 §15 兜底门判老 | §15:120 ms;看门狗:100 ms 抽样 + 连续 800 ms 停喂 | §15 闭锁保护(≤140 ms);IWDG 溢出复位(标称 2498 ms,LSI 偏快约 1701 ms) |
|
||||
| TPAFE BUSY EXTI 停 | 本层 `ADC_HF_TPAFE_STALL` | 100 ms | 闭锁保护(任务仍活着,不复位) |
|
||||
| ADC1 / DMA 停 | 本层 `ADC_HF_STM32_STALL`,L1 的 `stm32_errs` 增量同时给出事件 | 100 ms | 闭锁 + 留痕 |
|
||||
| HAL 报错 | L1 计数 → 本层 `HE_HW_ERR` | 下一拍 | 事件 + 锁存,不闭锁 |
|
||||
@@ -375,13 +376,27 @@ if (((serious | rise) & ~s_health_logged) != 0u) { /* 位图当去重键 */
|
||||
| 帧序号倒退 | 本层 `SEQ_BACKWARD` | 当拍 | 闭锁且不自愈,直到复位 |
|
||||
|
||||
一句话概括本层的**能力边界**:它判的是「生产者相对消费者是否前进」,因此**判不了消费者自己**
|
||||
是否还活着。后者必须换一个独立机制(IWDG)来实现——两层不能互相替代,也不要指望把门限调小
|
||||
就能替代它。
|
||||
是否还活着。过去只能靠 IWDG 兜命——它判的是"任务还在不在",不是"数据新不新";现在另有一条与本层
|
||||
完全解耦的兜底门专门管这件事(§15)。三者不可互相替代,也别指望把本层门限调小来顶班。
|
||||
|
||||
**如实登记的已知窗口**:TIM3 停摆到 IWDG 复位之间(最坏约 800 ms + 2498 ms ≈ 3.3 s,标称值),
|
||||
`protectTask` 仍在 20 ms 轮询、电平位却还没人置(判定随消费者一起停了),相量保持旧值参与判据。
|
||||
V0.1 没有出口硬件,后果限于遥信与日志;真要压这个窗口,正解是给相量侧加「帧年龄」判据
|
||||
(让 `prot_elm` 自己看数据新鲜度),而不是把 stall 门限调小。
|
||||
**这条盲区已闭合(原已知窗口)**:TIM3 停摆到 IWDG 复位之间,原本最坏约 800 ms + 2498 ms(标称)内
|
||||
`protectTask` 仍在 20 ms 轮询、而电平位还没人置——相量冻在最后一帧继续参与判据。现在 §15 的兜底门
|
||||
在同一工况下 120 ms 判老并闭锁。
|
||||
|
||||
台架实测(一次性停 TIM3 探针,验完即撤):
|
||||
|
||||
```text
|
||||
[+5410ms] [STACK] protect peak_used=620/2048 free_min=1428 (69%)
|
||||
[+5462ms] [ERR][PROT] sampling FAULT -> protection blocked (hf=0x00000100)
|
||||
[+5555ms] MISS start snap=0x000001B7 req=0x000001F7 t=5656
|
||||
[+5757ms] [PROT] sampling recovered -> protection resumed
|
||||
```
|
||||
|
||||
三条证据同时成立才算闭合:`hf` **只有 bit8、没有 stall 位**(闭锁由兜底门独立给出);同一次开机里
|
||||
`[ADC_TASK] health:` 行出现 **0 次**(判定层确实全程失明);`snap` 相对 `req` 缺的正是 bit6 =
|
||||
`TASK_WD_ADC`(`0x1F7 − 0x1B7 = 0x40`,实证 adcTask 当时真的阻塞,而不是"还在跑但没报");
|
||||
`reset cause:` 仅 1 次——300 ms 停摆被看门狗的 800 ms 容忍吸收,**闭锁不靠复位**。
|
||||
证据文件 `docs/测试说明/boot_log_data/20261021_probe_stale_gate_boot_log.txt`。
|
||||
|
||||
---
|
||||
|
||||
@@ -430,7 +445,8 @@ stateDiagram-v2
|
||||
1. `adc_health_status_t` 只给 `tpafe_stall_ms`,**STM32 侧没有对应的停滞时长字段**——
|
||||
只知道「STM32 静默了」,不知道「静默多久」。
|
||||
2. `tpafe_stall_ms` 只在电平位置位时给值,正常态恒为 0,因此它不能当「距上次前进的时间」趋势量用。
|
||||
3. **观察者死亡不可自证**(§8 的责任矩阵),判定层的存活依赖 `adcTask`。
|
||||
3. **观察者死亡本层不可自证**(§8 责任矩阵):判定层的存活依赖 `adcTask`。该盲区由 §15 的兜底门
|
||||
闭合(保护不再吃陈旧数据),但**本层自身**仍然报不出"我没在跑"这件事。
|
||||
4. `tgap` 与 `adc1_gap` 单位不同(点 / 次,§6.2),跨字段做除法或对比会得出错误结论。
|
||||
5. 倒退的可判定窗是 ±2^31 拍(约 ±24.85 天),窗口外的倒退读作前进(§6.3)。
|
||||
|
||||
@@ -455,8 +471,14 @@ stateDiagram-v2
|
||||
| tick 回绕 | `TC-ADCHEALTH-009` | 跨 0xFFFFFFFF 扫 512 拍不误报;回绕后冻结仍能检出 |
|
||||
| 空指针守卫 | `TC-ADCHEALTH-010` | `in == NULL` 不动 `out`;`out == NULL` 仍更新内部状态 |
|
||||
| 幂等复位 | `TC-ADCHEALTH-011` | 故障后 `adc_health_init()` 全清,且重新建基线干净 |
|
||||
| 帧年龄:首拍只建基线 | `TC-ADCHEALTH-012` | 第一次观测只记参照系并返回 0(开机窗口不得误锁保护) |
|
||||
| 帧年龄:健康与超拍 | `TC-ADCHEALTH-013` | 2000 拍扫描恒不判老,其中每 7 拍造一次 `d = 3` 的超拍 |
|
||||
| 帧年龄:门限含等号 | `TC-ADCHEALTH-014` | 差 1 ms 不判、到点即判;重新前进立刻不判老 |
|
||||
| 帧年龄:回绕 | `TC-ADCHEALTH-015` | tick 与序号一起跨 0xFFFFFFFF 不误判;回绕后冻结仍判老 |
|
||||
| 帧年龄:倒退分工 | `TC-ADCHEALTH-016` | 倒退按「有变化」不判老并重对齐(此后 119 ms 不判、120 ms 判) |
|
||||
| 帧年龄:多观察者 | `TC-ADCHEALTH-017` | 两个 age 对象并行观测互不污染;空参数返回 0(宁可不锁) |
|
||||
|
||||
合计 **11 组用例 / 31 条断言**(用例清单与被测源文件同一处:
|
||||
合计 **17 组用例 / 45 条断言**(用例清单与被测源文件同一处:
|
||||
`test/host/adc_health/adc_health_test.c` 文件头)。跑法:
|
||||
|
||||
```powershell
|
||||
@@ -503,6 +525,7 @@ stateDiagram-v2
|
||||
| `[ADC_TASK] health: recovered flags=0x0 sticky=0x3` | 静默自愈 | 别把「恢复」读成「没问题」:`sticky=0x3` 说明两侧都停过 |
|
||||
| `[PROT] sampling FAULT -> protection blocked (hf=0x00000001)` | 闭锁真的生效了 | 括号里就是命中位;此后保护不判据,元件状态全复位 |
|
||||
| `[PROT] sampling recovered -> protection resumed` | 闭锁解除 | 与上一条配对看时长 |
|
||||
| `…protection blocked (hf=0x00000100)` | **判定层失明时的兜底**:只有 bit8、stall 位一个都没报 | 查节拍源与 `adcTask`:同次开机 `[ADC_TASK] health:` 是否 0 次、`MISS` 快照是否缺 bit6(§15) |
|
||||
| 心跳 `tgap=` 持续上涨 | 消费者超拍 | 看 `[PROF]` 的 `adcm` 是否 > 1 ms(`docs/子系统设计/看门狗设计说明.md` §11.4) |
|
||||
|
||||
两个必须记住的读法:
|
||||
@@ -546,6 +569,7 @@ stateDiagram-v2
|
||||
| 动驱动侧计数器(自增时机、清零点、位宽) | 必须同时复核 §6.3 的倒退路径与 §6.4 的 `!=` 增量口径;位宽一变就可能造出假增量 |
|
||||
| 把任何 `*_init()` 挪到运行期重跑 | **必须同时 `adc_health_init()`**——`App/algo/adc_input.c` 的 init 会把 `s_dma_seq` 归零,不配套就第一拍报 `SEQ_BACKWARD` 并永久闭锁 |
|
||||
| 在判定层引入 HAL / 日志 / 内核 API | 先回答「主机单测怎么免桩跑」;答不上来就别改 |
|
||||
| 动兜底门(§15) | 同步 `PROT_HF_LOCK_MASK`、§7 位表 bit8 行、§8 责任矩阵、§11 的 TC-ADCHEALTH-012..017、配图生成器 `tools/arch_diagram/gen_adc_health_bitmap_svg.py`;两条车道的 `primed` 必须各一份 |
|
||||
|
||||
三条禁令(都对应已写死的机制,不是风格问题):
|
||||
|
||||
@@ -567,7 +591,51 @@ stateDiagram-v2
|
||||
|
||||
---
|
||||
|
||||
## 15. 相关文档
|
||||
## 15. 兜底新鲜度门(保护侧独立通道)
|
||||
|
||||
本节补的是本层的**结构性盲区**(§8 责任矩阵第一行):判定层的每一次判定都要有人替它跑,而那个
|
||||
人是 `adcTask`。节拍源一停,`adcTask` 就永久阻塞在 `osThreadFlagsWait`(刻意的 fail-safe),
|
||||
`adc_health_check()` 不再执行,`flags` 冻结在 0,而 `protectTask` 仍每 20 ms 拿冻住的相量判据。
|
||||
|
||||
**观测点为什么只能是那两个计数器**(整套方案的地基,选错就还是自证):
|
||||
|
||||
| 候选证据 | 写者 | 依赖 `adcTask` 存活 | 能否当兜底证据 |
|
||||
|---|---|---|---|
|
||||
| `phasor_get()` / 采样环的最后计算时刻 | adcTask | 是 | ❌ 自证 |
|
||||
| `adc_health_flags()` | adcTask(每拍 `check()`) | 是 | ❌ 就是它漏的 |
|
||||
| `tpafe5160_frame_seq()` | BUSY EXTI 中断 | 否 | ✅ |
|
||||
| `adc_input_stm32_seq()`(`s_dma_seq`) | DMA2 Stream4 中断 | 否 | ✅ |
|
||||
|
||||
**状态归属是设计要点,不是风格**:`adc_health_age_stale()` 是无模块状态的纯函数,参照系
|
||||
`adc_health_age_t` **由调用方自存**。`adc_health_check()` 用的模块级状态是「每拍一次、单写者」的
|
||||
契约——若让 `protectTask` 也去调它,两个上下文会互相刷新差值基线,把现有判定层一起弄坏。状态放
|
||||
调用方之后,「多个观察者各判各的」在结构上不可能互相污染(`TC-ADCHEALTH-017` 钉这条)。
|
||||
|
||||
**门限 120 ms** = `PROT_STALE_AGE_MS`(`ADC_HEALTH_STALL_MS` + `PROTECT_TASK_CYCLE_MS`)。本门
|
||||
每 20 ms 才观测一次,最坏比判定层晚一整周期;这 20 ms 买的是**时序阶梯**:判定层活着时它先报
|
||||
(`0x1`/`0x2`,带日志与自检留痕),本门随后补 `0x100`;判定层死了则只出现 `0x100`。排查时两类
|
||||
位的先后本身就是「判定层当时活着吗」的免费答案。闭锁最迟时刻 = 120 ms + ≤20 ms 观测相位 = **≤140 ms**,
|
||||
仍远小于保护最小动作延时(OF/UF 默认 1000 ms)。
|
||||
|
||||
三条实现细节(每一条都对应一次误锁风险):
|
||||
|
||||
- **`primed` 必须两条车道各一份**。共用一个标志时,先被观测的车道把它置 1,另一条首拍就拿
|
||||
`adv_ms = 0` 去算年龄 → **开机即误锁保护**。
|
||||
- **倒退按「有变化」处理并重对齐参照系**,不判老:单调性破坏归 `ADC_HF_SEQ_BACKWARD`,两条判据
|
||||
不互相顶班(`TC-ADCHEALTH-016` 把「重对齐后计时起点跟着走」钉住)。
|
||||
- **参数错返回 0**(不判老)——兜底门宁可漏锁一次,也不能因为一个空指针把保护永久锁掉。
|
||||
|
||||
**与留痕体系的关系**:本位不进 `sticky`、不进编排层的 `logged` 位图、判定层也不写它;留痕走
|
||||
`protectTask` 既有的闭锁边沿日志与 SOE 类型 5/6(value 里直接带 `0x100`,见 §12 判读)。
|
||||
|
||||
**边界与残余**:TIM3 停 → ADC1 无触发 → 无 DMA 请求 → `s_dma_seq` 也停(节拍源是唯一上游,别
|
||||
以为「DMA 还在循环所以计数会涨」)。开机不误锁的前提是 TIM3 在 `app_main_init()` 就启动、远早于
|
||||
`osKernelStart()`(`docs/子系统设计/ADC采样节拍设计说明.md` §3.4),protectTask 首拍时计数器已在
|
||||
前进。残余风险:`protectTask` 自己被饿死时无人判老,此时退回 IWDG(它在 `required_mask = 0x1F7` 内)。
|
||||
|
||||
---
|
||||
|
||||
## 16. 相关文档
|
||||
|
||||
- `docs/算法/采集与算法层设计说明.md` §4 —— 本模块在全层中的位置与接口速览(本文不重复)
|
||||
- `docs/子系统设计/ADC采样节拍设计说明.md` §8 —— 心跳字段全表与判读(`tgap` 所在行)
|
||||
@@ -578,6 +646,7 @@ stateDiagram-v2
|
||||
- `docs/算法/继电保护功能复现规划.md` §3.5 —— L5 自检与闭锁(本层供数的 L5-4 在此登记)
|
||||
- `docs/内存管理/RAM使用分析与优化方案.md` §1.4 —— `adcTask` 栈最坏链台账
|
||||
- `App/algo/README.md` —— 目录级文件清单与构建测试入口
|
||||
- `docs/子系统设计/ADC采样节拍设计说明.md` §3.4 —— TIM3 启动位置与顺序(兜底门开机不误锁的前提)
|
||||
|
||||
---
|
||||
|
||||
@@ -586,4 +655,5 @@ stateDiagram-v2
|
||||
| 日期 | 变更 | 说明 |
|
||||
|---|---|---|
|
||||
| 2026-10-21 | 新建 | 首版单文件深设计:判据推导、四种位语义、闭锁与兜底责任矩阵、验证分工与现场判读手册;新增三张配图生成器(`tools/arch_diagram/gen_adc_health_flow_svg.py`、`gen_adc_health_bitmap_svg.py`、`gen_adc_health_timeline_svg.py`)与产物 SVG |
|
||||
| 2026-10-21 | 新增 §15 | 兜底新鲜度门:`adc_health_age_stale()` 无状态纯判据 + `ADC_HF_STALE`(bit8)+ `protectTask` 独立观测;§7 位表、§8 责任矩阵与「已知窗口」段、§10 盲区、§11 用例表、§12 判读、§14 清单与位图配图全部同步 |
|
||||
| 2026-10-21 | §14 更新 | 初始化入口已接线:`adc_task_func()` 进循环前调 `adc_task_init()`(该入口不再打日志);同时删除 `App/task/net_task.c` 里的空壳 `net_task_init()` |
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
* TC-ADCHEALTH-009 tick 回绕:跨 0xFFFFFFFF 的正常推进不误报静默;回绕后冻结仍报
|
||||
* TC-ADCHEALTH-010 NULL 守卫:in=NULL 跳过;out=NULL 只更新内部状态
|
||||
* TC-ADCHEALTH-011 init 幂等:故障后 re-init 全清
|
||||
* TC-ADCHEALTH-012 帧年龄纯判据:首拍只建基线、不判老(开机不得误锁)
|
||||
* TC-ADCHEALTH-013 帧年龄纯判据:正常推进恒不判老,一次前进 3 帧也不判老
|
||||
* TC-ADCHEALTH-014 帧年龄纯判据:门限含等号(差 1 不判、到点判),恢复前进即清
|
||||
* TC-ADCHEALTH-015 帧年龄纯判据:tick 与序号跨 0xFFFFFFFF 不误判、停滞仍判老
|
||||
* TC-ADCHEALTH-016 帧年龄纯判据:序号倒退按「有变化」处理,不判老(判据分工)
|
||||
* TC-ADCHEALTH-017 帧年龄纯判据:两个 age 对象互不干扰;空指针不判老
|
||||
*
|
||||
* 通过:全部 TC PASS(main 返回 0)。
|
||||
* 入口:int main(void),返回 0=PASS / 1=FAIL(由 run 脚本判读)。
|
||||
@@ -349,6 +355,125 @@ static void tc_reinit(void) {
|
||||
"TC-ADCHEALTH-011 re-prime after re-init is clean");
|
||||
}
|
||||
|
||||
/* ===================== 帧年龄纯判据(保护侧兜底门专用) ===================== */
|
||||
|
||||
/* 构造一个"未建基线"的参照系(本测试只用 stdint/stdio,不引 string.h) */
|
||||
static adc_health_age_t mk_age(void) {
|
||||
adc_health_age_t a;
|
||||
|
||||
a.seq = 0u;
|
||||
a.adv_ms = 0u;
|
||||
a.primed = 0u;
|
||||
return a;
|
||||
}
|
||||
|
||||
/* TC-ADCHEALTH-012:首拍只建基线 */
|
||||
static void tc_age_prime(void) {
|
||||
adc_health_age_t age = mk_age();
|
||||
|
||||
CHECK(adc_health_age_stale(&age, 4242u, 1000u, 120u) == 0u,
|
||||
"TC-ADCHEALTH-012 first observation only primes");
|
||||
CHECK((age.primed == 1u) && (age.seq == 4242u) && (age.adv_ms == 1000u),
|
||||
"TC-ADCHEALTH-012 baseline recorded by first call");
|
||||
CHECK(adc_health_age_stale(&age, 4242u, 1001u, 120u) == 0u,
|
||||
"TC-ADCHEALTH-012 1ms idle is not stale");
|
||||
}
|
||||
|
||||
/* TC-ADCHEALTH-013:正常推进与超拍都不该判老 */
|
||||
static void tc_age_healthy(void) {
|
||||
adc_health_age_t age = mk_age();
|
||||
uint32_t seq = 0u, now = 0u;
|
||||
int i, ok = 1;
|
||||
|
||||
for (i = 0; i < 2000; i++) {
|
||||
if (adc_health_age_stale(&age, seq, now, 120u) != 0u) {
|
||||
ok = 0;
|
||||
}
|
||||
seq += ((i % 7) == 6) ? 3u : 1u; /* 每 7 拍造一次「前进 3 帧」的超拍 */
|
||||
now += 1u;
|
||||
}
|
||||
CHECK(ok, "TC-ADCHEALTH-013 advancing (incl. d=3 overrun) never goes stale");
|
||||
CHECK(now > 120u, "TC-ADCHEALTH-013 sweep exceeded the threshold span");
|
||||
}
|
||||
|
||||
/* TC-ADCHEALTH-014:门限含等号 + 恢复即清 */
|
||||
static void tc_age_threshold(void) {
|
||||
adc_health_age_t age = mk_age();
|
||||
uint32_t t;
|
||||
int ok = 1;
|
||||
|
||||
(void)adc_health_age_stale(&age, 10u, 0u, 120u); /* 建基线 */
|
||||
(void)adc_health_age_stale(&age, 11u, 10u, 120u); /* 前进:adv_ms = 10 */
|
||||
for (t = 11u; t < 130u; t++) {
|
||||
uint8_t want = ((t - 10u) >= 120u) ? 1u : 0u;
|
||||
if (adc_health_age_stale(&age, 11u, t, 120u) != want) {
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
CHECK(ok, "TC-ADCHEALTH-014 stale exactly at age_ms (inclusive boundary)");
|
||||
CHECK(adc_health_age_stale(&age, 12u, 200u, 120u) == 0u,
|
||||
"TC-ADCHEALTH-014 advancing again clears staleness");
|
||||
}
|
||||
|
||||
/* TC-ADCHEALTH-015:tick 与序号一起跨回绕 */
|
||||
static void tc_age_wrap(void) {
|
||||
adc_health_age_t age = mk_age();
|
||||
uint32_t seq = 700000u, now = 0xFFFFFF00u;
|
||||
int i, ok = 1;
|
||||
|
||||
for (i = 0; i < 512; i++) {
|
||||
if (adc_health_age_stale(&age, seq, now, 120u) != 0u) {
|
||||
ok = 0;
|
||||
}
|
||||
seq++; now++; /* uint32 自然回绕 */
|
||||
}
|
||||
CHECK(ok, "TC-ADCHEALTH-015 sweep across 0xFFFFFFFF never goes stale");
|
||||
seq--; /* 回到最后一次被观测到的值:此后两侧冻结 */
|
||||
for (i = 0; i < 121; i++) {
|
||||
now++;
|
||||
}
|
||||
CHECK(adc_health_age_stale(&age, seq, now, 120u) != 0u,
|
||||
"TC-ADCHEALTH-015 still detected stale after wrap");
|
||||
}
|
||||
|
||||
/* TC-ADCHEALTH-016:倒退按「有变化」处理,不判老 */
|
||||
static void tc_age_backward(void) {
|
||||
adc_health_age_t age = mk_age();
|
||||
|
||||
(void)adc_health_age_stale(&age, 1000u, 100u, 120u);
|
||||
CHECK(adc_health_age_stale(&age, 995u, 101u, 120u) == 0u,
|
||||
"TC-ADCHEALTH-016 backward counts as change, not staleness");
|
||||
/* 倒退已把参照系重新对齐到 995(adv_ms = 101):此后停在 995 上,
|
||||
* 差 1 ms 不判老、到点才判老——把"重对齐后计时起点跟着走"钉住 */
|
||||
CHECK(adc_health_age_stale(&age, 995u, 220u, 120u) == 0u,
|
||||
"TC-ADCHEALTH-016 119ms after re-alignment is not stale yet");
|
||||
CHECK(adc_health_age_stale(&age, 995u, 221u, 120u) != 0u,
|
||||
"TC-ADCHEALTH-016 baseline re-aligned by backward step");
|
||||
}
|
||||
|
||||
/* TC-ADCHEALTH-017:两个观察者互不干扰 + 空指针守卫 */
|
||||
static void tc_age_two_observers(void) {
|
||||
adc_health_age_t a = mk_age(); /* 模拟 adcTask:每拍观测 */
|
||||
adc_health_age_t b = mk_age(); /* 模拟 protectTask:每 20 拍观测 */
|
||||
uint32_t seq = 500u;
|
||||
uint32_t t;
|
||||
int ok = 1;
|
||||
|
||||
(void)adc_health_age_stale(&a, seq, 0u, 100u);
|
||||
(void)adc_health_age_stale(&b, seq, 0u, 120u);
|
||||
for (t = 1u; t <= 200u; t++) {
|
||||
(void)adc_health_age_stale(&a, seq + t, t, 100u);
|
||||
if ((t % 20u) == 0u) {
|
||||
if (adc_health_age_stale(&b, seq + t, t, 120u) != 0u) {
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
CHECK(ok, "TC-ADCHEALTH-017 two independent observers do not pollute each other");
|
||||
CHECK(adc_health_age_stale(0, 1u, 1u, 120u) == 0u,
|
||||
"TC-ADCHEALTH-017 NULL age never reports stale (no false lock)");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
printf("=== ADC Health Tests ===\n");
|
||||
|
||||
@@ -364,6 +489,12 @@ int main(void) {
|
||||
tc_backward();
|
||||
tc_err_counters();
|
||||
printf("-- tick wrap / guards / re-init --\n");
|
||||
tc_age_prime();
|
||||
tc_age_healthy();
|
||||
tc_age_threshold();
|
||||
tc_age_wrap();
|
||||
tc_age_backward();
|
||||
tc_age_two_observers();
|
||||
tc_tick_wrap();
|
||||
tc_null_guard();
|
||||
tc_reinit();
|
||||
|
||||
@@ -30,8 +30,8 @@ HEAD_FONT = 12.5
|
||||
|
||||
LABEL_X, LABEL_W = PAD, 262
|
||||
GRID_X = PAD + LABEL_W + 8
|
||||
BIT_W, BIT_H, BIT_GAP = 112, 46, 4
|
||||
NOTE_W = 340
|
||||
BIT_W, BIT_H, BIT_GAP = 94, 46, 4
|
||||
NOTE_W = 320
|
||||
GROUP_GAP = 26
|
||||
|
||||
FONT = "Microsoft YaHei, Segoe UI, PingFang SC, sans-serif"
|
||||
@@ -47,53 +47,58 @@ C_NONE = ("#94a3b8", "#f8fafc") # 未使用 / 不适用
|
||||
GROUPS = [
|
||||
dict(head="判定层写出的三张位图(adc_health.c)", rows=[
|
||||
dict(label="flags 电平位", sub="adc_health_flags(),当前活跃",
|
||||
note="protectTask 每 20 ms 读它做 L5-4 闭锁;不看事件位",
|
||||
note="protectTask 每 20 ms 读它做 L5-4 闭锁;bit8 由本任务自己判老后 OR 入(判定层不写)",
|
||||
bits=[("bit0", "TPAFE_STALL", "level"), ("bit1", "STM32_STALL", "level"),
|
||||
("bit2", "SEQ_BACKWARD", "latch"), ("bit3", "—", "none"),
|
||||
("bit4", "—", "none"), ("bit5", "—", "none"),
|
||||
("bit6", "—", "none"), ("bit7", "—", "none")]),
|
||||
("bit6", "—", "none"), ("bit7", "—", "none"),
|
||||
("bit8", "STALE", "level")]),
|
||||
dict(label="sticky 锁存位", sub="adc_health_sticky(),直到 init 才清",
|
||||
note="只留痕不闭锁:曾停摆/曾出错必须可追溯",
|
||||
bits=[("bit0", "TPAFE_STALL", "latch"), ("bit1", "STM32_STALL", "latch"),
|
||||
("bit2", "SEQ_BACKWARD", "latch"), ("bit3", "FRSTDATA", "latch"),
|
||||
("bit4", "STM32_ERR", "latch"), ("bit5", "HW_ERR", "latch"),
|
||||
("bit6", "不入锁存", "none"), ("bit7", "不入锁存", "none")]),
|
||||
("bit6", "不入锁存", "none"), ("bit7", "不入锁存", "none"),
|
||||
("bit8", "不入锁存", "none")]),
|
||||
dict(label="events 事件位", sub="adc_health_check() 出参,仅当拍有效",
|
||||
note="adc_health_report() 的唯一输入:按位分三级处置",
|
||||
bits=[("bit0", "—", "none"), ("bit1", "—", "none"), ("bit2", "—", "none"),
|
||||
("bit3", "FRSTDATA", "event"), ("bit4", "STM32_ERR", "event"),
|
||||
("bit5", "HW_ERR", "event"), ("bit6", "TPAFE_GAP", "event"),
|
||||
("bit7", "STM32_GAP", "event")]),
|
||||
("bit7", "STM32_GAP", "event"), ("bit8", "—", "none")]),
|
||||
]),
|
||||
dict(head="消费者侧的掩码与记忆位图", rows=[
|
||||
dict(label="PROT_HF_LOCK_MASK", sub="protect_task.c 编译期常量",
|
||||
note="命中即 prot_elm_init() 复位元件 + 本拍不 eval;SOE 类型 5/6",
|
||||
note="命中即 prot_elm_init() 复位元件 + 本拍不 eval;SOE 5/6 带位图",
|
||||
bits=[("bit0", "闭锁", "mask"), ("bit1", "闭锁", "mask"),
|
||||
("bit2", "闭锁", "mask"), ("bit3", "不闭锁", "none"),
|
||||
("bit4", "不闭锁", "none"), ("bit5", "不闭锁", "none"),
|
||||
("bit6", "—", "none"), ("bit7", "—", "none")]),
|
||||
("bit6", "—", "none"), ("bit7", "—", "none"),
|
||||
("bit8", "闭锁", "mask")]),
|
||||
dict(label="serious 严重事件", sub="adc_task.c 的 adc_health_report()",
|
||||
note="三类计数增量恒应为 0 → 每次 DBG_ERROR + 自检留痕",
|
||||
bits=[("bit0", "—", "none"), ("bit1", "—", "none"), ("bit2", "—", "none"),
|
||||
("bit3", "FRSTDATA", "mask"), ("bit4", "STM32_ERR", "mask"),
|
||||
("bit5", "HW_ERR", "mask"), ("bit6", "—", "none"),
|
||||
("bit7", "—", "none")]),
|
||||
("bit7", "—", "none"), ("bit8", "—", "none")]),
|
||||
dict(label="gap 丢帧事件", sub="同一函数里的丢帧分支",
|
||||
note="刻意不告警:超拍是常态(启动突发期即累计 23 次),只累计",
|
||||
bits=[("bit0", "—", "none"), ("bit1", "—", "none"), ("bit2", "—", "none"),
|
||||
("bit3", "—", "none"), ("bit4", "—", "none"), ("bit5", "—", "none"),
|
||||
("bit6", "TPAFE_GAP", "mask"), ("bit7", "STM32_GAP", "mask")]),
|
||||
("bit6", "TPAFE_GAP", "mask"), ("bit7", "STM32_GAP", "mask"),
|
||||
("bit8", "—", "none")]),
|
||||
dict(label="s_health_logged", sub="编排层记忆位图(每类一次留痕)",
|
||||
note=" |= (serious | rise):用同一位号把 SYSLOG 压成每类每次开机一条",
|
||||
bits=[("bit0", "记过", "mask"), ("bit1", "记过", "mask"),
|
||||
("bit2", "记过", "mask"), ("bit3", "记过", "mask"),
|
||||
("bit4", "记过", "mask"), ("bit5", "记过", "mask"),
|
||||
("bit6", "不记", "none"), ("bit7", "不记", "none")]),
|
||||
("bit6", "不记", "none"), ("bit7", "不记", "none"),
|
||||
("bit8", "不记", "none")]),
|
||||
]),
|
||||
]
|
||||
|
||||
FOOT = ("bit3 / bit4 / bit5 在 events 与 sticky 中刻意用同一位号 → 消费者能把事件位直接"
|
||||
"套在锁存位图上做每类一次留痕;bit8 以上全 32 位保留未用。"
|
||||
"套在锁存位图上做每类一次留痕;bit8 = 保护侧兜底门专用(判定层不写它)。"
|
||||
"详见 docs/算法/采样有效性校验设计说明.md")
|
||||
|
||||
KIND_COLOR = dict(level=C_LEVEL, latch=C_LATCH, event=C_EVENT, mask=C_MASK, none=C_NONE)
|
||||
@@ -118,6 +123,8 @@ def fit(s, fs, avail, where):
|
||||
|
||||
# ----------------------------- 生成 -----------------------------
|
||||
def build():
|
||||
# 位数列数由数据推导(曾硬编码 8 列,加 bit8 后备注框把新列盖住了)
|
||||
NB = max(len(row["bits"]) for g in GROUPS for row in g["rows"])
|
||||
body = []
|
||||
addb = body.append
|
||||
|
||||
@@ -157,7 +164,7 @@ def build():
|
||||
'%s</text>' % (x + 10, cy + 19, BIT_FONT, fg, esc(b)))
|
||||
addb('<text x="%d" y="%d" font-size="%d" fill="#334155">%s</text>'
|
||||
% (x + 10, cy + 36, TAG_FONT, esc(tag)))
|
||||
nx = GRID_X + 8 * (BIT_W + BIT_GAP) + 12
|
||||
nx = GRID_X + NB * (BIT_W + BIT_GAP) + 12
|
||||
addb('<rect x="%d" y="%d" width="%d" height="%d" rx="8" fill="#f8fafc" '
|
||||
'stroke="#64748b" stroke-opacity="0.25"/>' % (nx, cy, NOTE_W, BIT_H))
|
||||
lines = wrap(r["note"], NOTE_FONT, NOTE_W - 24)
|
||||
|
||||
Reference in New Issue
Block a user