Files
STM32F4-Base/docs/架构设计/引用关系图说明.md
T
wandering1 cea2b51efb docs(架构): 全景/启动顺序/存储/引用图与 README 同步任务面与 NET 内部模块
- 项目架构总览 v1.1:§1.1 去重复⑥行、硬件行 UART4/TIM3/ADC1;§2.1
  任务表 6→9 行且栈值按 freertos.c 校准;§3 补采集算法链与 TIM3 节拍;
  §5 补 net_events/net_listener/net_pending 与 iec104_serv,单客户端
  恢复窗更正为实测 p50 208ms;§7 目录树、§9 索引、§10 变更记录同步
- 项目启动顺序管理:任务表 5→10 行;启动轨迹表 8→14 行(fw build、
  ADC input layer、phasor/freq/protection、SD2506 明细、TIM3 启动)
- 存储架构说明:§1 初始化顺序块重写(gd5f 归位 app_main_init 内、
  rs485Task 未创建、补 TIM3 与 L1~L3 链)
- 引用关系图说明 §7 统计与产物重跑刷新;就绪屏障 SVG 补 iec104Task
  消费者后重生成(1400x912)
- README:外设引脚纠错(RS485=UART4/PC10/PC11/PA15、TPAFE 控制脚
  PC8/PC9/PC7)、启动流程补 sys_clock/adc_input/TIM3、任务表重生成
  (9 任务)、目录树与 NET 小节同步、ftp_speed_test→regression/
  integrity、文档表补四条专项索引
- 工具:gen_task_table.py 补 iec104Task/protectTask 职责;
  gen_barrier_svg.py 补 iec104Task 消费者与 bit0 计数
2026-10-14 19:07:48 +08:00

6.1 KiB
Raw Blame History

项目文件引用关系图(tools/refgraph)

