docs(algo): 新增 adc_health 单文件深设计与三张配图

- 新建 docs/算法/采样有效性校验设计说明.md(15 章):判据推导
  (100 ms 门限的三条独立依据)、电平/锁存/事件三种位语义与
  位号对齐的收益代价、闭锁与 IWDG 兜底责任矩阵、观测盲区、
  主机侧验证分工(11 组 TC / 31 断言映射)、现场判读手册、
  自测问题与改前必读清单
- 配图走 draw-diagram 生成器路线(脚本 + 产物一并提交):
  tools/arch_diagram/gen_adc_health_flow_svg.py 等三个脚本 →
  docs/images/ 下三张 SVG;文内另有 2 张 Mermaid(判定主干
  flowchart、静默位生命周期 stateDiagram-v2,沿用仓内既有方言)
- 登记与指针:docs/README.md §5.2 加一行 + 变更记录;
  docs/算法/采集与算法层设计说明.md §4 与 §13 加深读指针;
  本文只写「为什么」,接口表仍由该文档属主,不重复
- 读码确认并如实登记三项(本提交不改代码,待裁):
  1) adc_task_init() 全库无调用点,adc_health_init() 因此不在
     产品路径,判定正确只依赖 .bss 清零 + 首拍建基线
  2) tgap 计帧点数(d-1 加权),adc1_gap 计次数——两侧单位
     不对称,心跳里不可直接对比
  3) TIM3 停摆时判定层随消费者一起停,最坏约 800 ms + 2498 ms
     窗口内 protectTask 仍以旧相量判据(细节见 §10 / §14)
- 门禁自查:pre-commit 目标集全绿(doc-links / id-check /
  空白 / EOF / 大文件);主机单测 adc_health 31/31 复跑通过;
  9 个新增或改动文件 BOM=无、CR=0、U+FFFD=0
This commit is contained in:
2026-10-21 13:42:36 +08:00
parent a26a9d6f52
commit 513becd61d
9 changed files with 1902 additions and 0 deletions
@@ -0,0 +1,218 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1580" height="740" viewBox="0 0 1580 740" font-family="Microsoft YaHei, Segoe UI, PingFang SC, sans-serif">
<text x="40" y="44" font-size="21" font-weight="700" fill="#0f172a">采样有效性校验 · 出口位图与消费者掩码(逐位对齐)</text>
<text x="40" y="70" font-size="13" fill="#64748b">同一 bit 在三张位图与四个掩码里始终落在同一列:位号对齐 = 消费者可以位图代打表</text>
<rect x="0" y="0" width="1580" height="740" fill="#ffffff"/>
<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"/>
<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>
<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"/>
<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>
<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"/>
<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>
<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"/>
<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>
<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"/>
<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>
<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"/>
<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>
<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"/>
<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="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"/>
<text x="480" y="118" font-size="12" fill="#475569">锁存位(不自愈)</text>
<rect x="606" y="106" width="16" height="16" rx="4" fill="#fffbeb" stroke="#d97706" stroke-width="1.6"/>
<text x="628" y="118" font-size="12" fill="#475569">边沿事件位(仅当拍)</text>
<rect x="778" y="106" width="16" height="16" rx="4" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.6"/>
<text x="800" y="118" font-size="12" fill="#475569">消费者掩码命中 / 记忆位</text>
<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>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

