Files
STM32F4-Base/tools/arch_diagram/README.md
T
wandering1 f48208f1c5 docs(配图): 生成器与产物清单并成一张唯一真值表,挂载列改由实测反推
两张清单各自登记同一批生成器,2026-10-30 实测各漏各的:
`tools/arch_diagram/README.md`「脚本一览」21 行缺 5 个(adc_health 三张、
net_instability、net_pending),`docs/架构设计/图形绘制流程.md` 的三列表 18 行
缺 9 个(多出的还在 `docs/架构设计/图形绘制流程.md` §2.1 另立一张表登记例外面)。
同一条事实两处登记必然漂,现并成一张:

- 唯一真值表 = `tools/arch_diagram/README.md`「产物清单」:按图逐行,32 张入库
  `docs/images/*.svg` 全量(26 个本目录生成器 + refgraph 2 张 + 无生成器的手工
  级联框 2 张),列 = 图 / 生成器 / 这张图答什么 / 顶部数据区(改这里 → 重跑)/
  挂在(`文档:行号`)。
- `docs/架构设计/图形绘制流程.md` §二 的逐脚本表换成指针(只留选型判据与流程),
  §2.1 保留「钩子扫不到的图」的维护口径、去掉与主表重复的表。
- 级联框两张的绘制日期按 `git log --follow` 改对:原写「2026-10-26 手画」与 git 史
  不符,实测 2026-09-08 `891c9ef0` 入库、2026-09-11 `2429955d` 随配图规范收拢进
  `docs/images/`,此后未再改动。
- `docs/门禁说明/generated-fresh.md` §8 旧口径「加生成器 = `GENS` 加一项」对
  `docs-svg` 不实:该条目声明 `dir` + `pattern = gen_*.py`,实跑 `glob.glob` 现扫
  (`scripts/check_generated_fresh.py`:146-150 与 :452)→ 新增生成器自动进扫描面,
  要同批改的是产物清单不是门禁。已拆成「加新类别」与「`docs-svg` 不必登记」两条。
