让评审报告与 待处理内容.md 的分工更直观: - git mv 项目审查与优化建议报告.md → docs/问题记录/(与 Trap 台账、 错误码传播审计同处"专项审计"目录);rmdir 空的 docs/审查记录/。 - docs/README.md:§8 标题改为「评审报告 · 环境与部署 · 外部资料」, §8.1 改为「评审报告」,目录树删 审查记录/、补 问题记录/ 说明, 按角色导航改为 §8.1/§8.3,补 2026-10-04 变更记录。 - 根 README.md 目录树同步。 - docs/文档规范.md §1.1 现有目录列表、§6 归属表同步。 - 看门狗设计说明.md / 待处理内容.md 的路径引用重定向。 pre-commit 17/17 Passed。
15 KiB
文档规范
适用对象:本仓库
docs/下的全部 Markdown 文档,以及根目录README.md、AGENTS.md。 强制程度:§1~§6 为强制(pre-commit 机械校验,违反即拦截提交);§7~§8 为约定(评审时人工把关)。 相关文档:README.md(文档索引)、代码规范/pre-commit使用说明.md(钩子清单)、架构设计/图形绘制流程.md(配图流程)。
1. 目录与命名
1.1 目录
| 规则 | 说明 |
|---|---|
| 目录名一律不含空格 | 空格迫使脚本/链接/CI 处处加引号,且 URL 编码形态(UI%20设计)极易被漏改(D-6,2026-09-25 起强制;全库已无含空格目录) |
| 按领域归入子目录 | 顶层不放散落 .md;新领域先建无空格子目录,再在 README.md 登记 |
| 现有目录 | 架构设计/ 子系统设计/ 网络/ 测试说明/ 代码规范/ 内存管理/ 问题记录/ 环境与部署/ UI设计/ 硬件平台/ 芯片手册/ images/ |
1.1b 代码目录的 README.md
每个自建代码目录(非第三方库、非 HAL/CMSIS 生成)必须有一份 README.md,
说明该目录的职责、文件清单与关键约束,让新接手者不必读遍代码即可建立认知。
| 规则 | 说明 |
|---|---|
| 覆盖范围 | App/(含 log/ task/ util/)、Drivers/BSP/(含各芯片子目录)、Src/、Inc/、scripts/、tools/(含各子工具)、test/、MDK-ARM/、simulator/(含 sim/ tests/)、docs/ |
| 排除 | 第三方库与生成代码:Drivers/CMSIS/、Drivers/STM32F4xx_HAL_Driver/、Middlewares/Third_Party/、Lib/(FatFs/dhara/lvgl)、simulator/SDL2/、构建产物目录 |
| 必备内容 | ① 一句话定位 + 是否自研 ② 文件/子目录清单表(每个一句话作用)③ 关键约束或陷阱(改前须知)④ 指向 docs/ 权威文档的链接 |
| 命名 | 一律 README.md(大写),放该目录根部 |
| 链接 | 目录间互链用同级相对路径(如 ../NET/README.md);指向 docs/ 用仓库根相对路径 |
| 门禁 | README 内所有链接受 doc-links 钩子检查;新增/改名目录或文件后须同步更新对应 README |
目的:目录即文档的入口。根
README.md给全局地图,各目录README.md给局部细节, 二者构成"地图 + 地标"的导航体系(避免所有信息堆在单一 README)。
1.2 文件名
| 规则 | 说明 |
|---|---|
| 不含空格 | 同目录规则 |
| 主题词 + 类型后缀 | xxx设计说明.md / xxx_Test_Guide.md / xxx_Trap_Records.md / xxx使用说明.md |
| 中英混排 | 中文主题词直接写(如 系统墙钟时间维护说明.md);含专有名词/缩写可用下划线连接(如 BSD_Socket_API_使用指南.md) |
| 只用 ASCII 与中文 | 不含 ()【】〔〕 等全角括号、不含 &、?、*、<、>、` |
| 版本号写法 | 版本后缀用下划线连接,不用全角括号:xxx_V1.0.md(✅)/ xxx(V1.0).md(❌) |
例外:
docs/芯片手册/为外部芯片数据手册转录,文件名沿用上游原名(含空格等),不受本节约束。
2. 编码与换行
| 项 | 要求 |
|---|---|
| 编码 | UTF-8;.md 文档不带 BOM |
| 换行 | 与文件现状保持一致;新建文档用 LF |
| 行尾空白 | 禁止(pre-commit trailing-whitespace 自动清理) |
| 文件尾 | 必须以单个换行结束(end-of-file-fixer) |
| 乱码 | 禁止出现 U+FFFD(替换字符,字节序列 EF BF BD) |
⚠️ 本仓库 BOM 铁律(见
AGENTS.md):C 源码中Drivers/BSP/UI/*、App/task/ui_task.c、App/cfg/cfg_file.c、Lib/lv_conf.h等带 BOM,被工具改写后 BOM 会静默丢失 → ARMCC 改按 CP936 解码 → 中文字面量编译失败。 文档(.md)不受此限,一律用无 BOM UTF-8。但用脚本批量改写文档时,仍须按原样回写换行符(本仓库core.autocrlf=true且无.gitattributes,工作区换行混杂),否则会产生整文件行尾漂移的巨型 diff。
3. 链接规范
3.1 文档间互链:仓库根相对路径
文档之间引用一律使用仓库根相对路径(形如 `docs/xxx/yyy.md` 或 [文本](docs/xxx/yyy.md)),不使用 ../ 相对链接。
理由:根相对路径对文档所在层级不敏感,迁移子目录时零改动;
../形态在目录调整时会成片失效。
3.2 图片链接:文档所在目录相对
图片是例外——用相对当前文档的路径:
| 文档位置 | 图片写法 |
|---|---|
docs/xxx.md(docs 根下) |
 |
docs/子目录/xxx.md |
 |
⚠️ 踩坑记录:2026-09-25 目录重组时,5 篇文档从
docs/迁入子目录,images/xxx.svg未同步改为../images/xxx.svg→ 7 处真实断链(由 D-7 门禁check_doc_links.py揪出)。迁移含图文档时务必检查此项。
3.3 引用尚未创建 / 已删除的文件
| 场景 | 写法 | 示例 |
|---|---|---|
| 计划中、尚未创建 | 反引号内加 [计划] 前缀 |
`[计划] scripts/gen_task_table.py` |
| 已删除 | 写明「已删除」等状态词 | 删除 \tools/ui_mock/render_mockup.py`(已删除)` |
| 引用报错样例 / 日志片段(含路径) | 该行加 [示例] 标记 |
| **典型报错** | \[示例] docs/a.md:1 [markdown 链接] x.svg` |` |
为什么:check_doc_links.py 会豁免这些标记;否则门禁会把"诚实标注了未创建"的引用误判为断链。
3.4 链接写法示例须放行内代码
讲「怎么写链接」的语法示例必须包在反引号里(行内代码 span):
- ✅ 正确:
写 `` 的形式 - ❌ 错误:
写  的形式(会被门禁当作真实链接去校验存在性)
check_doc_links.py 扫描前会剥离行内代码 span,故写法示例不会误报;但反引号内的仓库根相对路径(docs/xxx.md)仍会被校验——那是本工程的引用约定形态。
4. 门禁:文档-代码一致性(D-7)
三个层次,全部由 pre-commit 机械校验:
| 层次 | 钩子 | 检查内容 | 触发条件 |
|---|---|---|---|
| 存在性 | doc-links |
docs/**/*.md 里的链接、反引号路径是否指向真实文件 |
改动任意 .md |
| 数值 | task-table |
README.md、AGENTS.md 的 FreeRTOS 任务表是否与 Src/freertos.c 一致 |
改动 README.md / AGENTS.md / Src/freertos.c |
| 体积 | mem-numbers |
内存/Flash 数字是否与最新 .map 一致(受管区 + 陈旧散句数字) |
改动内存文档 / App·Src·Inc 源码 / 脚本 |
| 体积 | check-added-large-files |
阻止 >1MB 大文件入库 | 任意文件 |
4.1 本地手动运行
# 全库文档链接存在性
& '.venv\Scripts\python.exe' scripts/check_doc_links.py --all
# 任务表一致性(只检查)
& '.venv\Scripts\python.exe' scripts/gen_task_table.py --check
# 任务表不一致时:自动重写受管表格区
& '.venv\Scripts\python.exe' scripts/gen_task_table.py --write
# 内存数字(受管快照 + 陈旧散句数字扫描)
& '.venv\Scripts\python.exe' scripts/check_mem_numbers.py --scan
& '.venv\Scripts\python.exe' scripts/check_mem_numbers.py --write # 同步受管快照
# 只看期望内容,不写文件
& '.venv\Scripts\python.exe' scripts/gen_task_table.py --diff
& '.venv\Scripts\python.exe' scripts/check_mem_numbers.py --diff
# 生成完整内存台账(人工分析用)
& '.venv\Scripts\python.exe' scripts/ram_report.py -o docs/内存管理/data/ram_report_<日期>.md
4.2 受管区域(锚点)
文档里凡随代码变化的具体数值,都必须放进受管区,由脚本生成、禁止手改:
任务表(README.md / AGENTS.md)——表格外的说明文字原样保留:
<!-- TASK_TABLE:BEGIN generated by scripts/gen_task_table.py -->
| Task | 栈 (words) | 优先级 |
|---|---|---|
| ... |
<!-- TASK_TABLE:END -->
内存/Flash 快照(docs/内存管理/RAM使用分析与优化方案.md §2.1):
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
| 区域 | 用量 | 容量 | 占比 |
|---|---|---|---|
| ... |
<!-- MEM_SNAPSHOT:END -->
改栈流程:先改
Src/freertos.c的osThreadAttr_t→ 跑gen_task_table.py --write→ 提交。 改内存流程:先改代码 +@build出.map→ 跑check_mem_numbers.py --write→ 提交。 钩子报不一致时不要手改受管区——跑--write让脚本重算。
陈旧数字扫描(mem-numbers --scan)
除受管区外,脚本还会扫正文里的陈旧区域数字:从 docs/内存管理/data/ram_report_*.md
历史快照提取「曾经是区域用量、现已变化」的值(如旧 RW_IRAM1 82,048),
若正文仍以陈述现状的口吻引用即告警。
允许保留旧数字的情况(脚本按行内关键词自动放行):该行含
「历史 / 旧 / 曾 / 此前 / 快照 / data/ / 修复前 / 优化前 / 迁入前 / 实施时 / 当时」等标记。
讲任务栈 / 内存池 / 峰值水位等非区域用量的行也自动跳过(那些数字语义不同)。
设计取舍:朴素地"扫所有 4~7 位数字"实测产生 45 处误报(栈配置
4096、堆配置49,152、 峰值1184全是合法数字),门禁会被无视。改为"只报历史快照里出现过、当前已变的区域值"后 误报 0、真问题全中。宁可窄而准,不可宽而吵。
4.3 豁免机制
check_doc_links.py 的豁免(不算失效,不报错):
`[计划] `前缀标记- 该行含
[示例]标记(引用报错样例 / 日志片段等含路径的引文) - 引用附近 ±40 字符内出现「未创建 / 尚未创建 / 已删除 / 待排期」等状态词
- 含通配符
*、尖括号<模块>等占位符 - 模板变量样式(
NN_/XX_/界面名/模块名/${...}/%s等) - 行内代码 span 里的链接写法
- 外部 URL(
http/https/mailto)与纯锚点(#...) docs/芯片手册/等外部资料目录
⚠️ 状态词按就近(±40 字符)判定,不是整行——否则文件名本身含「不存在」「删除」等字样时会误豁免同行的其它真实引用(2026-09-25 实测修正)。
5. 文档结构
5.1 必备要素
| 要素 | 要求 |
|---|---|
| 一级标题 | 文档首行为 # 标题,标题即主题,不写"文档""说明"等冗余后缀 |
| 开篇引言 | 可选 > 引用块,写明适用对象 / 阅读前提 / 相关文档 |
| 章节编号 | 多章节文档用 ## 1. ### 1.1 编号,便于交叉引用(§3.2) |
| 变更记录 | 设计类、流程类文档建议末尾保留「变更记录」表(日期 | 变更 | 说明) |
5.2 新增文档检查清单
新增一篇文档时逐项确认:
- 放在正确的子目录(目录名无空格)
- 文件名符合命名约定(无空格 / 主题词+类型后缀)
- UTF-8 无 BOM、LF 换行
- 互链用仓库根相对路径;图片用当前目录相对路径
- 尚未创建/已删除的引用加
[计划]或状态词 - 已在
README.md对应章节登记一行(否则视为未完成) - 若涉及任务表/栈,跑
gen_task_table.py --check pre-commit run --files <新文档>通过
6. 与代码文档的边界
| 内容 | 归属 |
|---|---|
| 项目级铁律、构建/烧录/测试命令、平台约束 | AGENTS.md(AI 协作上下文,精简优先) |
| 开发者入门、架构速览、目录导航 | README.md |
| 详细设计、专项说明、测试指南 | docs/ 下对应子目录 |
| 跨文档待办登记 | docs/待处理内容.md(统一登记簿) |
| 评审报告与专项审计 | docs/问题记录/ |
避免重复:同一事实只在一处详述,其它位置用链接指向。典型如 FreeRTOS 任务表——
Src/freertos.c是唯一事实源,README.md/AGENTS.md的表由脚本生成,不在别处再抄一份。
7. 写作约定
| 项 | 约定 |
|---|---|
| 语气 | 陈述事实,不用"我们认为""大家注意"等口语 |
| 标点 | 中文正文用全角标点;代码、路径、命令、文件名用行内代码 `...` |
| 术语 | 首次出现给全称 + 缩写(如"配置引擎(cfg_file)"),此后统一用同一术语 |
| 表格 | 对比、清单、参数优先用表格而非长段落 |
| 命令 | 用 powershell 代码块,含 & '.venv\Scripts\python.exe' 等本仓库统一入口 |
| 图 | 拓扑类用 Mermaid 代码块;技术配图走 SVG 生成器(见 架构设计/图形绘制流程.md) |
| 状态标记 | ✅ 已完成 / ⚠️ 注意事项 / ❌ 禁止 / 📌 要点(克制使用,不滥用 emoji) |
8. 常见错误速查
| 现象 | 原因 | 修复 |
|---|---|---|
doc-links 报失效链接 |
文件被移动/删除后引用未同步 | 改引用路径,或加 [计划] / 状态词 |
doc-links 报语法示例行 |
链接示例没包反引号 | 把示例包进 ` |
task-table 报不一致 |
freertos.c 改栈后文档未同步 |
跑 gen_task_table.py --write |
| 提交 diff 出现整文件行尾变化 | 脚本改写时强制了 LF/CRLF | 改写须按原换行符回写(见 §2) |
| 图片不显示 | 文档迁入子目录后未改 ../images/ |
补 ../(见 §3.2) |
| 引用"计划中"文件被拦 | 没加 [计划] 前缀 |
加前缀 |
变更记录
| 日期 | 变更 | 说明 |
|---|---|---|
| 2026-09-25 | 建立本文档 | 正式确立目录/命名/编码/链接/门禁/结构与写作约定;承接 D-6(去空格)与 D-7(一致性门禁),配套交付 scripts/check_doc_links.py、scripts/gen_task_table.py 两个门禁脚本与 doc-links/task-table 两个 pre-commit 钩子 |
| 2026-09-25 | 文件名风格统一(D-6 剩余) | 代码规范/嵌入式C语言代码规范(V1.0).md → 嵌入式C语言代码规范_V1.0.md(全角括号 → 下划线),同步 5 个文档 + 1 个脚本共 9 处引用;§1.2 明确禁用全角括号与版本号写法;docs/芯片手册/ 作为外部资料例外 |
| 2026-09-26 | 体积档门禁落地(D-7 第三档) | 交付 scripts/check_mem_numbers.py + pre-commit mem-numbers 钩子;§4.2 增「受管区域(锚点)」与「陈旧数字扫描」两节,记录误报取舍 |