@@ -0,0 +1,193 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1580" height="1038" viewBox="0 0 1580 1038" font-family="Microsoft YaHei, Segoe UI, PingFang SC, sans-serif">
<rect x="0" y="0" width="1580" height="1038" fill="#ffffff"/>
<text x="40" y="44" font-size="21" font-weight="700" fill="#0f172a">采样有效性判定时间轴 · 四个工况的 elapsed 与位存续区间</text>
<text x="40" y="70" font-size="13" fill="#64748b">elapsed = (int32_t)(now_ms - 最后一次序号前进的时刻);条带 = 位为 1 的存续区间</text>
<rect x="430" y="106" width="16" height="12" rx="3" fill="#0d9488"/>
<text x="452" y="116" font-size="12" fill="#475569">电平位 flags(可自愈)</text>
<rect x="619" y="106" width="16" height="12" rx="3" fill="#e11d48"/>
<text x="641" y="116" font-size="12" fill="#475569">锁存位 sticky / 不自愈</text>
<rect x="813" y="106" width="16" height="12" rx="3" fill="#d97706"/>
<text x="835" y="116" font-size="12" fill="#475569">边沿事件 events(仅当拍)</text>
<rect x="1022" y="106" width="16" height="12" rx="3" fill="#e11d48"/>
<text x="1044" y="116" font-size="12" fill="#475569">静默门限 100 ms</text>
<text x="40" y="178" font-size="13" font-weight="700" fill="#334155">工况与计数</text>
<text x="430" y="178" font-size="13" font-weight="700" fill="#334155">静默计时 elapsed(ms)与位存续</text>
<text x="1150" y="178" font-size="13" font-weight="700" fill="#334155">关键时刻与判读</text>
<rect x="40" y="220" width="370" height="142" rx="10" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
<text x="54" y="246" font-size="13" font-weight="700" fill="#0f172a">A 对照:健康 1 kHz(d 恒为 1)</text>
<text x="54" y="270" font-size="11" fill="#475569">seq: 1000 1001 1002 ... 每拍恰好 +1</text>
<text x="54" y="287" font-size="11" fill="#475569">每拍都刷新最后前进时刻 adv_ms</text>
<text x="54" y="310" font-size="11" font-weight="700" fill="#0d9488">elapsed = now - adv_ms 恒为 0 → 永不进门限带</text>
<rect x="430" y="224" width="690" height="96" fill="#ffffff" stroke="#cbd5e1" stroke-width="1"/>
<line x1="430" y1="316.0" x2="1120" y2="316.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="320.0" font-size="10" fill="#64748b" text-anchor="end">0</text>
<line x1="430" y1="284.0" x2="1120" y2="284.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="288.0" font-size="10" fill="#64748b" text-anchor="end">50</text>
<line x1="430" y1="252.0" x2="1120" y2="252.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="256.0" font-size="10" fill="#64748b" text-anchor="end">100</text>
<line x1="430" y1="220.0" x2="1120" y2="220.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="224.0" font-size="10" fill="#64748b" text-anchor="end">150</text>
<line x1="430.0" y1="316" x2="430.0" y2="320" stroke="#cbd5e1" stroke-width="1"/>
<text x="430.0" y="332" font-size="10" fill="#64748b" text-anchor="middle">0</text>
<line x1="602.5" y1="316" x2="602.5" y2="320" stroke="#cbd5e1" stroke-width="1"/>
<text x="602.5" y="332" font-size="10" fill="#64748b" text-anchor="middle">50</text>
<line x1="775.0" y1="316" x2="775.0" y2="320" stroke="#cbd5e1" stroke-width="1"/>
<text x="775.0" y="332" font-size="10" fill="#64748b" text-anchor="middle">100</text>
<line x1="947.5" y1="316" x2="947.5" y2="320" stroke="#cbd5e1" stroke-width="1"/>
<text x="947.5" y="332" font-size="10" fill="#64748b" text-anchor="middle">150</text>
<line x1="1120.0" y1="316" x2="1120.0" y2="320" stroke="#cbd5e1" stroke-width="1"/>
<text x="1120.0" y="332" font-size="10" fill="#64748b" text-anchor="middle">200</text>
<line x1="430" y1="252.0" x2="1120" y2="252.0" stroke="#e11d48" stroke-width="2" stroke-dasharray="8 5"/>
<text x="944" y="246.0" font-size="10" fill="#e11d48">ADC_HEALTH_STALL_MS = 100</text>
<polyline points="430.0,316.0 1120.0,316.0" fill="none" stroke="#0d9488" stroke-width="2.6" stroke-linejoin="round"/>
<rect x="430" y="328" width="690" height="15" rx="4" fill="#f1f5f9" stroke-opacity="0"/>
<rect x="430" y="347" width="690" height="15" rx="4" fill="#f1f5f9" stroke-opacity="0"/>
<text x="424" y="339" font-size="10" fill="#64748b" text-anchor="end">flags</text>
<text x="424" y="358" font-size="10" fill="#64748b" text-anchor="end">sticky/events</text>
<text x="1150" y="238" font-size="11" fill="#334155">判定层对健康态**零输出**:events=0、flags=0、</text>
<text x="1150" y="255" font-size="11" fill="#334155">sticky=0。主机单测 TC-ADCHEALTH-002 用 2000 拍</text>
<text x="1150" y="272" font-size="11" fill="#334155">扫描把这个结论钉死(健康不误报)。</text>
<rect x="40" y="406" width="370" height="142" rx="10" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
<text x="54" y="432" font-size="13" font-weight="700" fill="#0f172a">B TPAFE 静默:100 ms 检出,恢复只清电平位</text>
<text x="54" y="456" font-size="11" fill="#475569">seq: 1000 1001 ... 冻结在 1050</text>
<text x="54" y="473" font-size="11" fill="#475569">STM32 车道照常前进(分车道独立判定)</text>
<text x="54" y="496" font-size="11" font-weight="700" fill="#0d9488">elapsed 每拍 +1,达到 100 ms 那拍即置位</text>
<rect x="430" y="410" width="690" height="96" fill="#ffffff" stroke="#cbd5e1" stroke-width="1"/>
<line x1="430" y1="502.0" x2="1120" y2="502.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="506.0" font-size="10" fill="#64748b" text-anchor="end">0</text>
<line x1="430" y1="470.0" x2="1120" y2="470.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="474.0" font-size="10" fill="#64748b" text-anchor="end">50</text>
<line x1="430" y1="438.0" x2="1120" y2="438.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="442.0" font-size="10" fill="#64748b" text-anchor="end">100</text>
<line x1="430" y1="406.0" x2="1120" y2="406.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="410.0" font-size="10" fill="#64748b" text-anchor="end">150</text>
<line x1="430.0" y1="502" x2="430.0" y2="506" stroke="#cbd5e1" stroke-width="1"/>
<text x="430.0" y="518" font-size="10" fill="#64748b" text-anchor="middle">0</text>
<line x1="602.5" y1="502" x2="602.5" y2="506" stroke="#cbd5e1" stroke-width="1"/>
<text x="602.5" y="518" font-size="10" fill="#64748b" text-anchor="middle">50</text>
<line x1="775.0" y1="502" x2="775.0" y2="506" stroke="#cbd5e1" stroke-width="1"/>
<text x="775.0" y="518" font-size="10" fill="#64748b" text-anchor="middle">100</text>
<line x1="947.5" y1="502" x2="947.5" y2="506" stroke="#cbd5e1" stroke-width="1"/>
<text x="947.5" y="518" font-size="10" fill="#64748b" text-anchor="middle">150</text>
<line x1="1120.0" y1="502" x2="1120.0" y2="506" stroke="#cbd5e1" stroke-width="1"/>
<text x="1120.0" y="518" font-size="10" fill="#64748b" text-anchor="middle">200</text>
<line x1="430" y1="438.0" x2="1120" y2="438.0" stroke="#e11d48" stroke-width="2" stroke-dasharray="8 5"/>
<text x="944" y="432.0" font-size="10" fill="#e11d48">ADC_HEALTH_STALL_MS = 100</text>
<polyline points="430.0,502.0 775.0,438.0 947.5,406.0" fill="none" stroke="#0d9488" stroke-width="2.6" stroke-linejoin="round"/>
<polyline points="947.5,502.0 1120.0,502.0" fill="none" stroke="#0d9488" stroke-width="2.6" stroke-linejoin="round"/>
<line x1="775.0" y1="438.0" x2="775.0" y2="506" stroke="#64748b" stroke-width="1" stroke-dasharray="3 3"/>
<circle cx="775.0" cy="438.0" r="9" fill="#0f172a"/>
<text x="775.0" y="441.6" font-size="10.5" font-weight="700" fill="#ffffff" text-anchor="middle">1</text>
<line x1="947.5" y1="406.0" x2="947.5" y2="506" stroke="#64748b" stroke-width="1" stroke-dasharray="3 3"/>
<circle cx="947.5" cy="406.0" r="9" fill="#0f172a"/>
<text x="947.5" y="409.6" font-size="10.5" font-weight="700" fill="#ffffff" text-anchor="middle">2</text>
<rect x="430" y="514" width="690" height="15" rx="4" fill="#f1f5f9" stroke-opacity="0"/>
<rect x="430" y="533" width="690" height="15" rx="4" fill="#f1f5f9" stroke-opacity="0"/>
<text x="424" y="525" font-size="10" fill="#64748b" text-anchor="end">flags</text>
<text x="424" y="544" font-size="10" fill="#64748b" text-anchor="end">sticky/events</text>
<rect x="775.0" y="514.0" width="172.5" height="15" rx="4" fill="#0d9488" fill-opacity="0.85"/>
<text x="955.5" y="525.0" font-size="10" fill="#0d9488">TPAFE_STALL 电平</text>
<rect x="775.0" y="533.0" width="345.0" height="15" rx="4" fill="#e11d48" fill-opacity="0.85"/>
<text x="651.9" y="544.0" font-size="10" fill="#e11d48">TPAFE_STALL 锁存留痕</text>
<text x="1150" y="424" font-size="11" fill="#334155">1 t=100 ms:ADC_HF_TPAFE_STALL 置位 + 进 sticky;</text>
<text x="1150" y="441" font-size="11" fill="#334155"> 闭锁路径 = protectTask 下一拍(间隔 &lt;= 20 ms)</text>
<text x="1150" y="458" font-size="11" fill="#334155"> 命中掩码 → prot_elm_init() + 本拍不 eval</text>
<text x="1150" y="475" font-size="11" fill="#334155">2 t=150 ms:序号重新前进 → 电平位清、sticky 仍留痕</text>
<rect x="40" y="592" width="370" height="142" rx="10" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
<text x="54" y="618" font-size="13" font-weight="700" fill="#0f172a">C 消费者超拍:d=3 只算丢帧,永不判静默</text>
<text x="54" y="642" font-size="11" fill="#475569">seq: 1000 1003 1006 ... 每拍 +3</text>
<text x="54" y="659" font-size="11" fill="#475569">生产者活着,消费者没跟上</text>
<text x="54" y="682" font-size="11" font-weight="700" fill="#0d9488">d &gt;= 1 → 刷新 adv_ms,elapsed 恒 0;tgap += d-1</text>
<rect x="430" y="596" width="690" height="96" fill="#ffffff" stroke="#cbd5e1" stroke-width="1"/>
<line x1="430" y1="688.0" x2="1120" y2="688.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="692.0" font-size="10" fill="#64748b" text-anchor="end">0</text>
<line x1="430" y1="656.0" x2="1120" y2="656.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="660.0" font-size="10" fill="#64748b" text-anchor="end">50</text>
<line x1="430" y1="624.0" x2="1120" y2="624.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="628.0" font-size="10" fill="#64748b" text-anchor="end">100</text>
<line x1="430" y1="592.0" x2="1120" y2="592.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="596.0" font-size="10" fill="#64748b" text-anchor="end">150</text>
<line x1="430.0" y1="688" x2="430.0" y2="692" stroke="#cbd5e1" stroke-width="1"/>
<text x="430.0" y="704" font-size="10" fill="#64748b" text-anchor="middle">0</text>
<line x1="602.5" y1="688" x2="602.5" y2="692" stroke="#cbd5e1" stroke-width="1"/>
<text x="602.5" y="704" font-size="10" fill="#64748b" text-anchor="middle">50</text>
<line x1="775.0" y1="688" x2="775.0" y2="692" stroke="#cbd5e1" stroke-width="1"/>
<text x="775.0" y="704" font-size="10" fill="#64748b" text-anchor="middle">100</text>
<line x1="947.5" y1="688" x2="947.5" y2="692" stroke="#cbd5e1" stroke-width="1"/>
<text x="947.5" y="704" font-size="10" fill="#64748b" text-anchor="middle">150</text>
<line x1="1120.0" y1="688" x2="1120.0" y2="692" stroke="#cbd5e1" stroke-width="1"/>
<text x="1120.0" y="704" font-size="10" fill="#64748b" text-anchor="middle">200</text>
<line x1="430" y1="624.0" x2="1120" y2="624.0" stroke="#e11d48" stroke-width="2" stroke-dasharray="8 5"/>
<text x="944" y="618.0" font-size="10" fill="#e11d48">ADC_HEALTH_STALL_MS = 100</text>
<polyline points="430.0,688.0 1120.0,688.0" fill="none" stroke="#0d9488" stroke-width="2.6" stroke-linejoin="round"/>
<polyline points="430.0,688.0 499.0,688.0 499.0,660.2 637.0,660.2 637.0,632.3 775.0,632.3 775.0,604.5 1120.0,604.5" fill="none" stroke="#d97706" stroke-width="2.4" stroke-linejoin="round"/>
<text x="438" y="612" font-size="10" fill="#d97706">tpafe_gaps 累计点数(右轴 0~8)</text>
<line x1="499.0" y1="682.2" x2="499.0" y2="692" stroke="#64748b" stroke-width="1" stroke-dasharray="3 3"/>
<circle cx="499.0" cy="682.2" r="9" fill="#0f172a"/>
<text x="499.0" y="685.8" font-size="10.5" font-weight="700" fill="#ffffff" text-anchor="middle">1</text>
<line x1="637.0" y1="682.2" x2="637.0" y2="692" stroke="#64748b" stroke-width="1" stroke-dasharray="3 3"/>
<circle cx="637.0" cy="682.2" r="9" fill="#0f172a"/>
<text x="637.0" y="685.8" font-size="10.5" font-weight="700" fill="#ffffff" text-anchor="middle">2</text>
<rect x="430" y="700" width="690" height="15" rx="4" fill="#f1f5f9" stroke-opacity="0"/>
<rect x="430" y="719" width="690" height="15" rx="4" fill="#f1f5f9" stroke-opacity="0"/>
<text x="424" y="711" font-size="10" fill="#64748b" text-anchor="end">flags</text>
<text x="424" y="730" font-size="10" fill="#64748b" text-anchor="end">sticky/events</text>
<rect x="499.0" y="719.0" width="6.9" height="15" rx="4" fill="#d97706" fill-opacity="0.85"/>
<text x="513.9" y="730.0" font-size="10" fill="#d97706">ADC_HE_TPAFE_GAP 仅当拍</text>
<rect x="637.0" y="719.0" width="6.9" height="15" rx="4" fill="#d97706" fill-opacity="0.85"/>
<text x="651.9" y="730.0" font-size="10" fill="#d97706">同上</text>
<rect x="775.0" y="719.0" width="6.9" height="15" rx="4" fill="#d97706" fill-opacity="0.85"/>
<text x="789.9" y="730.0" font-size="10" fill="#d97706">同上</text>
<text x="1150" y="610" font-size="11" fill="#334155">1 t=20 ms:d=3 → tgap += 2 + 当拍事件,下一拍事件消失</text>
<text x="1150" y="627" font-size="11" fill="#334155"> (边沿语义,不是电平)</text>
<text x="1150" y="644" font-size="11" fill="#334155">2 丢帧不入锁存、不告警、不闭锁;两者口径也不同:tgap</text>
<text x="1150" y="661" font-size="11" fill="#334155"> 计帧点数(d-1 加权),adc1_gap 计次数(每次 +1)。</text>
<text x="1150" y="678" font-size="11" fill="#334155"> 台架日志:启动突发期累计 23 次,稳态每 10 s +1~2 次</text>
<rect x="40" y="778" width="370" height="142" rx="10" fill="#f8fafc" stroke="#64748b" stroke-opacity="0.25"/>
<text x="54" y="804" font-size="13" font-weight="700" fill="#0f172a">D 序号倒退:锁存不可自愈,代价是永久闭锁</text>
<text x="54" y="828" font-size="11" fill="#475569">seq: 1050 1051 ... 跳到 995</text>
<text x="54" y="845" font-size="11" fill="#475569">d = 995 - 1051 &lt; 0(有符号差)</text>
<text x="54" y="868" font-size="11" font-weight="700" fill="#0d9488">置位后重新对齐基线,不重复触发;位永不自动清</text>
<rect x="430" y="782" width="690" height="96" fill="#ffffff" stroke="#cbd5e1" stroke-width="1"/>
<line x1="430" y1="874.0" x2="1120" y2="874.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="878.0" font-size="10" fill="#64748b" text-anchor="end">0</text>
<line x1="430" y1="842.0" x2="1120" y2="842.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="846.0" font-size="10" fill="#64748b" text-anchor="end">50</text>
<line x1="430" y1="810.0" x2="1120" y2="810.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="814.0" font-size="10" fill="#64748b" text-anchor="end">100</text>
<line x1="430" y1="778.0" x2="1120" y2="778.0" stroke="#cbd5e1" stroke-width="0.8" stroke-dasharray="3 4"/>
<text x="424" y="782.0" font-size="10" fill="#64748b" text-anchor="end">150</text>
<line x1="430.0" y1="874" x2="430.0" y2="878" stroke="#cbd5e1" stroke-width="1"/>
<text x="430.0" y="890" font-size="10" fill="#64748b" text-anchor="middle">0</text>
<line x1="602.5" y1="874" x2="602.5" y2="878" stroke="#cbd5e1" stroke-width="1"/>
<text x="602.5" y="890" font-size="10" fill="#64748b" text-anchor="middle">50</text>
<line x1="775.0" y1="874" x2="775.0" y2="878" stroke="#cbd5e1" stroke-width="1"/>
<text x="775.0" y="890" font-size="10" fill="#64748b" text-anchor="middle">100</text>
<line x1="947.5" y1="874" x2="947.5" y2="878" stroke="#cbd5e1" stroke-width="1"/>
<text x="947.5" y="890" font-size="10" fill="#64748b" text-anchor="middle">150</text>
<line x1="1120.0" y1="874" x2="1120.0" y2="878" stroke="#cbd5e1" stroke-width="1"/>
<text x="1120.0" y="890" font-size="10" fill="#64748b" text-anchor="middle">200</text>
<line x1="430" y1="810.0" x2="1120" y2="810.0" stroke="#e11d48" stroke-width="2" stroke-dasharray="8 5"/>
<text x="944" y="804.0" font-size="10" fill="#e11d48">ADC_HEALTH_STALL_MS = 100</text>
<polyline points="430.0,874.0 1120.0,874.0" fill="none" stroke="#0d9488" stroke-width="2.6" stroke-linejoin="round"/>
<line x1="637.0" y1="868.2" x2="637.0" y2="878" stroke="#64748b" stroke-width="1" stroke-dasharray="3 3"/>
<circle cx="637.0" cy="868.2" r="9" fill="#0f172a"/>
<text x="637.0" y="871.8" font-size="10.5" font-weight="700" fill="#ffffff" text-anchor="middle">1</text>
<line x1="1099.3" y1="868.2" x2="1099.3" y2="878" stroke="#64748b" stroke-width="1" stroke-dasharray="3 3"/>
<circle cx="1099.3" cy="868.2" r="9" fill="#0f172a"/>
<text x="1099.3" y="871.8" font-size="10.5" font-weight="700" fill="#ffffff" text-anchor="middle">2</text>
<rect x="430" y="886" width="690" height="15" rx="4" fill="#f1f5f9" stroke-opacity="0"/>
<rect x="430" y="905" width="690" height="15" rx="4" fill="#f1f5f9" stroke-opacity="0"/>
<text x="424" y="897" font-size="10" fill="#64748b" text-anchor="end">flags</text>
<text x="424" y="916" font-size="10" fill="#64748b" text-anchor="end">sticky/events</text>
<rect x="637.0" y="886.0" width="483.0" height="15" rx="4" fill="#e11d48" fill-opacity="0.85"/>
<text x="507.8" y="897.0" font-size="10" fill="#e11d48">SEQ_BACKWARD 不自动清</text>
<rect x="637.0" y="905.0" width="483.0" height="15" rx="4" fill="#e11d48" fill-opacity="0.85"/>
<text x="528.8" y="916.0" font-size="10" fill="#e11d48">SEQ_BACKWARD 锁存</text>
<text x="1150" y="796" font-size="11" fill="#334155">1 t=60 ms:倒退被检出 → 重新对齐避免每拍重复置位</text>
<text x="1150" y="813" font-size="11" fill="#334155">2 电平位与锁存位同时置位 → 保护永久退出,直到</text>
<text x="1150" y="830" font-size="11" fill="#334155"> 复位或显式 adc_health_init();这是刻意取舍:</text>
<text x="1150" y="847" font-size="11" fill="#334155"> 计数被改写时相量不可信,宁可拒动不误动</text>
<rect x="40" y="982" width="1500" height="42" rx="10" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.45"/>
<text x="56" y="1008" font-size="11" fill="#7c2d12">横轴 = 距最后一次序号前进的时间(ms,tick 回绕由有符号差值吸收);红线 = ADC_HEALTH_STALL_MS = 100 ms。详见 docs/算法/采样有效性校验设计说明.md</text>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