- 「挂在」列由扫描 `![]()` 反推,并跳过 ``` 围栏与行内反引号里的示例写法——
  `docs/文档规范.md`:83、`draw-diagram` SKILL.md:155、本文档 §3.1 第 5 步
  那三处是教学示例、不是真挂载,先前手写表时误计进去过。
- 三张零内嵌图(`内存布局_RAM.svg`、`引用关系图.svg`、`引用关系图_模块.svg`)
  在表里明写「零内嵌」并给出被文字提到的位置。

`draw-diagram` skill 的落库义务同批改指:§二第 6 步与验证清单都指向「产物清单」,
并写明「全仓只此一张逐脚本清单」,避免下一个人再另起第二张。

自查:`check_doc_links.py --sections-strict` 三篇 rc=0;`check_generated_fresh.py`
PASS(26 生成器 / 22 一致 / 4 存量基线);`check_skill_size.py` 17 个 SKILL.md ok;
`check_mermaid.py --all` 31 文件 62 围栏新发 0;`check_bom_drift.py --all` 99 文件
无漂移;产物清单核对器(一次性,不入库)重写挂载列后复跑归零、再跑幂等。
纯文档与 skill 文案,未改任何生成器与代码,未 commit。
2026-10-30 16:54:53 +08:00

89 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# tools/arch_diagram/ — 架构图 SVG 生成器
> 用 Python 脚本**精确生成**架构类 SVG 图(分层、内存布局、协议帧、屏障等),
> 产物放 `docs/images/`。用于"必须精确布局"的图;拓扑图(流程/时序/状态机)改用 Mermaid。
>
> 下面这张表是**配图产物的唯一真值清单**——入库的 32 张 `docs/images/*.svg` 逐张列出:谁生成它、
> 它答什么问题、改哪一段数据能重跑、被哪篇文档内嵌。选型判据与绘制流程 → `docs/架构设计/图形绘制流程.md`,
> 画图时的操作入口 → **`draw-diagram` skill**。
## 产物清单(按主题分组 · 32 张全量)
「挂在」列只认 Markdown 图片链接 `![](...)`,格式 `文档:行号`;**行号会漂,现查勿背**:
`grep -rn "图名.svg" docs/ --include=*.md`。零内嵌的图在单元格明写「零内嵌」,它要么只被正文文字提到、
要么就是**挂了但没人挂图**——改图的人顺手把这条也核对一次。
| 图(`docs/images/`) | 生成器 | 这张图答什么 | 顶部数据区(改这里 → 重跑) | 挂在 |
|---|---|---|---|---|
| **架构与启动** | | | | |
| `项目架构总览.svg` | `gen_arch_svg.py` | 六层分层结构与跨层依赖——「谁在哪一层」(不含数据流边、不含片外硬件) | `LAYERS` / `ROWS` / `FOOT` | `docs/架构设计/软件架构与运行时规格.md`:14、`docs/架构设计/项目架构总览.md`:11 |
| `架构总览_端到端链路.svg` | `gen_arch_endtoend_svg.py` | 端到端链路鸟瞰——一个电气量从引脚走到 104 报文 / 显存 / 记录文件**穿过谁、与谁在什么时候换锁**;42 框 37 边 5 条纵带,线型分数据 / 命令 / 屏障心跳 | `NODES`(id / 列 / 行 / 标题 / 副题)+ `EDGES`(出入框方位与 `f` / `g` / `my` / `gx` 旋钮)+ `BANDS`;三条独占通道 `CHAN_B` / `CHAN_78` / `CHAN_SLOTS` 与走廊 `GUT_C4C5` 在几何区 | `docs/架构设计/项目架构总览.md`:53 |
| `就绪屏障.svg` | `gen_barrier_svg.py` | Event Flags 屏障模型:位 → 生产者 → 消费者三栏对齐,哪些位真在用、哪些是预留 | `BITS` / `PRODUCERS` / `CONSUMERS` / `FOOT` | `docs/架构设计/软件架构与运行时规格.md`:63、`docs/架构设计/项目启动顺序管理.md`:48、`docs/架构设计/项目架构总览.md`:85 |
| `配置文件分层架构.svg` | `gen_cfg_arch_svg.py` | 配置引擎分层与持久化:谁解析 `[section]`、落盘走哪条链 | `ROWS` 分层清单 + 标题 / 脚注文案 | `docs/产品需求/产品需求设计文档.md`:331、`docs/子系统设计/配置文件设计说明.md`:144 |
| **采集与算法** | | | | |
| `ADC前端电路.svg` | `gen_adc_frontend_svg.py` | 端子 → 串阻 → 转换节点 → 转换器引脚;含差分负端与 STM32 侧对照 | `SUB1` / `NOTE_*` 等文案常量 + 面板坐标(电路拓扑固定,网表变了才重画) | `docs/测试说明/专项验证/ADC前端注入验证流程.md`:31、`docs/硬件平台/ADC通道映射说明.md`:161 |
| `ADC码值刻度.svg` | `gen_adc_code_scale_svg.py` | 「码」的直观定义:两片转换器的刻度尺对照(16 位双极性 vs 12 位单极性) | `PANELS`(码范围 / LSB / 实测码标记位置)+ `FOOT`(换芯片才重画) | `docs/测试说明/专项验证/ADC前端注入验证流程.md`:104 |
| `ADC直流标定与交流验证.svg` | `gen_data_trust_dc_ac_svg.py` | 上排直流注入链、下排信号发生器正弦验证,中间列只有正弦能证的六件事 | `BOXES_A` / `BOXES_B` 两条泳道 + `CHIPS` 六件事 + `NOTES` 红线与"证不到"清单 | `docs/任务规划/数据可信.md`:294 |
| `数据可信台阶.svg` | `gen_data_trust_ladder_svg.py` | 采集数据可信度的五级台阶:现在踩在哪一级、下一级挡什么 | `STEPS` 五级台阶(状态 / 问题 / 依据)+ `BAND_LABEL_1` / `GATE_LABEL` / `FOOTNOTE`(台阶状态变了才重画) | `docs/任务规划/数据可信.md`:21 |
| `采样有效性校验数据流.svg` | `gen_adc_health_flow_svg.py` | 观测计数 → 快照 → 判定 → 位图 → 消费者:三条量车道(TPAFE / STM32 / 时基)平行流过五个阶段 | `STAGES` 五阶段 + `LANES` 三条车道 + `COLS` + `FOOT` | `docs/算法/采样有效性校验设计说明.md`:81 |
| `采样有效性位图与掩码.svg` | `gen_adc_health_bitmap_svg.py` | 出口位图与消费者掩码对照——同一 bit 在三张位图与四个掩码里落同一列(Mermaid 控不住列位,故必须等宽网格) | `GROUPS` 位图组 + `C_LEVEL` / `C_LATCH` / `C_EVENT` / `C_MASK` 四类位 + `WARN` / `FOOT` | `docs/算法/采样有效性校验设计说明.md`:303 |
| `采样有效性判定时间轴.svg` | `gen_adc_health_timeline_svg.py` | 四个工况的时序与门限(100 ms 门限线、静默计时线、电平位与锁存位的存续区间——按时间比例画,Mermaid 只画拓扑不保比例) | `PANELS` 四工况 + `T_MAX` / `V_MAX` 比例轴 + `WARN` / `FOOT` | `docs/算法/采样有效性校验设计说明.md`:212 |
| `采样环缓冲_为什么需要.svg` | `gen_sample_ring_why_svg.py` | 上游 1 kHz 覆盖写只交"最新一帧" vs 下游相量要一整周波(20 点):缺口 19 点与三个消费者 | `SUB1` + `CARDS` 对照卡 + `FOOTNOTE` | `docs/算法/采集与算法层设计说明.md`:162 |
| `采样环缓冲_环形布局.svg` | `gen_sample_ring_layout_svg.py` | 40 格环里哪 20 格是本窗、写指针指"下一格"而不是"最后一格"、整窗随每次写入右移一格与三条设计不变量 | `START` / `SUB3` + `CARDS` 三件事 + `FOOTNOTE` | `docs/算法/采集与算法层设计说明.md`:192 |
| `采样环缓冲_窗首下标.svg` | `gen_sample_ring_start_svg.py` | 窗首 `start = head − n` 的圆周走法,与"直接减 / 16 位回绕 / 先加 `DEPTH`"三种写法对照 | `START` / `SUB1` + `ROWS` 三种写法 + `FOOTNOTE` | `docs/算法/采集与算法层设计说明.md`:203 |
| `交流六轮速查.svg` | `gen_ac_rounds_svg.py` | 交流(正弦)动态验证六轮的总览卡:每轮注什么波形(六张波形缩略图)、判据一句话、主读数出口 | `SUB1` / `SUB2` + `CARDS` 六轮卡 + `FOOTNOTE` | `docs/测试说明/专项验证/ADC前端注入验证流程.md`:296 |
| `交流定数取中位数.svg` | `gen_ac_median_svg.py` | 为什么交流轮必须"连取 10 行心跳取中位数":机理(全周窗逐拍滑动 → 单行带拍频跳)与操作(中位数 vs 平均 vs 单行对真值) | `SUB1` + `VALS` 两栏数值 + `OPS_NOTE` / `FOOTNOTE` | `docs/测试说明/专项验证/ADC前端注入验证流程.md`:431 |
| **网络与协议** | | | | |
| `BSD网络栈分层.svg` | `gen_net_stack_svg.py` | BSD socket 分层在本仓落到哪一层(CH395F 之上) | `ROWS` 分层清单 + 标题 / 脚注文案 | `docs/网络/BSD_Socket_API_使用指南.md`:56 |
| `Net层阻塞模型.svg` | `gen_net_pending_svg.py` | 挂起(pending)请求模型:调用方两栏 + 主循环横带 + recv 五路 / send 四路判定带 | `CALLER_STEPS` / `FAST_PATH` / `LOOP_STEPS` / `PHASES` / `FOOT` | `docs/网络/Net层阻塞模型架构设计.md`:77 |
| `网络不稳根因总览.svg` | `gen_net_instability_svg.py` | 自愈架构复盘:左列七个误会(问题环)、右列对应拆法,水平箭头一一对应、竖箭头表示"叠加累积" | `RINGS` 七对 + `SUM_LEFT` / `SUM_RIGHT` 两个总结盒 + `FOOT` | `docs/网络/网络自愈架构设计.md`:233 |
| `RemoDispBus帧格式.svg` | `gen_frame_svg.py` | 协议帧字节级布局:字段宽严格 ∝ 字节数 + 逐字段标注 + 偏移标尺 | `FIELDS` / `TITLE` / `SUB` / `FOOT` | `docs/UI设计/RemoDispBus协议与接收设计说明.md`:60、`docs/产品需求/产品需求设计文档.md`:1204 |
| **存储与内存** | | | | |
| `存储栈分层.svg` | `gen_storage_stack_svg.py` | 存储栈三层:dhara FTL / FatFs / 应用落点(`gen_arch_svg.py` 的单栈副本) | `ROWS`(层数据在 `L_*` 常量)/ `TITLE` / `SUB` / `FOOT` | `docs/产品需求/产品需求设计文档.md`:299、`docs/架构设计/STM32F4-Base存储架构说明.md`:7 |
| `物理分区布局.svg` | `gen_partition_svg.py` | SPI NAND 物理分区:分区宽 ∝ MB 数 + 偏移标尺(帧图生成器的 MB 计量副本) | `FIELDS` / `TITLE` / `SUB` / `FOOT`(MB 计量) | `docs/架构设计/STM32F4-Base存储架构说明.md`:11 |
| `内存布局_RAM.svg` | `gen_memory_svg.py` | 192 KB SRAM(SRAM1/2)+ CCM 的分区归属与占用 | `RAM1_CATEGORIES` / `RAM2_CATEGORIES` | **零内嵌**——只在 `docs/内存管理/RAM使用分析与优化方案.md`:772 与本表被文字提到 |
| `内存布局_FLASH.svg` | `gen_memory_svg.py` | 1 MB Flash 的段划分与代码 / 常量占比 | `FLASH_CATEGORIES` / `FLASH_CODE_SUB` | `docs/内存管理/RAM使用分析与优化方案.md`:239 |
| `任务栈预算.svg` | `gen_memory_svg.py` | 9 个任务的栈配额与内核静态占用合计 | `TASK_STACKS` / `KERNEL_STACKS` | `docs/内存管理/RAM使用分析与优化方案.md`:101 |
| **时间 / 看门狗 / 录波** | | | | |
| `看门狗心跳模型.svg` | `gen_watchdog_svg.py` | IWDG + 任务心跳位图:置位 → 判定 → 喂狗,配一条时间轴 | `TASKS` / `REQ_BITS` / `POLL_STEPS` / `T_AXIS` / `TIMELINE` / `FOOT` | `docs/产品需求/产品需求设计文档.md`:397、`docs/子系统设计/看门狗设计说明.md`:151 |
| `故障录波数据流.svg` | `gen_wave_record_flow_svg.py` | 录波段数据的四个所有者与四条「不许」:谁独占写、谁只能读、标志怎么过界 | `CHAIN` 主链四段 + `EDGE` 跨边界标签 + `TRAPS` 三条陷阱 + `FORBID` 四条红线(所有权、段形态或红线变了才重画) | `docs/子系统设计/故障录波设计说明.md`:165 |
| **UI** | | | | |
| `菜单树总览.svg` | `gen_menu_tree_svg.py` | 菜单树 43 节点的层级 / 绑页 / 密码门鸟瞰 | **内嵌 `NODE_SRC`**(= `ui_menu_tree.txt` 的 43 行节点)+ `X_COL` 版面常量;在仓库里跑会与真值逐行互验、不一致 exit 1(临时目录读不到真值 → 用内嵌表,保证输出逐字节一致) | `docs/产品需求/产品需求设计文档.md`:1537 |
| `级联框总览.svg` | **无生成器(手工 SVG)** | 横向级联子框总览(主界面 → 参数定值 → 整定)的显示几何示意 | 直接改 SVG 文本(2026-09-08 入库 `891c9ef0`,2026-09-11 随配图规范收拢 `2429955d`);只作**显示几何示意**,不承载菜单树事实 | `docs/UI设计/菜单页面设计.md`:442 |
| `级联框几何计算.svg` | **无生成器(手工 SVG)** | `ui_menu_view_frame_build()` 逐框坐标推导:行剖面定框宽 → X 贴父框右缘 → Y 顶对齐选中行 → Y 溢出上移 | 同上;**坐标公式变了要重算重画,别在 SVG 上描字** | `docs/UI设计/菜单页面设计.md`:500 |
| **引用关系(另一个工具)** | | | | |
| `引用关系图.svg` | `tools/refgraph/gen_refgraph.py`(graphviz) | 文件级引用图(项目代码视图) | 跑 `& 'tools\refgraph\gen_refgraph.bat'` 重生成,**svg 与改动同一笔提交**,别只更新 `.dot` | **零内嵌**——`docs/架构设计/引用关系图说明.md`:47、`tools/refgraph/README.md`:23 以表格条目列出 |
| `引用关系图_模块.svg` | 同上 | 模块级概览图(目录 / 库聚合,边上 ×n = 引用条数) | 同上 | **零内嵌**——`docs/架构设计/引用关系图说明.md`:48 |
> **`OVERFLOW` 不算「数据区」**:它是生成器末尾的溢出预检累加器(非空即打 `OVERFLOW:` 并 exit 1),
> 不是给人改的内容。判据与预检用法 → **`draw-diagram` skill** §三。
>
> **本表怎么保持不漂**:新增生成器 = 同批在本表加一行(本目录的约定,也是 `draw-diagram` skill §五第 6 步);
> 图换挂载文档 = 同批改「挂在」列。门禁只兜**幂等性**不兜本表——`scripts/check_generated_fresh.py` 的
> `docs-svg` 条目按 `tools/arch_diagram/gen_*.py` **自动发现**重跑逐字节比对,**不必登记**;只有需要外部
> seed 的条目(`menu-gen` / `cn-chars` / `cn-font`)才在 `GENS` 里显式登记 → `docs/门禁说明/generated-fresh.md` §8。
## 使用方式
```bash
& '.venv\Scripts\python.exe' tools/arch_diagram/gen_memory_svg.py
```
产物统一输出到 `docs/images/`;**脚本与生成的 `.svg` 一并提交**。
## ⚠️ 约定
- 颜色/字体遵循 `docs/架构设计/图形绘制流程.md` 的规范
- 中文用 SVG `<text>` 直接写(需注意字体族声明)
- 改图**改脚本再重跑**,不手改 SVG(保证可复现);上表标「无生成器」的两张级联框图是**例外面**,
再多一张先说清为什么不能用生成器 → `docs/架构设计/图形绘制流程.md` §2.1
- 表里没有的 `docs/images/*.svg` 就是漂移——按 `grep -rn "gen_" tools/arch_diagram/*.py` 与
`ls docs/images/*.svg` 对账补齐本表,别另起一张
## 相关文档
- `docs/架构设计/图形绘制流程.md` — 配图选型(什么图用什么工具)、绘制流程与检查清单
- `docs/文档规范.md` §4.4 — 配图与生成物的入库纪律(类别级在册清单,不逐脚本登记)
- `docs/门禁说明/generated-fresh.md` — 幂等性门禁查什么、盲区在哪
- **`draw-diagram` skill** — 画图时的操作入口(含大图碰撞审计判据)