生成并维护 STM32F4-Base 的文件级引用关系图(#include 引用)。 工具:tools/refgraph/gen_refgraph.py(纯标准库)+ 成熟渲染引擎 Graphviz。 产物:docs/images/引用关系图.*(本目录图 + .dot + .json)。

1. 为什么自写工具(调研结论)

成熟工具 能力 对本需求的差距
Doxygen(开源,C 文档标准工具) 每文件的 include 依赖图、每函数的调用图、类协作图 输出按文件/函数分散,无单一整工程文件引用图;需配置解析全量源码
Graphviz(开源,图布局渲染引擎 dot) 渲染任意 DOT 图(分层布局) 只做布局渲染、不解析源码 —— 本工具用它出图
cflow(binutils) 函数级调用图 粒度是函数不是文件;依赖汇编/编译产物
SciTools Understand(商业) 依赖图/调用树/引用映射 重量级付费 IDE,不可脚本化、不入构建流程

结论:没有现成成熟工具能直接输出"单一、整工程、可重跑更新"的文件引用关系图, 故按"没有则自写"原则自写解析/建模工具;布局渲染这一难点交给成熟引擎 Graphviz。 本机已通过 winget 安装 Graphviz 16.1.0(安装后 dot 可从 PATH 找到;非标准安装位置用 DTU_GRAPHVIZ_DOT 指向 dot.exe,见 docs/环境与部署/本地工具路径环境变量方案.md)。

2. 生成 / 更新(一条命令)

# 方式一:bat(任意位置可运行)
& 'tools\refgraph\gen_refgraph.bat'

# 方式二:python 直跑(等效)
& '.venv\Scripts\python.exe' tools/refgraph/gen_refgraph.py

项目文件有增删改后,重跑上式即可:产物全量重新生成并覆盖 docs/images/引用关系图.*,对照 引用关系图.json 的文本 diff 即可看出引用面变化, 然后按仓库惯例把(工具 + 产物)一并提交。

可选参数:

参数 默认 说明
--views full,module 两者 只出文件级 / 只出模块级
--edge-scope project|all project project=仅第一方代码发起的引用边(清晰);all=含第三方内部引用(完整但密集)
--no-render 关 只出 .dot/.json,不调 Graphviz
--quiet 关 精简控制台输出

3. 产物与图例

文件 说明 是否提交
引用关系图.svg / .dot 文件级引用图(项目代码视图) 是
引用关系图_模块.svg / .dot 模块级概览图(目录/库聚合,边上 ×n=引用条数) 是
引用关系图.json 结构化数据:全部节点/边/未解析 include 明细 是
引用关系图.png 文件级图位图预览(大,~5 MB) 否(本地预览,可随时重出)

图例(文件级):

  • 节点:蓝=第一方(App/、Inc/、Src/、test/、simulator/〔除 SDL2、build〕、 Drivers/BSP/〔除 NET/lftpd〕);灰=第三方(Lib/、Middlewares/、 Drivers/CMSIS、HAL、lftpd、SDL2);橙=外部/系统头文件聚合节点。
  • 边:蓝实线 第一方→第一方;灰实线 第一方→第三方; 橙虚线 →外部/系统头文件(stdio.h 等编译器提供); all 模式下另有淡点线=第三方内部引用。

模块级图把第一方按目录模块聚合(App、App/task、BSP/UI、Src/Inc (CubeMX)…)、 第三方按库聚合(LVGL、FreeRTOS、CMSIS、HAL、FatFs、dhara、lftpd、SDL2)。

4. 解析原理(与编译器行为对齐)

  1. 扫描仓库全部 .c/.h(跳过 .git/.venv/MDK-ARM/docs/simulator/build);
  2. 提取每条 #include(处理行尾反斜杠续行;编码按 UTF-8→GBK→Latin-1 兜底);
  3. 解析顺序与编译器一致:所在文件目录 → Keil 工程包含路径(解析自 MDK-ARM/STM32F407-Demo.uvprojx,自动跟随)→ 模拟器 CMake 包含路径 (simulator/CMakeLists.txt,脚本内 SIM_INCLUDE_DIRS 需手动同步);
  4. 解析到仓库内文件 → 成边;解析不到 → 归"外部/系统头文件"(明细在 JSON unresolved),与编译器查系统目录的行为一致。
  5. 刻意不做"基名全库兜底":仓库内存在同名系统头(rapidjson 自带 msinttypes/stdint.h),兜底会把各处 <stdint.h> 误连到库内部文件产生假边 (曾产生 100+ 条假边,已验证并移除)。

5. 语义与已知限制

  • 文本层引用:#if 0 内、MCU/模拟器平台条件下的引用均计入(完整呈现项目引用面); 不评估 #if 条件 —— 未激活条件内的引用(如 LV_USE_DRAW_VG_LITE=0 时的 vg_lite.h)会显示为"未解析→外部",属预期。
  • 仅文件级 #include 引用;不含函数级调用关系(如需,可另行用 Doxygen/cflow 补充)。
  • 双端(Keil MCU / CMake 模拟器)包含路径合并解析,个别引用是"另一端视角" (如 LVGL 的 SDL2 后端引用),属项目级引用面的如实呈现。
  • 第一方/第三方划分规则见脚本头部 classify();lftpd 为移植的第三方组件 (与 AGENTS.md pre-commit 排除名单一致)。

6. 维护

  • 新增/移动第一方目录 → 改脚本 classify()、FP_MODULES; 新增第三方库 → 改 TP_LIBS(模块级聚合用)。
  • Keil 工程包含路径变化:自动跟随(每次运行解析 uvprojx)。
  • 模拟器包含路径变化:同步脚本 SIM_INCLUDE_DIRS 常量。
  • 换机:winget install Graphviz.Graphviz(渲染依赖;缺失时工具自动跳过渲染, 仍产出 .dot)。

7. 当前数据(2026-10-14 刷新)

索引 1495 个 .c/.h;解析 include 5972 条(解析成功 4821,外部/系统 1151,351 种); 第一方文件 215 个;节点 = 第一方 215 + 第三方 1266 + 外部聚合 1;去重边 5176 条。 被引用最多的第一方文件:Drivers/BSP/dbg_log.h(48)、Inc/main.h(33)、 Drivers/BSP/NET/net_socket.h(18)……(完整 Top10 见运行报告)。