@@ -0,0 +1,120 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1580" height="818" viewBox="0 0 1580 818" font-family="Microsoft YaHei, Segoe UI, PingFang SC, sans-serif">
<rect x="0" y="0" width="1580" height="818" fill="#ffffff"/>
<text x="40" y="44" font-size="21" font-weight="700" fill="#0f172a">采样有效性校验(adc_health)· 数据流与出口</text>
<text x="40" y="70" font-size="13" fill="#64748b">三条量车道平行流过五个阶段;判定层每拍一次、常数次整数运算,输入只是计数快照</text>
<rect x="136" y="150" width="268" height="34" rx="8" fill="#f1f5f9" stroke="#475569" stroke-opacity="0.35"/>
<text x="148" y="172" font-size="13" font-weight="700" fill="#334155">1. 观测计数(ISR / 驱动侧)</text>
<rect x="424" y="150" width="236" height="34" rx="8" fill="#f1f5f9" stroke="#475569" stroke-opacity="0.35"/>
<text x="436" y="172" font-size="13" font-weight="700" fill="#334155">2. 本拍计数快照</text>
<rect x="680" y="150" width="276" height="34" rx="8" fill="#f1f5f9" stroke="#475569" stroke-opacity="0.35"/>
<text x="692" y="172" font-size="13" font-weight="700" fill="#334155">3. 判定(adc_health.c 纯逻辑)</text>
<rect x="976" y="150" width="264" height="34" rx="8" fill="#f1f5f9" stroke="#475569" stroke-opacity="0.35"/>
<text x="988" y="172" font-size="13" font-weight="700" fill="#334155">4. 出口位图(32 位)</text>
<rect x="1260" y="150" width="250" height="34" rx="8" fill="#f1f5f9" stroke="#475569" stroke-opacity="0.35"/>
<text x="1272" y="172" font-size="13" font-weight="700" fill="#334155">5. 消费者与处置</text>
<rect x="40" y="214" width="82" height="148" rx="10" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.5"/>
<text x="81" y="293" font-size="12" font-weight="700" fill="#0d9488" text-anchor="middle">TPAFE</text>
<rect x="136" y="214" width="268" height="148" rx="10" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.45"/>
<text x="149" y="244" font-size="12" font-weight="700" fill="#0d9488">tpafe5160.c 的 BUSY EXTI</text>
<text x="149" y="270" font-size="11" fill="#334155">s_frame_seq++:每读完一帧 +1</text>
<text x="149" y="292" font-size="11" fill="#334155">s_frstdata_err++:无跳变帧累计(E-44)</text>
<text x="149" y="314" font-size="11" fill="#334155">ISR 内只加计数,不打日志</text>
<line x1="404" y1="288.0" x2="415" y2="288.0" stroke="#0d9488" stroke-width="2.2"/>
<path d="M 424.0 288.0 L 413.0 282.5 L 413.0 293.5 z" fill="#0d9488"/>
<rect x="424" y="214" width="236" height="148" rx="10" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.45"/>
<text x="437" y="244" font-size="12" font-weight="700" fill="#0d9488">adcTask 每拍 poll 之后取值</text>
<text x="437" y="270" font-size="11" fill="#334155">tpafe_seq</text>
<text x="437" y="292" font-size="11" fill="#334155">tpafe_frst_err(uint16 放宽)</text>
<text x="437" y="314" font-size="11" fill="#334155">⚠ 必须取本拍 poll 之后的值</text>
<line x1="660" y1="288.0" x2="671" y2="288.0" stroke="#0d9488" stroke-width="2.2"/>
<path d="M 680.0 288.0 L 669.0 282.5 L 669.0 293.5 z" fill="#0d9488"/>
<rect x="680" y="214" width="276" height="148" rx="10" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.45"/>
<text x="693" y="244" font-size="12" font-weight="700" fill="#0d9488">序号差值 d = seq - 上次</text>
<text x="693" y="270" font-size="11" fill="#334155">d &lt; 0 → 置倒退位并重新对齐</text>
<text x="693" y="292" font-size="11" fill="#334155">d &gt; 1 → tgap += d-1 + 当拍事件</text>
<text x="693" y="314" font-size="11" fill="#334155">d &gt;= 1 → 刷新「最后前进时刻」</text>
<line x1="956" y1="288.0" x2="967" y2="288.0" stroke="#0d9488" stroke-width="2.2"/>
<path d="M 976.0 288.0 L 965.0 282.5 L 965.0 293.5 z" fill="#0d9488"/>
<rect x="976" y="214" width="264" height="148" rx="10" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.45"/>
<text x="989" y="244" font-size="12" font-weight="700" fill="#0d9488">本车道出口</text>
<text x="989" y="270" font-size="11" fill="#334155">bit0 ADC_HF_TPAFE_STALL(自愈)</text>
<text x="989" y="292" font-size="11" fill="#334155">bit2 ADC_HF_SEQ_BACKWARD(锁存)</text>
<text x="989" y="314" font-size="11" fill="#334155">bit6/bit3 ADC_HE_TPAFE_GAP / FRSTDATA</text>
<line x1="1240" y1="288.0" x2="1251" y2="288.0" stroke="#0d9488" stroke-width="2.2"/>
<path d="M 1260.0 288.0 L 1249.0 282.5 L 1249.0 293.5 z" fill="#0d9488"/>
<rect x="1260" y="214" width="250" height="148" rx="10" fill="#f0fdfa" stroke="#0d9488" stroke-opacity="0.45"/>
<text x="1273" y="244" font-size="12" font-weight="700" fill="#0d9488">闭锁 + 留痕 + 计数</text>
<text x="1273" y="270" font-size="11" fill="#334155">protectTask 每 20 ms 读 bit0/bit2</text>
<text x="1273" y="292" font-size="11" fill="#334155">gap / FRSTDATA 事件 → 编排层日志</text>
<text x="1273" y="314" font-size="11" fill="#334155">tgap → 10 s 心跳字段</text>
<rect x="40" y="396" width="82" height="148" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-opacity="0.5"/>
<text x="81" y="475" font-size="12" font-weight="700" fill="#2563eb" text-anchor="middle">STM32</text>
<rect x="136" y="396" width="268" height="148" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-opacity="0.45"/>
<text x="149" y="426" font-size="12" font-weight="700" fill="#2563eb">adc_input.c(DMA2 Stream4)</text>
<text x="149" y="452" font-size="11" fill="#334155">s_dma_seq++:半区/整区完成各一次</text>
<text x="149" y="474" font-size="11" fill="#334155">s_stm32_gaps++:完成计数一次前进 &gt;1</text>
<text x="149" y="496" font-size="11" fill="#334155">s_stm32_errs++:连续 &gt;=2 拍无新帧</text>
<text x="149" y="518" font-size="11" fill="#334155">s_stm32_hw_errs++:HAL 错误回调</text>
<line x1="404" y1="470.0" x2="415" y2="470.0" stroke="#2563eb" stroke-width="2.2"/>
<path d="M 424.0 470.0 L 413.0 464.5 L 413.0 475.5 z" fill="#2563eb"/>
<rect x="424" y="396" width="236" height="148" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-opacity="0.45"/>
<text x="437" y="426" font-size="12" font-weight="700" fill="#2563eb">同一拍的四个 STM32 计数</text>
<text x="437" y="452" font-size="11" fill="#334155">stm32_seq / stm32_errs</text>
<text x="437" y="474" font-size="11" fill="#334155">stm32_gaps / stm32_hw_errs</text>
<text x="437" y="496" font-size="11" fill="#334155">gap 细账不重复取(L1 已算)</text>
<line x1="660" y1="470.0" x2="671" y2="470.0" stroke="#2563eb" stroke-width="2.2"/>
<path d="M 680.0 470.0 L 669.0 464.5 L 669.0 475.5 z" fill="#2563eb"/>
<rect x="680" y="396" width="276" height="148" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-opacity="0.45"/>
<text x="693" y="426" font-size="12" font-weight="700" fill="#2563eb">序号差值 d + 三处计数增量</text>
<text x="693" y="452" font-size="11" fill="#334155">d &lt; 0 → 同一个 SEQ_BACKWARD 位</text>
<text x="693" y="474" font-size="11" fill="#334155">d &gt;= 1 → 刷新最后前进时刻</text>
<text x="693" y="496" font-size="11" fill="#334155">增量 != 0 → 事件 + 锁存</text>
<line x1="956" y1="470.0" x2="967" y2="470.0" stroke="#2563eb" stroke-width="2.2"/>
<path d="M 976.0 470.0 L 965.0 464.5 L 965.0 475.5 z" fill="#2563eb"/>
<rect x="976" y="396" width="264" height="148" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-opacity="0.45"/>
<text x="989" y="426" font-size="12" font-weight="700" fill="#2563eb">本车道出口</text>
<text x="989" y="452" font-size="11" fill="#334155">bit1 ADC_HF_STM32_STALL(自愈)</text>
<text x="989" y="474" font-size="11" fill="#334155">bit2 共用(两车道同一位)</text>
<text x="989" y="496" font-size="11" fill="#334155">bit7/bit4/bit5 GAP / ERR / HW_ERR</text>
<line x1="1240" y1="470.0" x2="1251" y2="470.0" stroke="#2563eb" stroke-width="2.2"/>
<path d="M 1260.0 470.0 L 1249.0 464.5 L 1249.0 475.5 z" fill="#2563eb"/>
<rect x="1260" y="396" width="250" height="148" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-opacity="0.45"/>
<text x="1273" y="426" font-size="12" font-weight="700" fill="#2563eb">闭锁 + 严重事件</text>
<text x="1273" y="452" font-size="11" fill="#334155">bit1/bit2 → 同左闭锁路径</text>
<text x="1273" y="474" font-size="11" fill="#334155">STM32_ERR / HW_ERR:恒 0 增量</text>
<text x="1273" y="496" font-size="11" fill="#334155">出现即 DBG_ERROR + 自检留痕</text>
<rect x="40" y="578" width="82" height="148" rx="10" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.5"/>
<text x="81" y="657" font-size="12" font-weight="700" fill="#7c3aed" text-anchor="middle">时基</text>
<rect x="136" y="578" width="268" height="148" rx="10" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.45"/>
<text x="149" y="608" font-size="12" font-weight="700" fill="#7c3aed">osKernelGetTickCount()</text>
<text x="149" y="634" font-size="11" fill="#334155">HAL 时基 TIM7,tick = 1 ms</text>
<text x="149" y="656" font-size="11" fill="#334155">2^32 ms 后自然回绕</text>
<line x1="404" y1="652.0" x2="415" y2="652.0" stroke="#7c3aed" stroke-width="2.2"/>
<path d="M 424.0 652.0 L 413.0 646.5 L 413.0 657.5 z" fill="#7c3aed"/>
<rect x="424" y="578" width="236" height="148" rx="10" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.45"/>
<text x="437" y="608" font-size="12" font-weight="700" fill="#7c3aed">now_ms:本拍唯一一份</text>
<text x="437" y="634" font-size="11" fill="#334155">健康判定与心跳上报共用</text>
<text x="437" y="656" font-size="11" fill="#334155">不在判定层内再取一次</text>
<line x1="660" y1="652.0" x2="671" y2="652.0" stroke="#7c3aed" stroke-width="2.2"/>
<path d="M 680.0 652.0 L 669.0 646.5 L 669.0 657.5 z" fill="#7c3aed"/>
<rect x="680" y="578" width="276" height="148" rx="10" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.45"/>
<text x="693" y="608" font-size="12" font-weight="700" fill="#7c3aed">差值法 (int32_t)(now - adv)</text>
<text x="693" y="634" font-size="11" fill="#334155">回绕安全(取有符号差)</text>
<text x="693" y="656" font-size="11" fill="#334155">&gt;= ADC_HEALTH_STALL_MS(100)</text>
<text x="693" y="678" font-size="11" fill="#334155">可判定窗 ±2^31 ≈ ±24.85 天</text>
<line x1="956" y1="652.0" x2="967" y2="652.0" stroke="#7c3aed" stroke-width="2.2"/>
<path d="M 976.0 652.0 L 965.0 646.5 L 965.0 657.5 z" fill="#7c3aed"/>
<rect x="976" y="578" width="264" height="148" rx="10" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.45"/>
<text x="989" y="608" font-size="12" font-weight="700" fill="#7c3aed">tpafe_stall_ms</text>
<text x="989" y="634" font-size="11" fill="#334155">静默期内给出停滞时长</text>
<text x="989" y="656" font-size="11" fill="#334155">正常态恒为 0</text>
<text x="989" y="678" font-size="11" fill="#334155">STM32 侧未上报(观测盲区)</text>
<line x1="1240" y1="652.0" x2="1251" y2="652.0" stroke="#7c3aed" stroke-width="2.2"/>
<path d="M 1260.0 652.0 L 1249.0 646.5 L 1249.0 657.5 z" fill="#7c3aed"/>
<rect x="1260" y="578" width="250" height="148" rx="10" fill="#f5f3ff" stroke="#7c3aed" stroke-opacity="0.45"/>
<text x="1273" y="608" font-size="12" font-weight="700" fill="#7c3aed">上升沿日志可读性</text>
<text x="1273" y="634" font-size="11" fill="#334155">health: flags=… stall_ms=…</text>
<text x="1273" y="656" font-size="11" fill="#334155">回答到底停了多少毫秒</text>
<rect x="40" y="756" width="1500" height="46" rx="10" fill="#fffbeb" stroke="#d97706" stroke-opacity="0.45"/>
<text x="56" y="784" font-size="12" fill="#7c2d12">判定层零平台依赖(只 include &lt;stdint.h&gt;、不碰寄存器 / 不取数 / 不打日志)→ 主机侧以 #include 原样纳入、免桩全覆盖单测。详见 docs/算法/采样有效性校验设计说明.md</text>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB