merge: task/testdoc-test-docs-layering 合入 v2-on-ui
任务 testdoc(1 个提交)经 task-worktree 回收: - docs(测试说明): 按用途分六个子目录并同步全库引用
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
"stack-overflow-hook-impl": "03a383dda578d12a",
|
||||
"malloc-failed-hook-impl": "fcd7250e5cd6403b",
|
||||
"stack-overflow-hook-helper": "cacd9fd028be9b5b",
|
||||
"watchdog-module": "07808632996d66e8",
|
||||
"watchdog-module": "5fd7efd90a78fe5a",
|
||||
"net-msgq-adopt": "a0f913e3f34c8e9e",
|
||||
"reset-cause-latch": "983927d587cb9f48",
|
||||
"iwdg-hal-driver": "4b902875a84554e9",
|
||||
|
||||
@@ -36,7 +36,7 @@ whenToUse: 要跑板级测试套件(CH395F/STORAGE/GD5F/RTC)回归、要开/
|
||||
1. `test_config.h` 恢复全注释(用 run_all_suites.py 则已自动);
|
||||
2. `@build` 确认产品构建 0 错 0 警;
|
||||
3. 若开过破坏性开关:核对开机日志容量数字(健康满值 96064 pages / 187 MB),
|
||||
掉了 → 按 `docs/测试说明/存储维护与容量恢复.md` 走恢复动作;
|
||||
掉了 → 按 `docs/测试说明/专项验证/存储维护与容量恢复.md` 走恢复动作;
|
||||
4. 提交前 `test-suite-switch` 门禁会再兜一道。
|
||||
|
||||
## 三个维护动作别混用(存储类)
|
||||
@@ -47,8 +47,8 @@ whenToUse: 要跑板级测试套件(CH395F/STORAGE/GD5F/RTC)回归、要开/
|
||||
| B 容量恢复 | A + `STORAGE_RECOVERY_FULL_WIPE`(擦净 2044 块 + 断电重启) | 卷全失,约 4s 擦除 |
|
||||
| C 日常回归 | 只开 `TEST_SUITE_*`,不开破坏性 | 无(只读模式,横幅 `mode: READ-ONLY`) |
|
||||
|
||||
原理与完整步骤见 `docs/测试说明/存储维护与容量恢复.md`;各套件用例清单/判读见
|
||||
`docs/测试说明/` 对应 `*_Test_Guide.md`;流程规范 `docs/测试说明/测试开发标准流程.md` §3。
|
||||
原理与完整步骤见 `docs/测试说明/专项验证/存储维护与容量恢复.md`;各套件用例清单/判读见
|
||||
`docs/测试说明/` 对应 `*_Test_Guide.md`;流程规范 `docs/测试说明/流程与规范/测试开发标准流程.md` §3。
|
||||
|
||||
## 其它项目怎么套
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
1. **先确认连归档扫描工具也咬不到,并把这句话写进交付**(两道编号门禁已退役,机器面整体消失):`scripts/archive/id_gate/check_ids.py` 的族 pattern 是拉丁形态、中文前缀不进语料 → **id-check 的 refs / 可判定比例 / 悬空引用与本族无关**;报告开头写「本族不在 check_ids 语料内,口径 = 自建扫描器」。
|
||||
2. **销项删行前先核证据属主**(这是删行的唯一许可证):
|
||||
- 先取历史口径:`git log --oneline -20 -- <文档>`、`git show <rev>:<文档> | sed -n '/^## 5/,/^## 6/p'` 找回被删的卡表与当初「完成即销项删行 / 标 ✅ 保留行」的理由;
|
||||
- 核对判据与实测记录**已完整沉淀进属主章节**(实测:「已知电压注入验证」六项判据全 PASS、斜率 6544.2 码/V、偏差 −0.14 % 全在 `docs/硬件平台/ADC通道映射说明.md` §8.1,执行侧在 `docs/测试说明/ADC前端注入验证流程.md`);
|
||||
- 核对判据与实测记录**已完整沉淀进属主章节**(实测:「已知电压注入验证」六项判据全 PASS、斜率 6544.2 码/V、偏差 −0.14 % 全在 `docs/硬件平台/ADC通道映射说明.md` §8.1,执行侧在 `docs/测试说明/专项验证/ADC前端注入验证流程.md`);
|
||||
- **删的是任务规划侧的行与结论块,不是证据本体**;被代码头注释指称的设计约束章节(§2~§4 那类)**原样保留**,只删已完成记录;
|
||||
- 该行若当初是被「代码头注释按号引用」当例外保住的(实测 `App/task/adc_task.c` 的 v3.3 修订行按卡号当口径出处),必须**先把引用侧改成语义短语**,例外才成立撤销,并在规范里写明撤销理由(上一笔「完成即保留行」的例外就是这么随引用侧改动被撤掉的);
|
||||
- 删完逐行通读被改小节,报**行数变化**,不留孤立残句(实测 J7 dropped line 234 len=639、J13 闭环结论块 6 行删除并注明证据属主)。
|
||||
|
||||
@@ -40,7 +40,7 @@ RemoDispBus 推流回归单独跑:`.venv\Scripts\python.exe simulator/tests/ch
|
||||
## 两条铁律
|
||||
|
||||
- **改 `simulator/lv_conf.h` 触发 `lv-conf-sync` 门禁**:它与 MCU 端 `Lib/lv_conf.h` 必须保持同一特性子集(按**生效值**比对,未定义取 `lv_conf_internal.h` 兜底);四类判定与端专属白名单 → `docs/门禁说明/lv-conf-sync.md`;顶层 exclude 的教训 → `docs/代码规范/pre-commit使用说明.md` §5.5
|
||||
- **模拟器代码与固件同标准受检**(`cppcheck` / `coding-standard` / 乱码 / 改写型钩子 / `doc-links` 全覆盖 `simulator/`);**改动触及 `sim/` 任何后端,必须同步在 `docs/测试说明/模拟器差距清单.md` 登记一行**——模拟器跑过 ≠ 真机跑过
|
||||
- **模拟器代码与固件同标准受检**(`cppcheck` / `coding-standard` / 乱码 / 改写型钩子 / `doc-links` 全覆盖 `simulator/`);**改动触及 `sim/` 任何后端,必须同步在 `docs/测试说明/专项验证/模拟器差距清单.md` 登记一行**——模拟器跑过 ≠ 真机跑过
|
||||
|
||||
## 构建/运行报错速查(详解 `simulator/README.md`「四、已知坑(构建/运行)」)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""serial_tool — Python 串口助手(常驻 daemon + 薄 CLI + 日志文件即接口)。
|
||||
|
||||
设计文档:docs/测试说明/串口助手设计说明.md
|
||||
设计文档:docs/测试说明/测试工具/串口助手设计说明.md
|
||||
|
||||
架构:
|
||||
CLI(短命进程,硬超时) --HTTP JSON--> daemon(detached 单实例,127.0.0.1)
|
||||
|
||||
@@ -16,7 +16,7 @@ whenToUse: 需要向目标板烧录或复位后,用串口日志自动判定运
|
||||
| `.dsh/skills/serial-boot-test/scripts/run_boot_test.py` | 一键闭环:open+clear → 烧录 → wait-idle → 提取 boot log → 烧录回读校验 → 标记校验。串口助手按 `$DSH_SERIAL_TOOL` > 同目录 > `../serial-assistant/scripts/serial_tool.py` 解析 |
|
||||
| `.dsh/skills/serial-boot-test/scripts/verify_log.py` | 对任意日志文件做标记校验(Required/Forbidden/锚点计数/顺序/耗时),可单独用。`--exact` 做**整行 `^…$` 锚定**(子串口径照不出"行还在但行首被吃掉/行内被插字节"那一类损坏)、`--pair` 做跨复位配对、`--allow-residual/--head-char` 服务崩溃注入腿、`--selftest` 跑内置判别用例(**证明这套判据不是空跑**)。四个行级开关(`--exact` / `--pair` / `--allow-residual` / `--head-char`)同时接进了 `run_boot_test.py`,@test 闭环直接可用 |
|
||||
|
||||
> **判据取向(重要,会复发)**:`--exact` 默认**只锚文本、不钉长度**——字节长度属于某一份构建,钉死它会在无辜改动上假红(`@@LEN=<n>` 是显式逃生口,不是默认)。子串 `--required` 不能用于"可能丢行首/被插字节"的行。来龙去脉与固定动作见本仓 `docs/测试说明/启动日志原子性复验流程.md`。
|
||||
> **判据取向(重要,会复发)**:`--exact` 默认**只锚文本、不钉长度**——字节长度属于某一份构建,钉死它会在无辜改动上假红(`@@LEN=<n>` 是显式逃生口,不是默认)。子串 `--required` 不能用于"可能丢行首/被插字节"的行。来龙去脉与固定动作见本仓 `docs/测试说明/专项验证/启动日志原子性复验流程.md`。
|
||||
|
||||
交互式串口操作(open/send/log/wait-idle/status 等)不属于本 skill——
|
||||
**用 `serial-assistant` skill**。
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
run_boot_test.py 在烧录前取基线、启动后只把"基线之后新增"的记录写成临时副本交给本
|
||||
函数(`--selftest-scope this-run`,默认)。**抓取失败/无数据源/无法证明无新增一律由
|
||||
调用方判 FAIL**——旧实现把这些都当"无记录 → PASS",是假绿(详见
|
||||
docs/测试说明/自动化测试流程.md 的自检结果判定节)。
|
||||
docs/测试说明/流程与规范/自动化测试流程.md 的自检结果判定节)。
|
||||
- 启动锚点计数(2026-10-10):`--max-boot-count N`(run_boot_test.py 默认传 1)统计
|
||||
`reset cause:` 锚点出现次数——**0 次** = 采集没从复位开始(标记全中也可能只是上一轮
|
||||
的残留日志);**>N 次** = 板子在采集窗口内自己复位过(IWDG 咬狗 / Fault 后
|
||||
|
||||
@@ -47,7 +47,7 @@ whenToUse: 需要向 STM32 目标烧录 .hex/.bin、只复位重启目标、校
|
||||
被拒,本 skill 会打印 `RESET_NOTE` 并**自动降级**为这条系统复位(仍按降级结果给 rc)。
|
||||
- 探针在位先 `list`;`Programming Complete` 但行为像旧固件 → 先怀疑缺 `-Rst -Run`,
|
||||
再怀疑 hex 没重编(对比 hex 时间戳)。
|
||||
- 完整复位语义/故障排查(本仓库):`docs/测试说明/ST-LINK_CLI_复位使用说明.md`。
|
||||
- 完整复位语义/故障排查(本仓库):`docs/测试说明/测试工具/ST-LINK_CLI_复位使用说明.md`。
|
||||
|
||||
## 与其它 skill 的衔接
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Gitea Actions CI —— STM32F4-Base 持续集成
|
||||
#
|
||||
# 覆盖范围(**只做不依赖硬件的层**,见 docs/测试说明/测试开发标准流程.md §1/§9):
|
||||
# 覆盖范围(**只做不依赖硬件的层**,见 docs/测试说明/流程与规范/测试开发标准流程.md §1/§9):
|
||||
# 静态门禁 static = pre-commit 全部钩子(等价本地 `pre-commit run --all-files`)
|
||||
# + 手动阶段三根(覆盖率总闸 / 全量 cppcheck / test-cppcheck,`--hook-stage manual`;
|
||||
# 它们在 .pre-commit-config.yaml 里带 stages: [manual],提交期不跑,由本 job 强制)
|
||||
|
||||
@@ -241,7 +241,7 @@ repos:
|
||||
# 累计 / 100ms 节流 / tick 回绕)是纯逻辑,板端套件无法穷举边界;本钩子
|
||||
# 用 MSVC 离线编译真实源文件(#include 纳入)并用可观测桩驱动,秒级、零
|
||||
# 硬件、不占 MCU RAM。仅在被测文件或其平台层 / 测试变动时触发。
|
||||
# 详见 docs/测试说明/看门狗单元测试说明.md
|
||||
# 详见 docs/测试说明/单元测试/看门狗单元测试说明.md
|
||||
- id: watchdog-unit-test
|
||||
name: 看门狗判定状态机单测(主机侧)
|
||||
entry: python test/host/watchdog/run_unit_test.py
|
||||
@@ -726,7 +726,7 @@ repos:
|
||||
# 为什么现在才挂:接线前本文件只有 16 个 *-unit-test 钩子,而仓库已有 28 套主机单测——
|
||||
# P1 新增的 12 套不在任何提交钩子里。原先"再加一份全量插桩等于同一件事做两遍"
|
||||
# 这条理由到现在已经**反了**(现状是有一遍没做),所以必须挂;缺口此前如实登记在
|
||||
# docs/测试说明/主机单测覆盖率口径.md §8。
|
||||
# docs/测试说明/单元测试/主机单测覆盖率口径.md §8。
|
||||
# 为什么挂这一根而不是补 12 个 per-module 钩子:本钩子当时跑**全部 28 套**(现值 44 套,台账见
|
||||
# docs/门禁说明/host-unit-tests.md §6 第 4 条),并且守 §5 的
|
||||
# 回退台账(某套被删、或某文件的已覆盖行变少 → [REGRESS] 直接红)。这是 per-module
|
||||
@@ -735,7 +735,7 @@ repos:
|
||||
# 不做 skip。理由:skip 等于造一根会静默失效的门禁(与 pre-commit 4.x 移除 always: true
|
||||
# 是同一类坑);宁可在没装组件的机器上被挡一次、看清 [ENV] 那行提示,也不要一根假绿的闸。
|
||||
# 本机与 CI runner 同一台;实测两份 VS 安装都自带该 exe(口径 §7 第 8 条已按实测更正)。
|
||||
# 口径 / 分母 / 基线 / 盲区详解都在 docs/测试说明/主机单测覆盖率口径.md,本处只留接线事实。
|
||||
# 口径 / 分母 / 基线 / 盲区详解都在 docs/测试说明/单元测试/主机单测覆盖率口径.md,本处只留接线事实。
|
||||
# 触发面**含门禁自身**(.pre-commit-config.yaml):不带自身就等于谁改坏这根闸的 files:
|
||||
# 模式,它就再也不跑且无人察觉(同 lv-conf-sync / bsp-err 的既有做法)。
|
||||
# ⚠ stages: [manual](2026-10-28 用户裁定):本钩子跑光全部 44 套单测(41 套时实测 ~105 s,套件数
|
||||
|
||||
@@ -80,9 +80,9 @@
|
||||
|
||||
- **门禁时机(用户裁定 2026-10-13)**:`@build` / `scripts/ci_local.py` / `check_doc_links.py` **只在准备提交时跑**(用户让 commit 后统一跑一遍),**不是每次中间改动后都跑**——多步改动期间直接改即可,验证集中在提交门禁;`@test` 硬件闭环仍按任务需要跑
|
||||
- `@build` = `& '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py`(仓库根执行)。退出码 **0=PASS / 1=构建失败 / 2=环境错误(UV4/工程/档案)/ 3=用法 / 4=build 锁被占用**;日志 `MDK-ARM/build_log.txt`;换机必设 `DTU_KEIL_UV4` → 细节 **`keil-build` skill** + `docs/环境与部署/本地工具路径环境变量方案.md`
|
||||
- `@test` = `& '.venv\Scripts\python.exe' .dsh\skills\serial-boot-test\scripts\run_boot_test.py`:开串口+清日志 → 烧录(**固件身份戳**保证烧进去的就是这份构建、**回读校验**)→ wait-idle → 采日志 → 标记校验(含启动锚点计数)。退出码 **0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法**;戳提取规则、锚点计数判据与按模块定制标记见 `docs/测试说明/自动化测试流程.md`
|
||||
- `@test` = `& '.venv\Scripts\python.exe' .dsh\skills\serial-boot-test\scripts\run_boot_test.py`:开串口+清日志 → 烧录(**固件身份戳**保证烧进去的就是这份构建、**回读校验**)→ wait-idle → 采日志 → 标记校验(含启动锚点计数)。退出码 **0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法**;戳提取规则、锚点计数判据与按模块定制标记见 `docs/测试说明/流程与规范/自动化测试流程.md`
|
||||
- Forbidden 标记含 `[ERR]`:**四个 Fault 的崩溃日志都以 `[ERR]` 开头 → 出现 Fault 即本次不通过**(刻意)
|
||||
- **烧录必须 `-Rst -Run`**(`stlink-flash` skill 的 `flash`):裸 `-P` 会报 `Programming Complete`,但目标核处于死循环/异常时写入并不落地("反复重下载、芯片一直是旧镜像、二分法失效"的根因)。**烧后必须回读校验**(`stlink_flash.py cmp` = `-CmpFile`,`No difference found` 才算真正写入);⚠ `-CmpFile` 连接时会**复位目标** → 必须排在**采日志之后** → `docs/测试说明/ST-LINK_CLI_复位使用说明.md`
|
||||
- **烧录必须 `-Rst -Run`**(`stlink-flash` skill 的 `flash`):裸 `-P` 会报 `Programming Complete`,但目标核处于死循环/异常时写入并不落地("反复重下载、芯片一直是旧镜像、二分法失效"的根因)。**烧后必须回读校验**(`stlink_flash.py cmp` = `-CmpFile`,`No difference found` 才算真正写入);⚠ `-CmpFile` 连接时会**复位目标** → 必须排在**采日志之后** → `docs/测试说明/测试工具/ST-LINK_CLI_复位使用说明.md`
|
||||
- ⚠️ 旧绝对路径 `D:\Code\DTU 程序\...` 出现即失效(仓库已搬迁),一律改用仓库相对路径
|
||||
|
||||
## Python 环境
|
||||
@@ -148,7 +148,7 @@
|
||||
- **单连接 socket 的断开语义**:EOF 时 net 层已 `auto_relisten`,应用层**不得**在 EOF 时 `net_close` 该 fd(会连监听一起毁掉 → 端口"连接被拒");仅当数据 fd ≠ 监听 fd(模拟器多连接后端)时才关
|
||||
- 网口配置:`/config.ini` [network] 段(工厂默认 192.168.1.100/24、gw .1;MAC 全零 = 芯片内置;UI 保存立即生效;**旧档 `/cfg/netcfg.bin` 迁移已于 2026-10-10 删除**,旧档存在则被忽略);同文件 **[ftp] 段 = FTP 鉴权**(`user` / `pwd_hash` = SHA-256(user‖password) / `write`,出厂默认 admin/admin,默认口令在用有启动告警;连续 5 次失败锁 60 s)→ `docs/子系统设计/网络配置说明.md`
|
||||
- **新 .c 文件必须手动注册到两处**才能双端编译:`MDK-ARM/STM32F407-Demo.uvprojx` + `simulator/CMakeLists.txt`(用 `new-source-file` skill);⚠ **新文件落在还没有的新目录,还要把该目录加进 `uvprojx` 的 `<IncludePath>`**——否则报错落在**消费者 TU** 上(`cannot open source input file`),极易误判
|
||||
- 测试构建:`test/board/test_config.h` 的 `TEST_SUITE_CH395F/STORAGE/GD5F/RTC` **互斥**(一次只能一个,`#error`);全部注释 = 产品构建,**受 `test-suite-switch` 钩子门禁**;`ENABLE_DESTRUCTIVE_TESTS` **默认关闭**(关闭时套件只读模式,可随时在在用设备上跑)——⚠ 跑一轮破坏性 GD5F 即让 dhara 多记一个坏块且该计数持久化,普通恢复清不掉 → `docs/测试说明/存储维护与容量恢复.md`;板级套件运行用 **`board-test-suite` skill**
|
||||
- 测试构建:`test/board/test_config.h` 的 `TEST_SUITE_CH395F/STORAGE/GD5F/RTC` **互斥**(一次只能一个,`#error`);全部注释 = 产品构建,**受 `test-suite-switch` 钩子门禁**;`ENABLE_DESTRUCTIVE_TESTS` **默认关闭**(关闭时套件只读模式,可随时在在用设备上跑)——⚠ 跑一轮破坏性 GD5F 即让 dhara 多记一个坏块且该计数持久化,普通恢复清不掉 → `docs/测试说明/专项验证/存储维护与容量恢复.md`;板级套件运行用 **`board-test-suite` skill**
|
||||
- **改驱动前先读对应 `docs/问题记录/*_Trap_Records.md`**(CH395F / GD5F2GQ5UE / SD2506);各模块测试指南见 `docs/测试说明/`
|
||||
- **改 UI / 绘制缓冲前读两条实证坑**(I1 palette 头越界、白底白字整屏纯白)→ `docs/UI设计/UI_设计架构.md` §1.4 第 8/9 条,**`ui-verify` skill** 亦载
|
||||
|
||||
@@ -180,9 +180,9 @@
|
||||
| **还想给东西发编号?**(**2026-10-29 用户裁定:一律不发**,写语义短语;§4.1 五个存量族的既有号只读引用——「停发」不等于「暂缓」,也不等于「可以清号」)/ 编号门禁现状(**两道都已退役**:全库八项校验 2026-10-28、只查新增行 2026-10-29;此后无机器面,只靠 §1 与评审) | `docs/编号规范.md`(§1 默认答案、§4.1 存量族〔穷举〕与『已停发』栏、§8.5 手工普查与恢复机器面) |
|
||||
| 提交门禁通用机制(阶段 / stash 陷阱 / 触发面 / 增量拦截三段式) | `docs/代码规范/pre-commit使用说明.md` §2 |
|
||||
| 代码规范 V1.0 / cppcheck 口径 | `docs/代码规范/嵌入式C语言代码规范_V1.0.md`、`cppcheck使用说明.md` |
|
||||
| 自动化测试 / 实机测试 / 板级套件 | `docs/测试说明/自动化测试流程.md`、`实机测试实施指南.md`、`board-test-suite` skill |
|
||||
| 烧录与复位语义 | `docs/测试说明/ST-LINK_CLI_复位使用说明.md` |
|
||||
| 串口助手 | **`serial-assistant` skill**(命令/判据/陷阱,用到自动加载)、`docs/测试说明/串口助手使用指南.md`、`串口助手设计说明.md` |
|
||||
| 自动化测试 / 实机测试 / 板级套件 | `docs/测试说明/流程与规范/自动化测试流程.md`、`实机测试实施指南.md`、`board-test-suite` skill |
|
||||
| 烧录与复位语义 | `docs/测试说明/测试工具/ST-LINK_CLI_复位使用说明.md` |
|
||||
| 串口助手 | **`serial-assistant` skill**(命令/判据/陷阱,用到自动加载)、`docs/测试说明/测试工具/串口助手使用指南.md`、`串口助手设计说明.md` |
|
||||
| UI 架构 / 模拟器 / UI 自动化回归 | **`lvgl-simulator` skill**(构建/自检/报错速查,用到自动加载)、`docs/UI设计/UI_设计架构.md`、`LVGL模拟器部署与使用说明.md`、`UI_自动化测试流程.md`;UI 改动回归走 **`ui-verify` skill** |
|
||||
| 待办与审计发现登记簿 | `docs/任务规划/README.md` |
|
||||
| 多任务并行开发(开空间 / 合并回收 / 台架与构建排队);**DSH worktree 插件的仓内树怎么接上**(`.dsh-worktrees/` 缺 `.venv`、`plugin adopt`、锁归属 `pw:<name>`) | **`task-worktree` skill**(`@task`,用到自动加载;插件桥 → 其 F 节)、`docs/环境与部署/并行任务工作树方案.md` §3.4 |
|
||||
|
||||
+1
-1
@@ -261,5 +261,5 @@ ADC 引脚电压 V)+ `adc_health_rail_watch()` ×9(「采样通道自检」
|
||||
- **故障录波**(数据面 / 段格式 / 现场回放契约):docs/子系统设计/故障录波设计说明.md §6.2 是段文件
|
||||
字节布局的属主,同一篇的 docs/子系统设计/故障录波设计说明.md §6.3 是字段口径裁定——两节合起来是板端
|
||||
编码器与 PC 读段脚本两份独立实现的共同依据;卡片判据与顺序 → docs/任务规划/故障录波.md §2
|
||||
- 相量层 / ADC 输入层单测细则:`docs/测试说明/相量层单元测试说明.md`、`docs/测试说明/ADC输入层单元测试说明.md`
|
||||
- 相量层 / ADC 输入层单测细则:`docs/测试说明/单元测试/相量层单元测试说明.md`、`docs/测试说明/单元测试/ADC输入层单元测试说明.md`
|
||||
- RAM 与栈台账:`docs/内存管理/RAM使用分析与优化方案.md`
|
||||
|
||||
+1
-1
@@ -622,7 +622,7 @@ void adc_task_func(void *arg) {
|
||||
|
||||
/* 4) 首拍相量上报:攒满一周波(20 ms)后立即落一次,作为 全周傅氏相量链路的开机证据。
|
||||
* 不依赖 10 s 心跳 → 台架 @test 的 settle 窗口内即可见(否则会被静默判据
|
||||
* 截断,见 docs/测试说明/自动化测试流程.md 的 settle 口径)。 */
|
||||
* 截断,见 docs/测试说明/流程与规范/自动化测试流程.md 的 settle 口径)。 */
|
||||
if ((first_phasor_logged == 0u) && (dbg_console_writer_ready() != 0u)) {
|
||||
phasor_t p;
|
||||
|
||||
|
||||
+2
-2
@@ -30,10 +30,10 @@
|
||||
- **单一喂狗者**:`defaultTask` 每 100 ms 抽样判定,仅当位图等于必需掩码时才喂狗
|
||||
- **硬件访问收敛**:`IWDG` 寄存器与 `HAL_GetTick()` 经 `wd_platform_*` 弱钩子访问
|
||||
(声明在 `task_watchdog.h` 末段),MCU 端为 `__weak` 默认实现,主机侧单测以同名强符号覆盖 → 可在 PC 上跑纯逻辑回归
|
||||
- 设计详见 `docs/子系统设计/看门狗设计说明.md`;单测见 `docs/测试说明/看门狗单元测试说明.md`
|
||||
- 设计详见 `docs/子系统设计/看门狗设计说明.md`;单测见 `docs/测试说明/单元测试/看门狗单元测试说明.md`
|
||||
|
||||
## 相关文档
|
||||
|
||||
- `docs/子系统设计/系统墙钟时间维护说明.md`
|
||||
- `docs/子系统设计/看门狗设计说明.md`
|
||||
- `docs/测试说明/看门狗单元测试说明.md`
|
||||
- `docs/测试说明/单元测试/看门狗单元测试说明.md`
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
* 三个 __weak 钩子(wd_platform_feed / _start / _tick_ms);MCU 端默认实现见
|
||||
* 文件末尾,行为与重构前逐字一致。判定状态机因此成为纯逻辑,主机侧单测
|
||||
* (test/host/watchdog/)以强符号覆盖这三个钩子后即可离线穷举验证。
|
||||
* 详见 docs/测试说明/看门狗单元测试说明.md。
|
||||
* 详见 docs/测试说明/单元测试/看门狗单元测试说明.md。
|
||||
*/
|
||||
|
||||
#include "task_watchdog.h"
|
||||
@@ -562,7 +562,7 @@ void task_wd_poll(void) {
|
||||
* **直接喂狗**。若每轮 100ms 都写,等于在"停喂"窗口里持续喂狗 →
|
||||
* IWDG 永不溢出 → 停喂语义被证据机制自身抵消(2026-10-03 台架 V2
|
||||
* 实测:stall 已声明、miss 累至 1157≈115s 仍不复位,见
|
||||
* docs/测试说明/实机测试实施指南.md §4)。写一次即可留证,此后不再
|
||||
* docs/测试说明/板级测试/实机测试实施指南.md §4)。写一次即可留证,此后不再
|
||||
* 触碰 NAND,恢复"停喂 → IWDG 溢出复位"(§5.3 的权威归因)。 */
|
||||
if (s_stall_evidenced == 0u) {
|
||||
s_stall_evidenced = 1u;
|
||||
@@ -604,7 +604,7 @@ uint32_t task_wd_is_armed(void) {
|
||||
* 以下三个 __weak 为 MCU 端默认实现,行为与重构前逐字一致。
|
||||
* 主机侧单测提供同名强符号覆盖(链接器优先取强符号)以实现离线可观测。
|
||||
* 声明见 task_watchdog.h 末段"平台后端(内部)";详见
|
||||
* docs/测试说明/看门狗单元测试说明.md。
|
||||
* docs/测试说明/单元测试/看门狗单元测试说明.md。
|
||||
*
|
||||
* 主机侧单测(同编译单元 #include 本文件)需回避这组默认定义与自身桩重名,
|
||||
* 故由 TASK_WATCHDOG_UNIT_TEST 守卫:该宏下不编入默认实现,仅留桩。
|
||||
|
||||
@@ -169,7 +169,7 @@ void task_wd_tick_probe(void);
|
||||
* ============================ 平台后端(内部) ============================
|
||||
* 把判定状态机中的硬件访问收敛到三个薄钩子,使"取走清零 / 掩码判定 / 缺失
|
||||
* 累计 / 节流"成为纯逻辑,可在主机侧用桩替换后离线穷举验证
|
||||
* (见 test/host/watchdog/ 与 docs/测试说明/看门狗单元测试说明.md)。
|
||||
* (见 test/host/watchdog/ 与 docs/测试说明/单元测试/看门狗单元测试说明.md)。
|
||||
*
|
||||
* 与 App/cfg/cfg_file_store.h 的"共享核心 + 平台后端"同款做法:
|
||||
* - 三者由 task_watchdog.c 以 __weak 提供 MCU 默认实现(读写 IWDG 寄存器 /
|
||||
|
||||
@@ -29,6 +29,6 @@
|
||||
|
||||
## 相关文档
|
||||
|
||||
- 测试指南:`docs/测试说明/CH395F_Test_Guide.md`
|
||||
- 测试指南:`docs/测试说明/板级测试/CH395F_Test_Guide.md`
|
||||
- 上层抽象:`../NET/README.md`
|
||||
- 台架探针:`MDK-ARM/tcp_reconnect_probe.py`、`test/host/ftp_abort_probe.py`
|
||||
|
||||
@@ -42,5 +42,5 @@ GD5F2GQ5UE 芯片
|
||||
## 相关文档
|
||||
|
||||
- 存储架构:`docs/架构设计/STM32F4-Base存储架构说明.md`
|
||||
- 测试指南:`docs/测试说明/GD5F2GQ5UE_Test_Guide.md`
|
||||
- 容量恢复:`docs/测试说明/存储维护与容量恢复.md`
|
||||
- 测试指南:`docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md`
|
||||
- 容量恢复:`docs/测试说明/专项验证/存储维护与容量恢复.md`
|
||||
|
||||
@@ -40,7 +40,7 @@ int nand_ftl_init(void);
|
||||
* 限定条件:只允许走显式命令或恢复流程调用;不得因"某次读写失败"自动调用
|
||||
* 函数说明:新卷从空树写起,避免旧 journal 残留与新卷共存(结构卫生)。
|
||||
* 容量恢复动作的区分(A 清日志 / B 重挂载 / C 全片擦除 / D 残留清理)
|
||||
* → ../测试说明/存储维护与容量恢复.md。
|
||||
* → docs/测试说明/专项验证/存储维护与容量恢复.md。
|
||||
*/
|
||||
int nand_ftl_format(void);
|
||||
|
||||
|
||||
@@ -71,4 +71,4 @@
|
||||
- 内部调用关系:`docs/网络/BSD_Socket_API_函数调用关系.md`
|
||||
- 架构设计:`docs/网络/Net层阻塞模型架构设计.md`(阻塞等待 / pending 请求模型)
|
||||
- ACCEPT 挂起化不实施的判据:`docs/网络/Net层阻塞模型架构设计.md` §10
|
||||
- 测试:`docs/测试说明/CH395F_Test_Guide.md`、`docs/测试说明/FTP_Test_Guide.md`
|
||||
- 测试:`docs/测试说明/板级测试/CH395F_Test_Guide.md`、`docs/测试说明/板级测试/FTP_Test_Guide.md`
|
||||
|
||||
@@ -36,6 +36,6 @@ lftpd(本目录)
|
||||
|
||||
## 相关文档
|
||||
|
||||
- 测试指南:`docs/测试说明/FTP_Test_Guide.md`
|
||||
- 测试指南:`docs/测试说明/板级测试/FTP_Test_Guide.md`
|
||||
- 台架探针:`test/host/ftp_abort_probe.py`、`MDK-ARM/ftp_freeze_probe.py`
|
||||
- 内存优化:`docs/内存管理/RAM使用分析与优化方案.md` §4.1.4
|
||||
|
||||
@@ -44,4 +44,4 @@
|
||||
|
||||
- 架构全景:`docs/架构设计/项目架构总览.md`
|
||||
- 存储栈:`docs/架构设计/STM32F4-Base存储架构说明.md`
|
||||
- 测试指南:`docs/测试说明/*_Test_Guide.md`
|
||||
- 测试指南:`docs/测试说明/板级测试/*_Test_Guide.md`
|
||||
|
||||
@@ -24,5 +24,5 @@
|
||||
## 相关文档
|
||||
|
||||
- 墙钟维护:`docs/子系统设计/系统墙钟时间维护说明.md`
|
||||
- 测试指南:`docs/测试说明/SD2506_Test_Guide.md`
|
||||
- 测试指南:`docs/测试说明/板级测试/SD2506_Test_Guide.md`
|
||||
- 陷阱台账:`docs/问题记录/SD2506_Trap_Records.md`
|
||||
|
||||
@@ -130,7 +130,7 @@ typedef int bsp_err_t;
|
||||
* 丢弃 HAL_SPI_Transmit/Receive 返回值、以及"未初始化局部量直接进 P_FAIL 判定"**一条不报**
|
||||
* (它假定被调函数会写出参,而失败路径根本不写)。所以"丢弃底层传输的返回值"今天没有任何
|
||||
* 工具会响,只能靠脚本 + 书写约定;consume-result 上线当天就照出 37 处存量丢弃,其中一处是真窟窿:
|
||||
* bbt_rebuild 的 ECC 重开被丢弃(详见 ../测试说明/存储维护与容量恢复.md §4.3)。
|
||||
* bbt_rebuild 的 ECC 重开被丢弃(详见 docs/测试说明/专项验证/存储维护与容量恢复.md §4.3)。
|
||||
* 5. 重试由调用方决定:必须有上限、必须喂看门狗、不得跨越就绪屏障盲目等。本头文件
|
||||
* 不提供 retry helper——一个通用 while 重试包装太容易被拿去包住无限等待;每个日志
|
||||
* 调用点内联约 216 B 栈的教训在前,栈预算不欢迎「顺手加一层」。
|
||||
|
||||
+2
-2
@@ -60,6 +60,6 @@
|
||||
|
||||
## 相关文档
|
||||
|
||||
- 烧录/复位:`docs/测试说明/ST-LINK_CLI_复位使用说明.md`
|
||||
- 烧录/复位:`docs/测试说明/测试工具/ST-LINK_CLI_复位使用说明.md`
|
||||
- 构建与验证:根 `AGENTS.md`「构建与验证」章
|
||||
- 测试流程:`docs/测试说明/自动化测试流程.md`
|
||||
- 测试流程:`docs/测试说明/流程与规范/自动化测试流程.md`
|
||||
|
||||
@@ -332,7 +332,7 @@ UI 改动回归门禁(菜单像素回归 + 内容页黄金参考 + 池水位
|
||||
通过仓库内置 Python 串口助手(`.dsh/skills/serial-assistant/`)自主读取 USART1 串口打印:
|
||||
|
||||
- 端口配置:`.serialtest/config.json`(单一配置源)
|
||||
- 用法详见 `docs/测试说明/串口助手使用指南.md`,设计见 `docs/测试说明/串口助手设计说明.md`
|
||||
- 用法详见 `docs/测试说明/测试工具/串口助手使用指南.md`,设计见 `docs/测试说明/测试工具/串口助手设计说明.md`
|
||||
|
||||
## 开发规范
|
||||
|
||||
@@ -432,9 +432,9 @@ pre-commit run --all-files
|
||||
| `docs/代码规范/嵌入式C语言代码规范_V1.0.md` | C 语言代码规范 |
|
||||
| `docs/代码规范/pre-commit使用说明.md` | 自动化代码审查部署与使用 |
|
||||
| `docs/代码规范/cppcheck使用说明.md` | cppcheck 规则、配置与误报抑制 |
|
||||
| `docs/测试说明/自动化测试流程.md` | 构建 → 烧录 → 串口校验闭环 |
|
||||
| `docs/测试说明/流程与规范/自动化测试流程.md` | 构建 → 烧录 → 串口校验闭环 |
|
||||
| `docs/测试说明/` | 各模块测试指南(CH395F / NAND / FTP / RTC / 串口调试) |
|
||||
| `docs/测试说明/测试开发标准流程.md` / `docs/测试说明/测试文档模板规范.md` | 测试开发流程与文档模板 |
|
||||
| `docs/测试说明/流程与规范/测试开发标准流程.md` / `docs/测试说明/流程与规范/测试文档模板规范.md` | 测试开发流程与文档模板 |
|
||||
| `docs/问题记录/` | 已知陷阱与解决方案(CH395F / NAND / RTC) |
|
||||
| `docs/芯片手册/` | 硬件数据手册 |
|
||||
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@
|
||||
|
||||
## 相关文档
|
||||
|
||||
- 测试分层与门禁决策(静态门禁~人工目检各层由谁把关):[`../测试说明/测试开发标准流程.md`](../测试说明/测试开发标准流程.md)
|
||||
- 测试分层与门禁决策(静态门禁~人工目检各层由谁把关):[`../测试说明/流程与规范/测试开发标准流程.md`](../测试说明/流程与规范/测试开发标准流程.md)
|
||||
- workflow 本体:[`../../.gitea/workflows/ci.yml`](../../.gitea/workflows/ci.yml)
|
||||
- 本地等价脚本:[`../../scripts/ci_local.py`](../../scripts/ci_local.py)
|
||||
- runner 机器的工具链环境要求:[`../环境与部署/项目部署环境要求.md`](../环境与部署/项目部署环境要求.md)
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@
|
||||
> (与 CI 同一套判定),**不依赖远程 CI 是否在线**——runner 掉线不影响本地门禁。
|
||||
|
||||
> **适用**:为 STM32F4-Base 部署 / 排障 CI(`.gitea/workflows/ci.yml`,静态门禁 + 主机侧纯逻辑单测)。
|
||||
> **前置阅读**:[docs/测试说明/测试开发标准流程.md §9](../测试说明/测试开发标准流程.md)(CI 覆盖边界与判定细节)、
|
||||
> **前置阅读**:[docs/测试说明/流程与规范/测试开发标准流程.md §9](../测试说明/流程与规范/测试开发标准流程.md)(CI 覆盖边界与判定细节)、
|
||||
> [docs/环境与部署/项目部署环境要求.md §2.11](../环境与部署/项目部署环境要求.md)(runner 环境要求)。
|
||||
> 本文只讲**怎么配**,不重复"为什么这么设计"。
|
||||
> 本篇由原两篇 CI 指南 `CI配置指南.md` 与 `Gitea_Runner部署指南.md`(原位于「环境与部署」目录,
|
||||
@@ -104,7 +104,7 @@
|
||||
|
||||
### 0.2 部署前置清单(需人工确认)
|
||||
|
||||
> 2026-10-12 自 `docs/测试说明/测试开发标准流程.md` §9.4 并入——这几项是"CI 能不能跑起来"的前提,
|
||||
> 2026-10-12 自 `docs/测试说明/流程与规范/测试开发标准流程.md` §9.4 并入——这几项是"CI 能不能跑起来"的前提,
|
||||
> 属于机器侧知识,故与本文其余内容放在一起,不再散在测试流程文档里。
|
||||
|
||||
| 项 | 要求 |
|
||||
@@ -984,7 +984,7 @@ github.com 会在 checkout 步骤卡住/失败。三种处置:
|
||||
故 pipeline 前后需 `Save/Restore` 该偏好为 `Continue`(与"环境自检"步骤同法)。
|
||||
`$LASTEXITCODE` 在 `Tee-Object` 之后**仍保留** native 退出码(实测),可直接用于判定。
|
||||
|
||||
### 5.5 两个 job 的步骤要点(2026-10-12 自 docs/测试说明/测试开发标准流程.md §9.2 并入)
|
||||
### 5.5 两个 job 的步骤要点(2026-10-12 自 docs/测试说明/流程与规范/测试开发标准流程.md §9.2 并入)
|
||||
|
||||
| job | `runs-on` | 步骤要点 |
|
||||
|---|---|---|
|
||||
|
||||
+47
-31
@@ -17,7 +17,7 @@ docs/
|
||||
├── 子系统设计/ 各功能子系统的设计说明
|
||||
├── 算法/ 傅氏算法与继电保护算法专题
|
||||
├── 网络/ BSD Socket API 使用与内部实现
|
||||
├── 测试说明/ 测试流程、模块测试指南、工具说明
|
||||
├── 测试说明/ 测试流程与规范 · 单元测试 · 板级测试 · 专项验证 · 测试工具 · 测试数据(六个子目录,导航 `测试说明/README.md`)
|
||||
├── 代码规范/ 编码规范与静态检查门禁
|
||||
├── 文档规范.md 本文档体系的规范(命名/链接/门禁/结构)
|
||||
├── 内存管理/ RAM 预算、分配策略与优化调研
|
||||
@@ -46,7 +46,7 @@ docs/
|
||||
| 3 | [`项目启动顺序管理.md`](架构设计/项目启动顺序管理.md) | Event Flags 就绪屏障(取代魔法延时)的任务启动模型 |
|
||||
| 4 | [`项目部署环境要求.md`](环境与部署/项目部署环境要求.md) | 开发机/目标板/现场部署的完整环境核对清单 |
|
||||
| 5 | [`项目部署环境要求.md`](环境与部署/项目部署环境要求.md) → 构建 | 跑通 `@build` / `@test`(见根 `AGENTS.md`) |
|
||||
| 6 | [`测试开发标准流程.md`](测试说明/测试开发标准流程.md) | 测试分层 静态门禁~保护判据与门禁决策表 |
|
||||
| 6 | [`测试开发标准流程.md`](测试说明/流程与规范/测试开发标准流程.md) | 测试分层 静态门禁~保护判据与门禁决策表 |
|
||||
| 7 | [`嵌入式C语言代码规范_V1.0.md`](代码规范/嵌入式C语言代码规范_V1.0.md) | 命名/格式/注释规范(提交门禁强制) |
|
||||
| 8 | [`项目架构总览.md`](架构设计/项目架构总览.md) → 按需 | 进入具体子系统设计文档 |
|
||||
|
||||
@@ -114,50 +114,66 @@ docs/
|
||||
|
||||
## 6. 测试说明
|
||||
|
||||
**总流程与规范**
|
||||
> 本目录分六个子目录(**归层判据与本目录文件清单 → [`测试说明/README.md`](测试说明/README.md)**);
|
||||
> 下面每个分组与一个子目录一一对应。
|
||||
|
||||
**流程与规范/**(测试开发总流程、门禁决策表、测试文档模板)
|
||||
|
||||
| 文档 | 内容 |
|
||||
|---|---|
|
||||
| [`测试开发标准流程.md`](测试说明/测试开发标准流程.md) | 测试开发总流程:规划→板端套件→主机工具→门禁→沉淀;门禁决策表 |
|
||||
| [`自动化测试流程.md`](测试说明/自动化测试流程.md) | `@test` 闭环细节:命令 / 串口标记 / 失败模式 |
|
||||
| [`测试文档模板规范.md`](测试说明/测试文档模板规范.md) | 测试文档模板与命名规则(TM / TC / DP) |
|
||||
| [`链路延迟测试说明.md`](测试说明/链路延迟测试说明.md) | 网络链路时延分段定义、判定基线、执行流程 |
|
||||
| [`模拟器差距清单.md`](测试说明/模拟器差距清单.md) | **PC 模拟器 vs 真机差距登记册**(保护判据门禁可信度依据;改动涉及网络/日志/硬件层前必查 §3 决策规则) |
|
||||
| [`实机测试实施指南.md`](测试说明/实机测试实施指南.md) | **上板(真机)测试执行流程**(按顺序:环境预检 → `@test`+自检判定 → IWDG 注入/长跑 → 堆告警 → GD5F 错误通道 → 网络基线 → 工程卫生;每步含判据/命令/状态);已完成事项证据去向见 §10 |
|
||||
| [`ADC前端注入验证流程.md`](测试说明/ADC前端注入验证流程.md) | **ADC 前端与两片转换器的台架注入验证**(已知电压注入验证的执行侧,实测证据 → `docs/硬件平台/ADC通道映射说明.md` §8.1):注入点清单 / 期望码值表 / 零点·线性·映射·极性·节奏五步(每步自带现场记录表,边做边填);**不需示波器与信号源**,一块万用表即可 |
|
||||
| [`测试开发标准流程.md`](测试说明/流程与规范/测试开发标准流程.md) | 测试开发总流程:规划→板端套件→主机工具→门禁→沉淀;门禁决策表 |
|
||||
| [`自动化测试流程.md`](测试说明/流程与规范/自动化测试流程.md) | `@test` 闭环细节:命令 / 串口标记 / 失败模式 |
|
||||
| [`测试文档模板规范.md`](测试说明/流程与规范/测试文档模板规范.md) | 测试文档模板与命名规则(TM / TC / DP) |
|
||||
|
||||
**主机侧单元测试(主机侧纯逻辑单测)**
|
||||
**单元测试/**(主机侧纯逻辑单测说明与覆盖率口径)
|
||||
|
||||
| 文档 | 内容 |
|
||||
|---|---|
|
||||
| [`看门狗单元测试说明.md`](测试说明/看门狗单元测试说明.md) | Task Watchdog 判定状态机(位图 / 掩码 / 节流 / tick 回绕),39 用例 |
|
||||
| [`系统时钟单元测试说明.md`](测试说明/系统时钟单元测试说明.md) | sys_clock 时间换算 / 星期 Zeller / 30 天惰性再基准化 / RTC 故障降级,100 断言点 |
|
||||
| [`开机账本单元测试说明.md`](测试说明/开机账本单元测试说明.md) | boot_stats 上电次数四态(不可信 / 首次启用 / 延续 / 电池域掉过电)/ SRAM 记录校验与格式版本 / I2C 失败分支 / 复位原因优先级链,21 断言点 |
|
||||
| [`配置文件单元测试说明.md`](测试说明/配置文件单元测试说明.md) | cfg_file INI 解析 / 值编解码 / load-save-poll 契约 / 超长守卫,149 断言点(含抓出的外科手术保存死码 P0) |
|
||||
| [`ADC输入层单元测试说明.md`](测试说明/ADC输入层单元测试说明.md) | adc_input 语义通道映射 / ADC1 顺序扫描(**Rank↔通道判据**)/ poll 契约 / HAL 故障路径,70 用例 |
|
||||
| [`相量层单元测试说明.md`](测试说明/相量层单元测试说明.md) | phasor 全周傅氏系数表 / 幅值·相位 / 谐波抑制与提取 / 频偏 / 采样环 / 双区交换,57 用例 |
|
||||
| [`卷锁单元测试说明.md`](测试说明/卷锁单元测试说明.md) | vol_lock 创建 / 获取 / 释放契约(**fail-open 不变量**:创建失败仍返回 1 且零阻塞)/ 幂等 / 超时透传,33 断言点 |
|
||||
| [`时间同步单元测试说明.md`](测试说明/时间同步单元测试说明.md) | time_sync 分片喂狗延时 / 监听退避 / 时间包重组 / 任务主循环(探针窗口心跳缺口的全部逻辑贡献者),80 断言点 |
|
||||
| [`主机单测覆盖率口径.md`](测试说明/主机单测覆盖率口径.md) | **跨全部 16 套 主机侧纯逻辑单测的覆盖率**:`scripts/check_test_coverage.py` 用法 / 统计面与生成物例外 / 基线增量门禁(只拦回退)/ **为什么本机拿不到分支覆盖** / 九条限制与盲区 / 未挂 pre-commit 的三条理由与待粘 YAML |
|
||||
| [`看门狗单元测试说明.md`](测试说明/单元测试/看门狗单元测试说明.md) | Task Watchdog 判定状态机(位图 / 掩码 / 节流 / tick 回绕),39 用例 |
|
||||
| [`系统时钟单元测试说明.md`](测试说明/单元测试/系统时钟单元测试说明.md) | sys_clock 时间换算 / 星期 Zeller / 30 天惰性再基准化 / RTC 故障降级,100 断言点 |
|
||||
| [`开机账本单元测试说明.md`](测试说明/单元测试/开机账本单元测试说明.md) | boot_stats 上电次数四态(不可信 / 首次启用 / 延续 / 电池域掉过电)/ SRAM 记录校验与格式版本 / I2C 失败分支 / 复位原因优先级链,21 断言点 |
|
||||
| [`配置文件单元测试说明.md`](测试说明/单元测试/配置文件单元测试说明.md) | cfg_file INI 解析 / 值编解码 / load-save-poll 契约 / 超长守卫,149 断言点(含抓出的外科手术保存死码 P0) |
|
||||
| [`ADC输入层单元测试说明.md`](测试说明/单元测试/ADC输入层单元测试说明.md) | adc_input 语义通道映射 / ADC1 顺序扫描(**Rank↔通道判据**)/ poll 契约 / HAL 故障路径,70 用例 |
|
||||
| [`相量层单元测试说明.md`](测试说明/单元测试/相量层单元测试说明.md) | phasor 全周傅氏系数表 / 幅值·相位 / 谐波抑制与提取 / 频偏 / 采样环 / 双区交换,57 用例 |
|
||||
| [`卷锁单元测试说明.md`](测试说明/单元测试/卷锁单元测试说明.md) | vol_lock 创建 / 获取 / 释放契约(**fail-open 不变量**:创建失败仍返回 1 且零阻塞)/ 幂等 / 超时透传,33 断言点 |
|
||||
| [`时间同步单元测试说明.md`](测试说明/单元测试/时间同步单元测试说明.md) | time_sync 分片喂狗延时 / 监听退避 / 时间包重组 / 任务主循环(探针窗口心跳缺口的全部逻辑贡献者),80 断言点 |
|
||||
| [`主机单测覆盖率口径.md`](测试说明/单元测试/主机单测覆盖率口径.md) | **跨全部 16 套 主机侧纯逻辑单测的覆盖率**:`scripts/check_test_coverage.py` 用法 / 统计面与生成物例外 / 基线增量门禁(只拦回退)/ **为什么本机拿不到分支覆盖** / 九条限制与盲区 / 未挂 pre-commit 的三条理由与待粘 YAML |
|
||||
|
||||
**模块测试指南**(动手写测试前先读)
|
||||
**板级测试/**(上板测试:模块测试指南 + 实机实施流程;动手写测试前先读)
|
||||
|
||||
| 文档 | 内容 |
|
||||
|---|---|
|
||||
| [`CH395F_Test_Guide.md`](测试说明/CH395F_Test_Guide.md) | CH395F 以太网控制器(硬件层 Phase 1~5 / NET 层 Phase 6~11) |
|
||||
| [`GD5F2GQ5UE_Test_Guide.md`](测试说明/GD5F2GQ5UE_Test_Guide.md) | GD5F2GQ5UE SPI NAND 存储测试 |
|
||||
| [`SD2506_Test_Guide.md`](测试说明/SD2506_Test_Guide.md) | SD2506 RTC 测试 |
|
||||
| [`FTP_Test_Guide.md`](测试说明/FTP_Test_Guide.md) | FTP 服务测试 |
|
||||
| [`CH395F_Test_Guide.md`](测试说明/板级测试/CH395F_Test_Guide.md) | CH395F 以太网控制器(硬件层 Phase 1~5 / NET 层 Phase 6~11) |
|
||||
| [`GD5F2GQ5UE_Test_Guide.md`](测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md) | GD5F2GQ5UE SPI NAND 存储测试 |
|
||||
| [`SD2506_Test_Guide.md`](测试说明/板级测试/SD2506_Test_Guide.md) | SD2506 RTC 测试 |
|
||||
| [`FTP_Test_Guide.md`](测试说明/板级测试/FTP_Test_Guide.md) | FTP 服务测试 |
|
||||
| [`实机测试实施指南.md`](测试说明/板级测试/实机测试实施指南.md) | **上板(真机)测试执行流程**(按顺序:环境预检 → `@test`+自检判定 → IWDG 注入/长跑 → 堆告警 → GD5F 错误通道 → 网络基线 → 工程卫生;每步含判据/命令/状态);已完成事项证据去向见 §10 |
|
||||
|
||||
**工具与运维**
|
||||
**专项验证/**(针对一个缺陷或一次复验的台架专项流程;做完即定稿)
|
||||
|
||||
| 文档 | 内容 |
|
||||
|---|---|
|
||||
| [`串口助手使用指南.md`](测试说明/串口助手使用指南.md) | 串口助手命令用法 / 工作流 / 排障 |
|
||||
| [`串口助手设计说明.md`](测试说明/串口助手设计说明.md) | 串口助手契约 / daemon 行为 / 陷阱 |
|
||||
| [`ST-LINK_CLI_复位使用说明.md`](测试说明/ST-LINK_CLI_复位使用说明.md) | 烧录 / 复位 / 回读校验(`ST-LINK_CLI` 完整用法) |
|
||||
| [`存储维护与容量恢复.md`](测试说明/存储维护与容量恢复.md) | 全片擦除恢复 dhara 坏块记账 / 容量恢复 |
|
||||
| [`m2_data/README.md`](测试说明/m2_data/README.md) · `m3_data/` | 链路时延测试采集数据(JSON 原始记录) |
|
||||
| [`ADC前端注入验证流程.md`](测试说明/专项验证/ADC前端注入验证流程.md) | **ADC 前端与两片转换器的台架注入验证**(已知电压注入验证的执行侧,实测证据 → `docs/硬件平台/ADC通道映射说明.md` §8.1):注入点清单 / 期望码值表 / 零点·线性·映射·极性·节奏五步(每步自带现场记录表,边做边填);**不需示波器与信号源**,一块万用表即可 |
|
||||
| [`启动日志原子性复验流程.md`](测试说明/专项验证/启动日志原子性复验流程.md) | **控制台整行独占 / 崩溃遗言原子性**这类**行级完整性**判据的固定动作与口径(`docs/子系统设计/控制台单写者日志设计说明.md` 的验收侧:那边讲怎么修,这边讲怎么证明修好了、以及为什么"标记全中"不等于"日志没坏") |
|
||||
| [`链路延迟测试说明.md`](测试说明/专项验证/链路延迟测试说明.md) | 网络链路时延分段定义、判定基线、执行流程 |
|
||||
| [`模拟器差距清单.md`](测试说明/专项验证/模拟器差距清单.md) | **PC 模拟器 vs 真机差距登记册**(保护判据门禁可信度依据;改动涉及网络/日志/硬件层前必查 §3 决策规则) |
|
||||
| [`存储维护与容量恢复.md`](测试说明/专项验证/存储维护与容量恢复.md) | 全片擦除恢复 dhara 坏块记账 / 容量恢复 |
|
||||
|
||||
**测试工具/**(PC 侧工具用法)
|
||||
|
||||
| 文档 | 内容 |
|
||||
|---|---|
|
||||
| [`串口助手使用指南.md`](测试说明/测试工具/串口助手使用指南.md) | 串口助手命令用法 / 工作流 / 排障 |
|
||||
| [`串口助手设计说明.md`](测试说明/测试工具/串口助手设计说明.md) | 串口助手契约 / daemon 行为 / 陷阱 |
|
||||
| [`ST-LINK_CLI_复位使用说明.md`](测试说明/测试工具/ST-LINK_CLI_复位使用说明.md) | 烧录 / 复位 / 回读校验(`ST-LINK_CLI` 完整用法) |
|
||||
|
||||
**测试数据/**(一手证据,**只增不改** → `docs/测试说明/README.md` §4)
|
||||
|
||||
| 目录 | 内容 |
|
||||
|---|---|
|
||||
| [`boot_log_data/README.md`](测试说明/测试数据/boot_log_data/README.md) | `@test` 产出的**开机串口日志快照**存档(跨构建 `[STACK]` 栈 / 堆水位对照,39 个文件) |
|
||||
| [`m2_data/README.md`](测试说明/测试数据/m2_data/README.md) | 链路时延 M2 安静档采集数据(JSON + 串口 `[LAT]` 片段,含逐帧尾批明细与方法学约束) |
|
||||
| `m3_data/` | 链路时延 M3 各档原始 JSON(quiet / stress / pending / 尾批实验;无独立 README,口径见 [`链路延迟测试说明.md`](测试说明/专项验证/链路延迟测试说明.md) 附表) |
|
||||
|
||||
> UI 相关测试见 [`UI设计/UI_自动化测试流程.md`](UI设计/UI_自动化测试流程.md)。
|
||||
|
||||
|
||||
@@ -302,4 +302,4 @@ if (n > 0) {
|
||||
| 启动顺序 / 就绪屏障 | `docs/架构设计/项目启动顺序管理.md` |
|
||||
| UI 设计架构 | `docs/UI设计/UI_设计架构.md` |
|
||||
| LVGL 模拟器部署 | `docs/UI设计/LVGL模拟器部署与使用说明.md` |
|
||||
| CH395F 网络测试 | `docs/测试说明/CH395F_Test_Guide.md` |
|
||||
| CH395F 网络测试 | `docs/测试说明/板级测试/CH395F_Test_Guide.md` |
|
||||
|
||||
@@ -693,7 +693,7 @@ typedef struct {
|
||||
| 3 | 交流量页显示真实相量(非写死值) | 台架:注入已知信号 → 页面值随信号变 |
|
||||
| 4 | 未标定时页面明确标识(不把码值当伏特) | 目检 + 文本断言(`eng=0` 时带标记) |
|
||||
| 5 | 首帧前显示 `--` 而非 `0.000` | 模拟器:不 publish 直接开页,断言文本 |
|
||||
| 6 | 定值整定全链闭环 | 就地改 → 保存 → 重启 → 值保持 + 校验和自检通过 + 主站 C_RD 一致。**半收口(2026-10-26)**:模拟器侧「改 → 保存 → OK → 回首屏新值已在帧里」已由像素 + 文本断言覆盖(黄金用例 `sparam_save` / `sparam_landed`,越界侧 `sparam_oob`);**重启保持与主站 C_RD 一致只能上板**——模拟器没有 NAND,`apply()` 到 `prot_set_set_sealed()` 就是终点,这条差距已登记在 `docs/测试说明/模拟器差距清单.md`;另注意 40 项里有 13 项 `comm_addr=0`(纯本地项),主站侧根本读不到,不能拿 C_RD 当它们的判据 |
|
||||
| 6 | 定值整定全链闭环 | 就地改 → 保存 → 重启 → 值保持 + 校验和自检通过 + 主站 C_RD 一致。**半收口(2026-10-26)**:模拟器侧「改 → 保存 → OK → 回首屏新值已在帧里」已由像素 + 文本断言覆盖(黄金用例 `sparam_save` / `sparam_landed`,越界侧 `sparam_oob`);**重启保持与主站 C_RD 一致只能上板**——模拟器没有 NAND,`apply()` 到 `prot_set_set_sealed()` 就是终点,这条差距已登记在 `docs/测试说明/专项验证/模拟器差距清单.md`;另注意 40 项里有 13 项 `comm_addr=0`(纯本地项),主站侧根本读不到,不能拿 C_RD 当它们的判据 |
|
||||
| 7 | 像素回归稳定 | `ui-golden` 连续两次运行零差异。**已验(2026-10-26,当时下限为 27 页)**:27 页连跑两次逐字节一致(含整定 9 态)——**集合现已扩至 66 张**,**双次一致已验(2026-10-29:同一批 66 张连跑三次逐字节一致,池水位 5,448 B;菜单 8 状态连跑三次亦一致,5,368 B)**;轮询定时器不影响——无头模式不调 `lv_timer_handler()`(§9.2 注 6) |
|
||||
| 9 | 「写不进去」与「改了不动作」两条事实互不冒充 | 反向文本断言(`check_content_pages.py` 的 `ABSENT`:查看页与只读态不得出现「未标定」徽标与「保存」行)+ 台架:未制造该态——要它必须改坏 /prot_set.bin(破坏产品配置存储,用户裁定 2026-10-26 不做),故 LOCK 态目前只有代码级证据与三重反证(ENTER 被正常消费、遥信 YX31=OFF、开机 CORRUPT=0),**没有像素证据** |
|
||||
| 8 | 主机单测覆盖数据模块 | `test/host/ui_data` 全绿并挂 pre-commit 钩子 |
|
||||
|
||||
@@ -120,8 +120,8 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
|
||||
| 留档帧 | 文件名声称 | 实际是 | 墨量 | 证据 |
|
||||
|---|---|---|---|---|
|
||||
| 00 / 01 / 02 | 根菜单 / 装置信息 / 交流量 | 名副其实 | 3226 / 3476 / 3346 | 认屏一致 |
|
||||
| 03_dc | 直流量 | 菜单级联(整屏无页标题) | 4961 | [blindwalk_cascade](../测试说明/boot_log_data/20261025_uinav_blindwalk_cascade.png) |
|
||||
| 04_yx / 05_yxp2 / 06_soe | 遥信量两页 / SOE记录 | **密码输入页** | 512 / 515 / 512 | [blindwalk_pwd512](../测试说明/boot_log_data/20261025_uinav_blindwalk_pwd512.png) |
|
||||
| 03_dc | 直流量 | 菜单级联(整屏无页标题) | 4961 | [blindwalk_cascade](../测试说明/测试数据/boot_log_data/20261025_uinav_blindwalk_cascade.png) |
|
||||
| 04_yx / 05_yxp2 / 06_soe | 遥信量两页 / SOE记录 | **密码输入页** | 512 / 515 / 512 | [blindwalk_pwd512](../测试说明/测试数据/boot_log_data/20261025_uinav_blindwalk_pwd512.png) |
|
||||
| 07_vparam | 参数查看页 | 网口设置页 | 3774 | 标题带命中「网口设置」 |
|
||||
| 08_vset | 定值查看页 | 装置信息页 | 3474 | 标题带命中「装置信息」 |
|
||||
|
||||
@@ -185,7 +185,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
|
||||
脚本对策是「枚举 + 验终点」——末列先盲按 N 次下移再进(第 N 次尝试),成败仍只由页面
|
||||
身份裁定,所以它会大声报错而不是静默走错页。实测 `自检记录` / `运行记录` 两页在模拟器
|
||||
上 5 次枚举内没吃到,现场帧见
|
||||
[popup_clipped](../测试说明/boot_log_data/20261025_uinav_popup_clipped.png);
|
||||
[popup_clipped](../测试说明/测试数据/boot_log_data/20261025_uinav_popup_clipped.png);
|
||||
**真机上那层弹框究竟画在哪,留台架窗口取证后再定修法**——这是取证题,不是编码题。
|
||||
2. 同一标题的多个显示态(网口设置的 只读 / 编辑 / 保存)在分类里都是同一个页面 id
|
||||
`net_cfg`;要区分得看行内文本,写路径判据需要时再加。
|
||||
|
||||
@@ -582,7 +582,7 @@ sequenceDiagram
|
||||
|
||||
**FR-STO-2 坏块管理与持久化 BBT**
|
||||
- 需求:坏块表持久化,重启后不丢失;不交给 dhara 管理。
|
||||
- 判据:全片擦除后容量恢复流程可用(见 `docs/测试说明/存储维护与容量恢复.md`)。
|
||||
- 判据:全片擦除后容量恢复流程可用(见 `docs/测试说明/专项验证/存储维护与容量恢复.md`)。
|
||||
|
||||
**FR-STO-3 卷并发一致性**
|
||||
- 需求:FTP 传输(ftpTask)与配置读写(defaultTask)并发访问卷时不得损坏。
|
||||
@@ -724,7 +724,7 @@ sequenceDiagram
|
||||
- 判据:已知电压注入斜率与理论 LSB 偏差 ≤2%(2026-10-27 台架实测端子侧 **6544.2 码/V**,与引脚侧
|
||||
理论 6553.6 差 **−0.14%**,零点 0~5 码、R²=0.9999997、极性对称 ≤0.34%);8 通道系数/零点往返一致。
|
||||
- 证据与现场步骤:[`docs/硬件平台/ADC通道映射说明.md`](../硬件平台/ADC通道映射说明.md) §8.1、
|
||||
[`docs/测试说明/ADC前端注入验证流程.md`](../测试说明/ADC前端注入验证流程.md)。
|
||||
[`docs/测试说明/专项验证/ADC前端注入验证流程.md`](../测试说明/专项验证/ADC前端注入验证流程.md)。
|
||||
|
||||
**FR-ADC-4 采样有效性校验**
|
||||
- 需求:芯片静默、丢帧、序号倒退、转换错误必须被检出并可闭锁保护,且**不误报**。
|
||||
@@ -1681,7 +1681,7 @@ mac=00:00:00:00:00:00
|
||||
|
||||
| 指标 | 基线值 | 来源 |
|
||||
|---|---|---|
|
||||
| M3 压力档帧周期 | med 60.1 / p95 66.4 / max 69.3 ms(零尖峰) | `docs/测试说明/链路延迟测试说明.md` |
|
||||
| M3 压力档帧周期 | med 60.1 / p95 66.4 / max 69.3 ms(零尖峰) | `docs/测试说明/专项验证/链路延迟测试说明.md` |
|
||||
| 队列响应性(挂起客户端) | 92.5 ms(pending 一期) | `test/host/e02_probe.py` |
|
||||
| FTP 传输速率 | 约 49 / 60 KB/s(上传/下载) | 128 KB 实测 |
|
||||
| 网络重建生效 | 2~5 s(含等链路 ≤3 s) | 配置设计 |
|
||||
@@ -2680,7 +2680,7 @@ docs/任务规划/UI补齐.md §5);原「当前执行 6 项」(记录 5
|
||||
| 采样有效性校验 | [`docs/算法/采样有效性校验设计说明.md`](../../docs/算法/采样有效性校验设计说明.md) |
|
||||
| ADC 采样节拍与 DMA | [`docs/子系统设计/ADC采样节拍设计说明.md`](../../docs/子系统设计/ADC采样节拍设计说明.md) |
|
||||
| ADC 通道映射与实测 | [`docs/硬件平台/ADC通道映射说明.md`](../../docs/硬件平台/ADC通道映射说明.md) |
|
||||
| ADC 前端注入验证流程 | [`docs/测试说明/ADC前端注入验证流程.md`](../../docs/测试说明/ADC前端注入验证流程.md) |
|
||||
| ADC 前端注入验证流程 | [`docs/测试说明/专项验证/ADC前端注入验证流程.md`](../测试说明/专项验证/ADC前端注入验证流程.md) |
|
||||
| IEC 60870-5-104 上行 | [`docs/子系统设计/IEC104上行设计说明.md`](../../docs/子系统设计/IEC104上行设计说明.md) |
|
||||
| 数据可信(标定 / 快照 / 运行参数) | [`docs/任务规划/数据可信.md`](../任务规划/数据可信.md) |
|
||||
| 页面补齐规划 | [`docs/UI设计/页面补齐规划.md`](../../docs/UI设计/页面补齐规划.md) |
|
||||
@@ -2688,8 +2688,8 @@ docs/任务规划/UI补齐.md §5);原「当前执行 6 项」(记录 5
|
||||
| 部署环境 | [`docs/环境与部署/项目部署环境要求.md`](../../docs/环境与部署/项目部署环境要求.md) |
|
||||
| 硬件网表 | [`docs/硬件平台/V0.1_网表详细分析报告.md`](../../docs/硬件平台/V0.1_网表详细分析报告.md) |
|
||||
| 待办登记簿 | [`docs/任务规划/README.md`](../任务规划/README.md) |
|
||||
| 实机测试指南 | [`docs/测试说明/实机测试实施指南.md`](../../docs/测试说明/实机测试实施指南.md) |
|
||||
| 测试标准流程 | [`docs/测试说明/测试开发标准流程.md`](../../docs/测试说明/测试开发标准流程.md) |
|
||||
| 实机测试指南 | [`docs/测试说明/板级测试/实机测试实施指南.md`](../测试说明/板级测试/实机测试实施指南.md) |
|
||||
| 测试标准流程 | [`docs/测试说明/流程与规范/测试开发标准流程.md`](../测试说明/流程与规范/测试开发标准流程.md) |
|
||||
| RAM 预算与优化 | [`docs/内存管理/RAM使用分析与优化方案.md`](../../docs/内存管理/RAM使用分析与优化方案.md) |
|
||||
| AI 开发规范 | `AGENTS.md`(仓库根) |
|
||||
| 开发者入门 | `README.md`(仓库根) |
|
||||
|
||||
@@ -41,7 +41,7 @@ git commit
|
||||
> 以 `pre-commit run --all-files` 复跑 **`pre-commit` 阶段的 47 根**(`mem-numbers` 在无 Keil `.map` 的 runner 上自适应跳过),
|
||||
> 再以「手动阶段门禁」步**逐根** `--hook-stage manual` 复跑 `cppcheck` / `test-cppcheck` / `test-coverage` 三根
|
||||
> (`pre_commit run a b c` 不支持多 id,实测报 `unrecognized arguments`)。
|
||||
> 本地提交前想跑同一套判定:`& '.venv\Scripts\python.exe' scripts/ci_local.py`。详见 `../测试说明/测试开发标准流程.md` §9。
|
||||
> 本地提交前想跑同一套判定:`& '.venv\Scripts\python.exe' scripts/ci_local.py`。详见 `../测试说明/流程与规范/测试开发标准流程.md` §9。
|
||||
|
||||
### 依赖清单
|
||||
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@
|
||||
运行报告页同日落地并绑页,内容页黄金参考 53 → 60 张(runreport 分 2 页,第 2 页单独拍一张;判据 = simulator/tests/ref/ 入库 shot_*.bin 实数,张数 = 页面个数 + 分页多拍的那一张;**该集合 2026-10-29 已扩至 66 张**,多出的是录波回放页 6 态)。
|
||||
上板判据(真记录翻页、掉电保持、清除后归零、boot_count 自增、RESTARTED、rst_cause=IWDG、conn_up +1)
|
||||
已登记登记簿 §7「UI 六页真机判据」,六页文件头各留「台架待补」段;模拟器差距见
|
||||
docs/测试说明/模拟器差距清单.md §2.3「开机账本 boot_stats」一行。
|
||||
docs/测试说明/专项验证/模拟器差距清单.md §2.3「开机账本 boot_stats」一行。
|
||||
|
||||
**执行纪律:单道串行。** 菜单树与页面注册表是生成物,字库也是整文件生成物;
|
||||
不要同时开多条 UI 页面分支。上板验证可累积成一批,但保存、重启、主站读回等判据不能删除。
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@
|
||||
| 通讯设置 | 页面与六态黄金已随 `728d6067` 入库;`[comm]` 段与端口真源在 `App/protocol/iec104/iec104_comm.{c,h}` | 「改后重启即生效」真机判据、配置段数与键数上限核对(台架窗口统一补做并留证) |
|
||||
| 记录 5 页 | 五类记录 ID / 文件 / 写入点已齐(docs/任务规划/登记簿.md §7 与 App/log/README.md §五类记录);reader 注入两端已映射 7 个记录源 | 页面已交付;只剩真机判据(真记录翻页、掉电保持、清除后归零),见 docs/任务规划/登记簿.md §7 |
|
||||
| 录波两页 | 手动录波操作页 + 录波回放页已落地绑页(2026-10-29 录波 UI 道);数据源 = `App/algo/wave_ring`/`wave_store` 真实现经 `ui_data_wave_ops_t` 注入,回放读盘走 `vol_lock` try 锁小窗口 | 页面已交付;真机判据归台架(真实触发落盘的段号连续性、削徽标真值、切段切道实测毫秒与卷锁忙「本轮无段」行为,见 `docs/子系统设计/故障录波设计说明.md` §10 台架判据) |
|
||||
| 运行报告 | boot_stats(SD2506 用户 SRAM 上电次数 + 本次复位原因快照,道G task-12)、iec104_serv 四个只读观测计数、现成 uptime_s | 页面已交付;**跨开机累计不做**(用户裁定只报本次开机)。真机待复核 SRAM 自增与四态判定,见 docs/测试说明/模拟器差距清单.md §2.3 |
|
||||
| 运行报告 | boot_stats(SD2506 用户 SRAM 上电次数 + 本次复位原因快照,道G task-12)、iec104_serv 四个只读观测计数、现成 uptime_s | 页面已交付;**跨开机累计不做**(用户裁定只报本次开机)。真机待复核 SRAM 自增与四态判定,见 docs/测试说明/专项验证/模拟器差距清单.md §2.3 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
+14
-14
@@ -33,7 +33,7 @@
|
||||
**三条结论**:
|
||||
|
||||
1. **第 1、2 级已闭环**,证据与判据的属主是 `docs/硬件平台/ADC通道映射说明.md` §8.1,执行步骤属主是
|
||||
`docs/测试说明/ADC前端注入验证流程.md`——本文不重抄,只写"证到哪、为什么不能再往外推"。
|
||||
`docs/测试说明/专项验证/ADC前端注入验证流程.md`——本文不重抄,只写"证到哪、为什么不能再往外推"。
|
||||
2. **第 3 级是当前唯一的空白,而且不需要任何外部资源**:一台能出 50 Hz 正弦的交流信号发生器,
|
||||
接在**已经验证过的那个注入点**上就行。它比第 4、5 级安全一个量级——只需 ±2 V 以内的正弦,
|
||||
而端子级验证要上 100 V / 220 V 二次值。**不用烧高压、不用标准源,这是把它排最前的理由**(§4.6)。
|
||||
@@ -106,7 +106,7 @@
|
||||
### 2.6 静态验证:已知电压注入已于 2026-10-27 台架闭环(锚点:`adc_cal.*` / `meas.*` / `ui_data*`)
|
||||
|
||||
判据与实测记录的属主 = `docs/硬件平台/ADC通道映射说明.md` §8.1,执行步骤属主 =
|
||||
`docs/测试说明/ADC前端注入验证流程.md`。一块万用表 + 一个电位器 + 串口 `adc:` 心跳行就够,
|
||||
`docs/测试说明/专项验证/ADC前端注入验证流程.md`。一块万用表 + 一个电位器 + 串口 `adc:` 心跳行就够,
|
||||
**不需要**示波器、信号源、标准源;注入点在串联电阻的端子侧 `U5` 排针(不碰 LQFP 引脚)。
|
||||
|
||||
| 项 | 实测 | 判据 |
|
||||
@@ -150,7 +150,7 @@ V0.1 恒命中 UB/UC/IB/IC/IN,位图 `0xE6`),它表示"这路不能测交
|
||||
| `test/host/meas/run_unit_test.py` | 「读数与注入源比对类判据仍归台架(实测采样类,本套件不覆盖)」 |
|
||||
| `test/host/prot_dim/prot_dim_test.c` | 系数是合成覆写的 10 mV/码,非板上 152.59 / 805.66 µV/码 |
|
||||
| `App/algo/adc_cal.h` | `adc_cal_two_point()`:「实测注入未做(台架待跑),本函数即"公式齐备"的交付物」 |
|
||||
| `docs/测试说明/ADC前端注入验证流程.md` | 「**只验直流**:零点 / 线性 / 通道映射 / 极性。不验交流有效值——台架无信号源」 |
|
||||
| `docs/测试说明/专项验证/ADC前端注入验证流程.md` | 「**只验直流**:零点 / 线性 / 通道映射 / 极性。不验交流有效值——台架无信号源」 |
|
||||
| `App/task/adc_task.c` 心跳块 | `adc:` 是当拍瞬时码值、`meas:` 是 200 ms 快照——**没有一行能给出波形形状** |
|
||||
|
||||
按下游列一遍"现在能不能信":
|
||||
@@ -297,7 +297,7 @@ typedef struct {
|
||||
|
||||
| 理由 | 依据 |
|
||||
|---|---|
|
||||
| 注入点已经验证过,且就在那儿 | `docs/测试说明/ADC前端注入验证流程.md` §3 的注入点清单(串联电阻端子侧 = `U5` 排针);③ 段 1:1 已拿到台架证据(§2.6) |
|
||||
| 注入点已经验证过,且就在那儿 | `docs/测试说明/专项验证/ADC前端注入验证流程.md` §3 的注入点清单(串联电阻端子侧 = `U5` 排针);③ 段 1:1 已拿到台架证据(§2.6) |
|
||||
| **不知道 ④ 变比也能验算法** | 注入点在 ④ **之前**,发生器给的电压就是引脚电压,算法链要证的正是"引脚域里算得对不对" |
|
||||
| 幅度小两个数量级 | 只需 ±2 V 以内的正弦(TPAFE 侧判据上限);端子二次值验证要上 100 V / 220 V,风险与设备都在那一级 |
|
||||
| 现有静态验证的读数出口可直接复用 | 串口心跳 + 104 YC,零固件改动(§4.6.3) |
|
||||
@@ -308,7 +308,7 @@ typedef struct {
|
||||
#### 4.6.2 判据(六轮:幅值 / 波形 / 相位 / 测频 / 削顶 / 谐波)
|
||||
|
||||
> **分工**:本节定"验什么、过判据是多少";**期望值的算术、接法细节与执行步骤**在
|
||||
> `docs/测试说明/ADC前端注入验证流程.md` §8(同一轮次的手册,两边于 2026-10-29 已对齐)。
|
||||
> `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8(同一轮次的手册,两边于 2026-10-29 已对齐)。
|
||||
>
|
||||
> **轮次名一律用语义短语(用户裁定 2026-10-30:清退"字母+数字"判据号)**:D1 → 幅值轮、D2 → 波形轮、
|
||||
> D3 → 相位轮、D4 → 测频轮、D5 → 削顶轮、D6 → 谐波轮;本族旧号作废不得再取走
|
||||
@@ -317,14 +317,14 @@ typedef struct {
|
||||
| 轮次 | 验什么 | 接法 | 读哪 | 过判据 |
|
||||
|---|---|---|---|---|
|
||||
| **幅值轮** | 基波幅值计量 | UA(R31 / `AIN1`)注 1.000 Vrms、50.000 Hz 正弦 | `meas:` 的 `ua_mv`;或 104 `0x4011` | 读数 = 万用表 AC 档读数,偏差 ≤2 %(与静态同档)。⚠ 别用 `phasor(hb)` 行比幅值——那是 ×0.1 定点,注 1 V 只剩 10 格(§4.6.3) |
|
||||
| **波形轮** | 读数是否只跟基波走 | 同幅值改方波、三角 | 同上 | 期望值 = **基波分量有效值**(同峰值下的基波 / 峰值比:方波 ≈ **0.90**,闭式 4/π ÷ √2 = 0.900、20 点整周期 DFT 实算 0.904;三角 ≈ **0.573**,闭式 8/π² ÷ √2 = 0.573、实算 0.578),**不是**真有效值(方波 = 1.000、三角 = 0.583 峰值);偏差 ≤2 %。算术与逐波形对照表见 `docs/测试说明/ADC前端注入验证流程.md` §8.5 的波形卡。顺带把"这台仪表读的是基波"这条口径钉进文档——用户拿真有效值表去对会以为差了 10 % |
|
||||
| **波形轮** | 读数是否只跟基波走 | 同幅值改方波、三角 | 同上 | 期望值 = **基波分量有效值**(同峰值下的基波 / 峰值比:方波 ≈ **0.90**,闭式 4/π ÷ √2 = 0.900、20 点整周期 DFT 实算 0.904;三角 ≈ **0.573**,闭式 8/π² ÷ √2 = 0.573、实算 0.578),**不是**真有效值(方波 = 1.000、三角 = 0.583 峰值);偏差 ≤2 %。算术与逐波形对照表见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.5 的波形卡。顺带把"这台仪表读的是基波"这条口径钉进文档——用户拿真有效值表去对会以为差了 10 % |
|
||||
| **相位轮** | 相位 | UA 与 UN 两路**同片**(都走 TPAFE)注同幅、同相 | **定量档**:录波段文件 `test/host/wave_read.py fft`(浮点重算基波相位;段内表序 `UA` = 0、`UN` = 3);**定性档**:`phasor(hb)` 各行 `Re=` / `Im=` | **定量档**:同段内两路相位差 ≤2°,把发生器相位改 90° 后差值跟到 ≈90°。**定性档只判"跟随"**(差值落进 80°~100°)——`phasor` 出口是 ×0.1 定点,1.000 Vrms 时每格 0.1 V,角度量化最坏 ≈ atan(0.1 / 0.707) ≈ 8°,判不动 2°(§4.6.3)。⚠ 段与发生器**无绝对相位锁定**(触发瞬间钉在段内点 159),只能比**同段内两路**的相对差,跨段比相位或拿发生器相位当绝对基准都不成立。**只许比同片内**——跨转换器无同刻性(§9),STM32 那五路还有 1 拍乒乓滞后 |
|
||||
| **测频轮** | 测频 | 同幅值轮的 1 V/50 Hz | `freq(hb):` 与 104 `0x401D` | **预期就是"不出数"**(幅值门 50 V 在引脚域恒不过,§2.3 #1)→ 这条的判据是"如实报不可测"(`freq_valid=0`、UI `Hz` 显示 `--`、104 上送 IV),**不是**报出一个错误的 50.00。想真验 45~55 Hz 精度(PC 侧判据 0.02 Hz)须临时把 `FREQ_AMP_MIN` 降到引脚域量级(如 0.5 V)单跑一轮 → §7 #8 + §8 风险行 |
|
||||
| **削顶轮** | 削顶与品质路由(**负向用例**) | 给 UB(R52 / `AIN2`)注 **DC −1.00 V 并保持 ≥5 s**;或 1.000 Vrms 而频率 **2.0 Hz** 的正弦——两档都能造出"连续贴同一侧轨带"。⚠ **注 50 Hz 同幅正弦造不出锁存,且这是预期而非故障**:1 kHz 下一个周波只 20 点、正半周必落中带,而 `adc_health_rail_watch()` 任何一拍回中带就把计数清零(`App/algo/adc_health.c`),连续贴底最长 ≈ 209/360 × 20 ≈ 11 拍 < 20。TPAFE 侧在 ±2 V 判据上限内造不出这条(轨带 ±32112 码 ≈ ±4.9 V),只有 STM32 那五路能做 | `cal:` 行的 `rail=` / `edge=`;`rail: edge=…` 的 `[ERR]` 行;104 `0x4012`;段文件档另加 `wave_read.py shape` 的三把尺子(`--strict` / 再加 `--clip-superset` / 不带),逐条配法见 `docs/测试说明/ADC前端注入验证流程.md` §8.5 的削顶卡 | 负半周钉下轨 → **连续 20 拍同侧后该路贴轨位锁存**(`ADC_RAIL_N_RUN = 20`,`App/algo/adc_health.h:174`)、`edge` 起沿、104 上该路 IV 且值清零。锁存另有**释放沿前提**:该通道此前须出现过中带样本 → **先上电见基线摆动、再开发生器输出**,开机就注会测出假不通过。撤掉注入后 `rail` 仍非 0 是 sticky 语义(只有 `adc_health_rail_init()` / 复位清)——**复位后仍不清才是 bug**。⚠ 这条会**故意造出 `[ERR]`**,而 `@test` 的 forbidden 标记含 `[ERR]` → 人工判读、排在最后单独一轮(§8 第一行) |
|
||||
| **削顶轮** | 削顶与品质路由(**负向用例**) | 给 UB(R52 / `AIN2`)注 **DC −1.00 V 并保持 ≥5 s**;或 1.000 Vrms 而频率 **2.0 Hz** 的正弦——两档都能造出"连续贴同一侧轨带"。⚠ **注 50 Hz 同幅正弦造不出锁存,且这是预期而非故障**:1 kHz 下一个周波只 20 点、正半周必落中带,而 `adc_health_rail_watch()` 任何一拍回中带就把计数清零(`App/algo/adc_health.c`),连续贴底最长 ≈ 209/360 × 20 ≈ 11 拍 < 20。TPAFE 侧在 ±2 V 判据上限内造不出这条(轨带 ±32112 码 ≈ ±4.9 V),只有 STM32 那五路能做 | `cal:` 行的 `rail=` / `edge=`;`rail: edge=…` 的 `[ERR]` 行;104 `0x4012`;段文件档另加 `wave_read.py shape` 的三把尺子(`--strict` / 再加 `--clip-superset` / 不带),逐条配法见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.5 的削顶卡 | 负半周钉下轨 → **连续 20 拍同侧后该路贴轨位锁存**(`ADC_RAIL_N_RUN = 20`,`App/algo/adc_health.h:174`)、`edge` 起沿、104 上该路 IV 且值清零。锁存另有**释放沿前提**:该通道此前须出现过中带样本 → **先上电见基线摆动、再开发生器输出**,开机就注会测出假不通过。撤掉注入后 `rail` 仍非 0 是 sticky 语义(只有 `adc_health_rail_init()` / 复位清)——**复位后仍不清才是 bug**。⚠ 这条会**故意造出 `[ERR]`**,而 `@test` 的 forbidden 标记含 `[ERR]` → 人工判读、排在最后单独一轮(§8 第一行) |
|
||||
| **谐波轮** | 谐波轨 | 基波 + 20 % 二次 + 20 % 五次(IA 上注)。⚠ 峰值预算:1.000 Vrms 基波 + 两个 20 % 分量的最坏对齐 ≈ 1.98 V 已顶 ±2 V 红线 → 基波用 **0.800 Vrms**、二次与五次各 0.160 Vrms | **定量档**:段文件 `test/host/wave_read.py fft --ch 4 --all`(`IA` = 段内表序 4,直接给基波与 2 / 5 次谐波 RMS,单位 mV);**旁证**:UI 交流量页 `Ia2` / `Ia5`(1 mV)与 `phasor(hb) C04-IA-F2` / `C05-IA-F5`(×0.1 定点,只证这根轨不是恒 0) | 谐波轨读数 = 注入分量(**±2 %,走定量档**;周期行档判不动:0.160 Vrms 在 ×0.1 出口只有 1~2 格)。⚠ 这两根轨**目前没有任何下游消费者**(`prot_elm.c` 无引用、`meas` 只算 `harm=1`),所以谐波轮只证"算得对",**不证"有人用"**——出口归 §9 的谐波轨立项 |
|
||||
|
||||
**先做幅值 / 波形 / 削顶三轮**(纯读数、无跨通道约定),相位 / 谐波次之,测频轮视 §7 #8 的裁定。每条的两档跑法(周期行标量档 /
|
||||
录波段文件定量档)、触发动作、耗时排布与失败分诊在 `docs/测试说明/ADC前端注入验证流程.md` §8.6。
|
||||
录波段文件定量档)、触发动作、耗时排布与失败分诊在 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.6。
|
||||
|
||||
#### 4.6.3 读数出口(零固件改动)
|
||||
|
||||
@@ -333,12 +333,12 @@ typedef struct {
|
||||
| 串口每 10 s 心跳(`App/task/adc_task.c` 心跳块) | `adc:`(9 路码值)、`cal:`(三路 mV + `vl`/`cl`/`rail`/`edge` 位图)、`phasor(hb)`(逐实例 `Re` / `Im` / `rms`)、`freq(hb)`、`meas:`(快照轨) | MicroLIB 无 `%f`,全是定点:`phasor` ×0.1(**1 V 注入只剩 10 格**)、`freq` ×0.01 Hz、`cal:` / `meas:` ×1000(1 mV)。10 s 一行的单点瞬时值对 50 Hz 等价于随机相位抽样 |
|
||||
| 104 YC(现成 PC 主站 `test/host/iec104_master.py`) | `0x4011`~`0x4018` 八个电气量 + `0x401D` 频率,**浮点无量化**,还带品质 | UB/UC/IB/IC/IN 恒 IV、值清零 → 那五路只能回读串口码值域 |
|
||||
| UI 交流量页 | `Ua` / `U0` / `Ia` / `Ia2` / `Ia5` / `Hz` / 标定徽标 共 7 行 | 160×160 单色;`--` **同时**表示"没数"和"有数但不可信" → 不能当判据,只能当旁证 |
|
||||
| **段文件样本出口(代码侧已落地,2026-10-29)** | 每次触发一段:`/wave/WAVE00.BIN` 起共 100 个号轮转(FTP 根下可见),8 路 × 320 点原始码值加封存瞬间的标定与品质快照;PC 侧 `test/host/wave_read.py` 提供 dump / fft / shape / plot 四个子命令(bench 工具,纯标准库,自带 `--selftest`) | 「比对派生标量」已可升级成「PC 独立重算 vs 板上读数」对表(判据与执行步骤见 `docs/测试说明/ADC前端注入验证流程.md` §4,格式属主见 `docs/子系统设计/故障录波设计说明.md` §6.2 与 §6.3)。**但板级那一轮还没跑**(注 1 V / 50 Hz、与 `meas:` 与 104 YC 对表、CRC 不符必须拒收的实测,见 `docs/任务规划/故障录波.md` 卡片判据);示波器仍旧只作旁证、不当判据。段内点序:触发瞬间落在段内点 159(预触发 160 点的最后一点),段的绝对相位与发生器无锁定关系,可核对的是相对相位与极性 |
|
||||
| **段文件样本出口(代码侧已落地,2026-10-29)** | 每次触发一段:`/wave/WAVE00.BIN` 起共 100 个号轮转(FTP 根下可见),8 路 × 320 点原始码值加封存瞬间的标定与品质快照;PC 侧 `test/host/wave_read.py` 提供 dump / fft / shape / plot 四个子命令(bench 工具,纯标准库,自带 `--selftest`) | 「比对派生标量」已可升级成「PC 独立重算 vs 板上读数」对表(判据与执行步骤见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §4,格式属主见 `docs/子系统设计/故障录波设计说明.md` §6.2 与 §6.3)。**但板级那一轮还没跑**(注 1 V / 50 Hz、与 `meas:` 与 104 YC 对表、CRC 不符必须拒收的实测,见 `docs/任务规划/故障录波.md` 卡片判据);示波器仍旧只作旁证、不当判据。段内点序:触发瞬间落在段内点 159(预触发 160 点的最后一点),段的绝对相位与发生器无锁定关系,可核对的是相对相位与极性 |
|
||||
| **仍然没有的(2026-10-29 更新)** | 没有命令控制台、也没有「把窗里 20 / 40 个点导出来」的定点 dump 子命令——**但样本出口本身已成立**(上一行的段文件:一次 320 点 / 8 路,比原来规划的 20 / 40 点窗更宽) | 现场取回一律走现成 FTP(21 端口),形状就地看回放页单通道、或在 PC 侧用同一脚本出图;示波器只对照发生器、不当判据。**判据已升级为「PC 独立重算 vs 板上读数」对表**,对表的执行轮次待台架(见 `docs/子系统设计/故障录波设计说明.md` §11) |
|
||||
|
||||
#### 4.6.4 接法与红线(照抄既有红线,不新发明)
|
||||
|
||||
- 注入点:串联电阻的**端子侧**焊盘(`U5` 排针),逐路清单见 `docs/测试说明/ADC前端注入验证流程.md` §3;
|
||||
- 注入点:串联电阻的**端子侧**焊盘(`U5` 排针),逐路清单见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §3;
|
||||
引脚侧没有串阻保护,必须外串 **10 k** 限流。
|
||||
- 幅度按**峰值**算,别看 Vrms 数字:1.000 Vrms 正弦峰值已 1.414 V;TPAFE 侧按判据只到 **±2 V**(满量程 ±5 V),
|
||||
STM32 那五路是 **0~3.3 V 单极性**——给它们注交流只能是削顶轮那种"故意削顶"的用例,峰值同样不得超 3.3 V。
|
||||
@@ -361,14 +361,14 @@ typedef struct {
|
||||
|
||||
> 资源图例:🔴 台架(COM3 / ST-LINK,`bench.lock` 独占)· 🟡 外部(标准源 / 子板原理图)· 🟢 纯软件。
|
||||
> 状态:⬜ 未开始 · 🟦 进行中。**已闭环 = 直接删行**。
|
||||
> 本表**只写判据**;执行步骤在 `docs/测试说明/ADC前端注入验证流程.md`,实测结论在
|
||||
> 本表**只写判据**;执行步骤在 `docs/测试说明/专项验证/ADC前端注入验证流程.md`,实测结论在
|
||||
> `docs/硬件平台/ADC通道映射说明.md` §8.1(动态实测结论开在其后)。
|
||||
|
||||
| 标识(任务名)| DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 |
|
||||
|---|---|---|---|---|---|
|
||||
| **信号发生器动态波形验证** | 按 §4.6.2 跑完六轮(测频轮允许以"如实报不可测"通过),逐条记实测 / 判据 / 结论;执行步骤与判据表**新增到** `docs/测试说明/ADC前端注入验证流程.md`(直流节之后开一节"交流"),实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.1 之后新开一节;证据(串口日志 + 104 落库)归档 `docs/测试说明/boot_log_data/` | 静态注入闭环(✅ 2026-10-27)+ 一台能出 50 Hz 正弦、幅度可调到 1 Vrms 的交流信号发生器(**不需要标准源、不需要端子加压**) | 🔴 台架 + 手边发生器 | `docs/测试说明/`、`docs/硬件平台/` | ⬜ |
|
||||
| **信号发生器动态波形验证** | 按 §4.6.2 跑完六轮(测频轮允许以"如实报不可测"通过),逐条记实测 / 判据 / 结论;执行步骤与判据表**新增到** `docs/测试说明/专项验证/ADC前端注入验证流程.md`(直流节之后开一节"交流"),实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.1 之后新开一节;证据(串口日志 + 104 落库)归档 `docs/测试说明/测试数据/boot_log_data/` | 静态注入闭环(✅ 2026-10-27)+ 一台能出 50 Hz 正弦、幅度可调到 1 Vrms 的交流信号发生器(**不需要标准源、不需要端子加压**) | 🔴 台架 + 手边发生器 | `docs/测试说明/`、`docs/硬件平台/` | ⬜ |
|
||||
| **端子/子板变比确认** | 给出"端子电压 → ADC 引脚电压"的比值(万用表同时量端子与引脚,或查子板原理图后实测核对),写入 `docs/硬件平台/ADC通道映射说明.md`;据此判定 `eng` 能否置 1;数据缺失则本波只交付引脚电压并登记缺口 | 已知电压注入验证(✅);**与动态验证无依赖关系**,可并行 | 🟡 子板实物或原理图 | `docs/硬件平台/` | ⬜ |
|
||||
| **两点标定与精度验收** | 电压 4 路(UA/UB/UC/UN)+ 电流 4 路(IA/IB/IC/IN)各做两点标定(零点 + 满度,温度不纳入),写入 `[adc_cal]` 并置 `VALID`;误差 ≤ 目标精度(待定:0.5 级 / 1 级 → §7 #1);证据归档 | 端子/子板变比确认;削顶五路的处置结论(削顶轮) | 🟡 标准源 / 继保测试仪 | `docs/算法/`、`docs/测试说明/boot_log_data/` | ⬜ |
|
||||
| **两点标定与精度验收** | 电压 4 路(UA/UB/UC/UN)+ 电流 4 路(IA/IB/IC/IN)各做两点标定(零点 + 满度,温度不纳入),写入 `[adc_cal]` 并置 `VALID`;误差 ≤ 目标精度(待定:0.5 级 / 1 级 → §7 #1);证据归档 | 端子/子板变比确认;削顶五路的处置结论(削顶轮) | 🟡 标准源 / 继保测试仪 | `docs/算法/`、`docs/测试说明/测试数据/boot_log_data/` | ⬜ |
|
||||
|
||||
**为什么把动态验证排在第一**(不是因为它最重要,而是因为它把后面两张卡踩实):
|
||||
|
||||
@@ -470,7 +470,7 @@ flowchart TD
|
||||
|
||||
| 工作 / 文档 | 关系 |
|
||||
|---|---|
|
||||
| **`docs/测试说明/ADC前端注入验证流程.md`** | **执行步骤的属主**。本文只写"证到哪、判据是什么、为什么这么排";怎么接表笔、读哪一行、填哪张表一律在那篇里。动态验证的**步骤**同样落那篇(新开"交流"节),本文 §4.6 只留判据 |
|
||||
| **`docs/测试说明/专项验证/ADC前端注入验证流程.md`** | **执行步骤的属主**。本文只写"证到哪、判据是什么、为什么这么排";怎么接表笔、读哪一行、填哪张表一律在那篇里。动态验证的**步骤**同样落那篇(新开"交流"节),本文 §4.6 只留判据 |
|
||||
| **通道映射说明** | `docs/硬件平台/ADC通道映射说明.md` §7.1(①②③④ 链路分段)与 §8.1(静态六项实测)是**量纲与实测记录的属主**;本文 §2.1 / §2.6 是它的**消费者**,不另立口径,动态实测结论也回写该文件 |
|
||||
| **`docs/子系统设计/故障录波设计说明.md`** | 录波段文件是本卡「动态波形验证」的**样本出口**,数据面代码侧已落地(2026-10-29:环与段格式在 `App/algo/wave_ring.c` / `App/algo/wave_store.c`,PC 侧 `test/host/wave_read.py`);判据从「比对派生标量」升级为「PC 独立重算 vs 板上读数」对表的**执行轮次待台架**,动态验证的排序已因此让位给录波数据面(用户裁定 2026-10-29,理由与三处口径变更见 docs/子系统设计/故障录波设计说明.md §11) |
|
||||
| **`docs/算法/采集与算法层设计说明.md`** | 算法与判据正文(全周傅氏、测频、保护元件);本文只规定"这些算法的信度到什么程度" |
|
||||
|
||||
+4
-4
@@ -12,7 +12,7 @@
|
||||
|---|---|---|---|---|
|
||||
| 队列往返基线待重验 | **队列往返基线(1223/988µs)在发送分块握手改造后的重验**——队列往返测 DONTWAIT 队列全程;发送分块握手对该路径逐位不变 → 机制上无影响,但基线数值属分片时代,严格重锁需跑一轮 Phase 13(需 PC peer) | 2026-09-22(发送分块握手收尾留档) | 低风险:10ms/100ms 阈值余量 >8×;下次 Phase 13 窗口顺带重锁即可 | `链路延迟测试说明.md` §6.4 队列往返行的注¹ |
|
||||
| 网络负向场景台架验证 | **负向场景台架验证待办**(拔线断链 / 芯片级 `net_init` 失败分支 / 短写压测;正常路径已实测零回归):① PHY 拔线负向测试——断链需断 **DTU 侧**线缆或关**受管交换机端口**;② 芯片级 `net_init` 失败分支(需 SPI 故障注入);③ 短写压测(需远显客户端 + UI 推流压力) | 2026-10-03(台架拓扑 = CH395↔交换机,拔线操作受限) | 待专项台架窗口 | `实机测试实施指南.md` §10 |
|
||||
| reconcile 突发饿死 uiTask | **对时 reconcile/relisten 突发(0~4s 窗)把唯一 BelowNormal 的 uiTask 压成同一任务 800ms+ 单串缺席(饿死型,非等待型——F3 返回点喂位射程外)**:8 连窗级 UI 缺席期间喂狗面本身未断(cf=0 seg=1)、uisn=0(不在 sink 段内)、uip 在途 307→1083ms 而 uis 峰仅 183ms——被拖的 1s 在 feed/port 纯计算段墙钟。**2026-10-25 台架两轮分箱定案**:同负载换 :7003 churn 2200 周期 stall=0(阻塞型已被 F3 治愈),探针轮 3 事件 8 行全为该签名(漏检零、误报零,v1.1 口径 FAIL 面精确收缩)。处置方向 = 自愈设计 §11.3 脆弱点 1 实测样本并档「net 层跨上下文收口」项:优先级矩阵复核与 reconcile 突发分片让路两案并评;**排期 = UI 完成后的第一项**,与裸指针收口同批 | 2026-10-25(F2/F3 验收轮②,v1.1 判据下捕获) | `docs/测试说明/boot_log_data/f3rounds_r2_probe_30min.log.gz`(3 事件 8 行 + STALL 证据行 + 同行 PROF);对照轮 `f3rounds_r1_7003_churn_30min.log.gz`;机理归档 `../网络/网络自愈架构设计.md` §4.6、`../子系统设计/看门狗设计说明.md` §11.3、`../UI设计/UI_设计架构.md` §5.8 | `../算法/继电保护功能复现规划.md`(裸指针收口项属主文档指针) |
|
||||
| reconcile 突发饿死 uiTask | **对时 reconcile/relisten 突发(0~4s 窗)把唯一 BelowNormal 的 uiTask 压成同一任务 800ms+ 单串缺席(饿死型,非等待型——F3 返回点喂位射程外)**:8 连窗级 UI 缺席期间喂狗面本身未断(cf=0 seg=1)、uisn=0(不在 sink 段内)、uip 在途 307→1083ms 而 uis 峰仅 183ms——被拖的 1s 在 feed/port 纯计算段墙钟。**2026-10-25 台架两轮分箱定案**:同负载换 :7003 churn 2200 周期 stall=0(阻塞型已被 F3 治愈),探针轮 3 事件 8 行全为该签名(漏检零、误报零,v1.1 口径 FAIL 面精确收缩)。处置方向 = 自愈设计 §11.3 脆弱点 1 实测样本并档「net 层跨上下文收口」项:优先级矩阵复核与 reconcile 突发分片让路两案并评;**排期 = UI 完成后的第一项**,与裸指针收口同批 | 2026-10-25(F2/F3 验收轮②,v1.1 判据下捕获) | `docs/测试说明/测试数据/boot_log_data/f3rounds_r2_probe_30min.log.gz`(3 事件 8 行 + STALL 证据行 + 同行 PROF);对照轮 `f3rounds_r1_7003_churn_30min.log.gz`;机理归档 `../网络/网络自愈架构设计.md` §4.6、`../子系统设计/看门狗设计说明.md` §11.3、`../UI设计/UI_设计架构.md` §5.8 | `../算法/继电保护功能复现规划.md`(裸指针收口项属主文档指针) |
|
||||
| relisten 沉降段原语化受阻 | **relisten 沉降段统一到驱动 `sock_reset` 原语受阻**——"去重复实现"的收口已实测回退:原语版 `ftp_abort_probe` RST **0/10**、FIN **0/5**(中止后首笔复连仍被截断到 ≤2048B),另新增 `sock_reset_sync timeout (600ms)` 与 `close: sock_reset not done` 两条 `[ERR]`;同场 net 层自建序列 **10/10 + 5/5** | 2026-10-14(同一块板 A/B,判据 `test/host/ftp_abort_probe.py`;快复连 50/50、背靠背 30/30 两版都过 → 失效面精确落在"中止后首笔复连") | **现状 = `net_listener.c` 保留自建排渣序列**(排空 + CLOSE + 排事件 + 等 CLOSED,30 ms 重试轮持续清)。重开前置三条语义:① 隔离窗内**持续**排空/关闭(残渣在 CLOSE 之后才落进 RX,一次排空接不住)② **复用让位**(复位机不得拆上层刚在同一芯片 Socket 上重建的监听)③ `net_sock_reset_sync` 改"已在运行 = 加入等待"(`begin` 返 -1 ≠ 失败) | `../网络/网络自愈架构设计.md` §8 延后项 1、§5.2 E16;`../问题记录/CH395F_Trap_Records.md` TRAP-NET-18 |
|
||||
|
||||
## 2. 存储 / 日志管线
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
| # | 事项 | 优先级 | 问题与证据 | 处置方向 | 出处 |
|
||||
|---|---|---|---|---|---|
|
||||
| CI 远端闭环未验证 | **CI 远端闭环未验证**(runner 本机已就绪) | 中 | **剩余两件**:③ 推送远端跑一次两 job 闭环验证(**跑通证据尚无留档**,故仍按"未验证"对待);④ 第二机交叉验证(不同工具安装路径,验 `DTU_*` 环境变量方案,→ `../环境与部署/本地工具路径环境变量方案.md` 变更记录 TODO)。①② 已就绪,见 `../CI/远程CI完整指南.md` §0 仓库状态行 | 完成前**提交前仍须在本地跑 `scripts/ci_local.py` 或 `pre-commit run --all-files` 自查**(静态门禁唯一保障,不能因"已配 CI"而放宽) | `.gitea/workflows/ci.yml`;`../CI/远程CI完整指南.md`;`../测试说明/测试开发标准流程.md` §9 |
|
||||
| CI 远端闭环未验证 | **CI 远端闭环未验证**(runner 本机已就绪) | 中 | **剩余两件**:③ 推送远端跑一次两 job 闭环验证(**跑通证据尚无留档**,故仍按"未验证"对待);④ 第二机交叉验证(不同工具安装路径,验 `DTU_*` 环境变量方案,→ `../环境与部署/本地工具路径环境变量方案.md` 变更记录 TODO)。①② 已就绪,见 `../CI/远程CI完整指南.md` §0 仓库状态行 | 完成前**提交前仍须在本地跑 `scripts/ci_local.py` 或 `pre-commit run --all-files` 自查**(静态门禁唯一保障,不能因"已配 CI"而放宽) | `.gitea/workflows/ci.yml`;`../CI/远程CI完整指南.md`;`../测试说明/流程与规范/测试开发标准流程.md` §9 |
|
||||
|
||||
## 5. RS-485、内存与仓库观察
|
||||
|
||||
@@ -64,9 +64,9 @@
|
||||
| **标准源送检与第三方 104 验收** | 两点标定完成、保护 VALID 置位、第三方主站 | 标准源注入判据全部通过;总召、周期、变位、遥控全流程通过;证据归档。送检窗口前 2 日冻结特性 | `../子系统设计/IEC104上行设计说明.md` §7/§8 |
|
||||
| **队列往返基线待重验** | 台架 + PC peer | 下次 Phase 13 窗口重锁基线 | 本文件 §1 |
|
||||
| **网络负向场景台架验证** | 拔线、SPI 故障注入、远显压力条件 | PHY 拔线、芯片级 `net_init` 失败、短写压测 | 本文件 §1 |
|
||||
| **串口助手正路径补验** | CH340 接入 | 补齐尚未覆盖的正路径 | `../测试说明/串口助手设计说明.md` |
|
||||
| **串口助手正路径补验** | CH340 接入 | 补齐尚未覆盖的正路径 | `../测试说明/测试工具/串口助手设计说明.md` |
|
||||
| **CI 远端闭环未验证** | runner 与第二台机器 | 验证远端两 job 闭环和不同工具路径 | 本文件 §4 |
|
||||
| **UI 六页真机判据(记录 5 页 + 运行报告)** | 台架:NAND 里有真实事件记录、SD2506 电池域可控、104 主站可连 | 上板复核六件事:真记录翻页与掉电后保持、清除记录后对应页归零、上电一次看 `boot_count` +1、拔 RTC 电池后 `seq_state` 落 RESTARTED、IWDG 复位后 `rst_cause` 落 IWDG、主站连一次看 `conn_up` +1(模拟器侧这些记录文件无写入方、无 `boot_stats`、无 104 协议栈,黄金只拍得到空态「无记录」与固定假数据的显示口径) | 六个页面模块文件头「台架待补」段 + `../测试说明/模拟器差距清单.md` §2.3 开机账本一行 |
|
||||
| **UI 六页真机判据(记录 5 页 + 运行报告)** | 台架:NAND 里有真实事件记录、SD2506 电池域可控、104 主站可连 | 上板复核六件事:真记录翻页与掉电后保持、清除记录后对应页归零、上电一次看 `boot_count` +1、拔 RTC 电池后 `seq_state` 落 RESTARTED、IWDG 复位后 `rst_cause` 落 IWDG、主站连一次看 `conn_up` +1(模拟器侧这些记录文件无写入方、无 `boot_stats`、无 104 协议栈,黄金只拍得到空态「无记录」与固定假数据的显示口径) | 六个页面模块文件头「台架待补」段 + `../测试说明/专项验证/模拟器差距清单.md` §2.3 开机账本一行 |
|
||||
|
||||
**送检顺序不可倒过来**:产品构建当前要求 UA/UN/IA 的标定 VALID 全部置位才走保护判据。
|
||||
未完成标准源标定就送检,保护会表现为不动作。保持该闭锁,不用非标准源标定走捷径。
|
||||
|
||||
@@ -408,7 +408,7 @@ void vApplicationMallocFailedHook(void)
|
||||
|
||||
- defaultTask:静态 2776 > 实测 2136——静态是**上界**(最深分支未必走到),实测是**已走路径**。**判栈够不够看两者更坏者,做定栈优化看实测。**
|
||||
- netTask / uiTask / testTask / timeSyncTask / **ftpTask**:实测 > 静态——静态是**下界**(互递归、间接调用、ISR 上下文保存 ~100B 未计入)。ftpTask 最典型:优化前静态 2528 B(控制通道握手链)**低估了 950 B**,真实峰值 3480 B 只在 128KB STOR 传输时暴露 → **不跑真实业务就定栈 = 拍脑袋。** §4.1.4 静态化后静态 472 B / 实测 1184 B,两者重新收敛(差距回到 ISR/上下文量级)。
|
||||
- 本次可观测性的第一个产出不是数字而是**缺陷**:ftpTask 因就绪位被其它等待者消费而**从未启动**(21 端口一直无监听),修好后才有了上面这组数据——详见 `docs/测试说明/FTP_Test_Guide.md` §8.8。
|
||||
- 本次可观测性的第一个产出不是数字而是**缺陷**:ftpTask 因就绪位被其它等待者消费而**从未启动**(21 端口一直无监听),修好后才有了上面这组数据——详见 `docs/测试说明/板级测试/FTP_Test_Guide.md` §8.8。
|
||||
|
||||
要点与边界:
|
||||
|
||||
@@ -418,7 +418,7 @@ void vApplicationMallocFailedHook(void)
|
||||
- 帧宽榜直接点名宽度大户(自身帧):`s_append` 704 B(FIL 512 + 记录 64 + 时间戳)、`StartDefaultTask` 560 B(探针 `FIL __chk`)、`cfg_store_read`/`cfg_store_write_atomic` 576 B、LVGL 绘制 624/560/400 B——与 §4.1.4 的整改项对得上。**lftpd 三项已于 2026-09-21 静态化(§4.1.4),已退出帧宽榜前 15**(原 `handle_control_channel` 1104 B、`receive_file`/`send_file` 1088 B、`send_response` 800 B)。
|
||||
- **静态分析的天然盲区**:递归/互递归(LVGL widget 树、`layout_update_core`、`apply_theme` 等)与间接调用只能按 "Cycle" 近似,armlink 明确标注 `+ Unknown(Cycles, Untraceable Function Pointers)`。因此 uiTask 的 912 B 是**下限**(实测 3824 B),必须靠运行时水位。
|
||||
- testTask 在产品构建里只是 `osDelay` 空循环(168 B);2048 words 是给**存储套件构建**(`TEST_SUITE_STORAGE`)预留的,测套件时应重跑本脚本看该构建的静态值。
|
||||
- **测 ftpTask 的复现配方**:设备就绪后跑 `& '.venv\Scripts\python.exe' test/host/ftp_speed_test.py --size 128`(STOR 128KB + RETR + 逐字节比对),再按上面命令叠加串口日志出报告。**不要用裸 TCP 工具探测 21 端口**——CH395F 单客户端复用,探测会占掉唯一会话(见 `docs/测试说明/FTP_Test_Guide.md` §8.9)。
|
||||
- **测 ftpTask 的复现配方**:设备就绪后跑 `& '.venv\Scripts\python.exe' test/host/ftp_speed_test.py --size 128`(STOR 128KB + RETR + 逐字节比对),再按上面命令叠加串口日志出报告。**不要用裸 TCP 工具探测 21 端口**——CH395F 单客户端复用,探测会占掉唯一会话(见 `docs/测试说明/板级测试/FTP_Test_Guide.md` §8.9)。
|
||||
|
||||
#### 2026-10-10 复测:**不抬栈**把 defaultTask 从 FAIL 拉回 PASS(该项销项)
|
||||
|
||||
@@ -521,7 +521,7 @@ vApplicationAssertFailed` 共 103 行),而 `vApplicationAssertFailed` 钩子
|
||||
「端口没开」记成「又崩了一次栈」。判据与门都可执行:`scripts/stack_gate.py`(`--selftest` 14 条),它是
|
||||
**台架侧门禁**(每轮台架跑完必跑;Lead 裁定 2026-10-27:不接 pre-commit——提交时既无设备也无当轮日志,
|
||||
挂上去只会得到「永远 SKIP」或「拿上一轮日志判这一轮的码」,后者正是体积门禁那条假凭证的同族)。
|
||||
口径正文:`docs/测试说明/启动日志原子性复验流程.md` §5(三档表与门的细节都在那节)。
|
||||
口径正文:`docs/测试说明/专项验证/启动日志原子性复验流程.md` §5(三档表与门的细节都在那节)。
|
||||
本节口径与本文的运行时水位小节、静态硬线小节互指(同文件内引用,不再另标编号,避免跨文档串号)。
|
||||
|
||||
**取证纪律(本节方法的可复用模板)**:凡跨树/跨构建引用数字,必须同时钉**产物路径 +
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
|---|---|
|
||||
| 主机侧纯逻辑单测 | `test/host/iec104/`:APCI 重组/坏帧、STARTDT 握手、总召全流程(含 RBT/分片/预算)、COV、k/w 窗、t1/t2/t3(假时基)、遥控两段式与 PN、YK12 软压板两段转真 + 置脏(B7)、定值两段写 + set_sealed 后 selfcheck、C_RD(含本地项不可寻址)、C_CS(含闰年)、错地址/错类型 EVI;**板端默认源真实链**(ring→phasor→freq→meas 快照,非桩):值/品质透传、CLIPPED→IV、0x401D 绑频(收敛 ±0.02 Hz / 未新鲜 IV)、死区运行时化 + 2 点确认/回摆撤销、seq 去重(104 改读快照与频率点绑定,TC-IEC104-025~028)+ 运行参数段路由/两段式/RMW(TC-IEC104-029)+ `[comm]` 段真链(道G task-8,TC-IEC104-031~033:注册/出厂模板/沉降重载/带外自愈/setter 守卫/ca 端到端 = C_RD 正答与旧写死 ca=1 转 COT13+EVI);`test/host/iec104_serv/` 钉端口与 ca 取值来源(TC-I104SRV-001b/c);`test/host/cfg_file/` 钉段/键容量上限(TC-CONFIG-056/057);`test/host/run_par/`:[run_par] 注册/落盘往返/守卫/系数直通合法带(TC-RUNPAR-001~008);`test/host/prot_set/`:blob 往返 + 损坏整表拒绝(all-or-nothing)|
|
||||
| 静态门禁 | `iec104-unit-test` 钩子 + cppcheck/coding-standard |
|
||||
| 台架 | `@test` 锚点(104 服务启动/监听行);**PC 主站客户端 `test/host/iec104_master.py`(纯标准库,B6 2026-10-12 就绪)**:STARTDT/总召四组+actterm/C_SE 定值两段写→YX15·16 变位(COT=3)/恢复复归/YK11 两段正答/C_RD 读回,台架往返 **18/18 PASS**(证据 `../测试说明/boot_log_data/20261012_B6_iec104_roundtrip_log.txt`);**B7 持久化模式 `--b7-pre/--b7-post/--b7-mark/--b7-check`**(中间 ST-LINK 复位):YK12 两段投退→保护退出/联动、**定值与压板态跨复位保持**(含非默认 7.5 往返),**21/21 + 13/13 + 4/4+4/4 PASS**(证据 `../测试说明/boot_log_data/20261012_B7_iec104_persist_log.txt`);**B9 SOE 腿**(同工具同轮回归):自发 YX 断言 **M_SP_TB_1 带 ts**(工具解析 type 30/1 双型)+ FTP 下载 `/log/soe.log` 经 `test/host/soe/decode_soe.py` 解码断言(校验和/seq 单调/CP56↔epoch UTC 交叉),pre 21/21 + post 13/13 不回归;lib60870 级第三方全流程归 B10 |
|
||||
| 台架 | `@test` 锚点(104 服务启动/监听行);**PC 主站客户端 `test/host/iec104_master.py`(纯标准库,B6 2026-10-12 就绪)**:STARTDT/总召四组+actterm/C_SE 定值两段写→YX15·16 变位(COT=3)/恢复复归/YK11 两段正答/C_RD 读回,台架往返 **18/18 PASS**(证据 `../测试说明/测试数据/boot_log_data/20261012_B6_iec104_roundtrip_log.txt`);**B7 持久化模式 `--b7-pre/--b7-post/--b7-mark/--b7-check`**(中间 ST-LINK 复位):YK12 两段投退→保护退出/联动、**定值与压板态跨复位保持**(含非默认 7.5 往返),**21/21 + 13/13 + 4/4+4/4 PASS**(证据 `../测试说明/测试数据/boot_log_data/20261012_B7_iec104_persist_log.txt`);**B9 SOE 腿**(同工具同轮回归):自发 YX 断言 **M_SP_TB_1 带 ts**(工具解析 type 30/1 双型)+ FTP 下载 `/log/soe.log` 经 `test/host/soe/decode_soe.py` 解码断言(校验和/seq 单调/CP56↔epoch UTC 交叉),pre 21/21 + post 13/13 不回归;lib60870 级第三方全流程归 B10 |
|
||||
|
||||
## 8. V0.1 限制与待办(如实登记)
|
||||
|
||||
|
||||
+10
-10
@@ -3,7 +3,7 @@
|
||||
> **版本**:v1.7(已实施;修订史见文末「修订记录」)
|
||||
> **日期**:2026-10-26(v1.7:崩溃上报归一进单写者 + 多段裸发收口,道G task-26;v1.6:未注册期裸发加「行级单一所有者」,O1 第二个实例收口;v1.5 于 2026-10-24;初版 v1.0 于 2026-09-25)
|
||||
> **状态**:已实施并验证——`@build` 0 错误 0 警告、`@test` 硬件闭环 PASS(2026-09-25,见 §10);设计 2026-09-24 加固实施(当时位于 `Src/usart.c` USER CODE 区),2026-09-25 实现迁出至 `App/log/`(HAL 生成文件不含应用代码);同日写者任务体自 `Src/freertos.c` 迁至 `App/task/default_task.c`(与其余 5 任务文件同址归位)
|
||||
> **关联文档**:`项目架构总览.md` · `运行与自检记录设计说明.md`(姊妹模块:持久化日志,同一写者任务) · `测试说明/链路延迟测试说明.md`(D6 日志税 / 步骤 8 非阻塞日志,需求出处) · AGENTS.md「平台约束」
|
||||
> **关联文档**:`项目架构总览.md` · `运行与自检记录设计说明.md`(姊妹模块:持久化日志,同一写者任务) · `docs/测试说明/专项验证/链路延迟测试说明.md`(D6 日志税 / 步骤 8 非阻塞日志,需求出处) · AGENTS.md「平台约束」
|
||||
|
||||
## 1. 背景:实测故障与根因
|
||||
|
||||
@@ -210,7 +210,7 @@ sequenceDiagram
|
||||
|
||||
#### 4.4.1 行级单一所有者(2026-10-26 道G task-23,O1 第二个实例收口)
|
||||
|
||||
**台架一手证据**(`docs/测试说明/boot_log_data/20261026_prod_console_interleave_evidence.txt`,同一镜像 `fw 戳 Oct 26 2026 16:27:01`,排除构建差异):
|
||||
**台架一手证据**(`docs/测试说明/测试数据/boot_log_data/20261026_prod_console_interleave_evidence.txt`,同一镜像 `fw 戳 Oct 26 2026 16:27:01`,排除构建差异):
|
||||
|
||||
| 启动 | 方式 | 结果 |
|
||||
|---|---|---|
|
||||
@@ -230,7 +230,7 @@ sequenceDiagram
|
||||
- **新增 API**:`dbg_console_tx_begin()` / `dbg_console_tx_end()`(同样非阻塞:拿不到返回 0,调用方照发即可)——给"一条行分多段裸发"的调用方收口用。本模块只提供 API 与主机单测;调用点改造已随 **task-26(2026-10-26)** 落地,但**只落在任务态**:`App/util/task_watchdog.c` 的 STALL 行(正文 + CRLF 共 2 段)包进一次独占,调用点一律写 `(void)dbg_console_tx_begin();`、不拿返回值分支;`Src/freertos.c` 栈溢出/断言钩子与 `Src/stm32f4xx_it.c hard_fault_report` 三处**刻意不包**,理由见下面那条 bullet。
|
||||
- **异常态的整行性不靠凭证**(task-26 语义,必须写清免得误读):`IPSR != 0` 时 `dbg_console_tx_begin()` **返回 1 但并不持有凭证**(异常上下文绝不允许等待或失败)。所以四个 Fault 与栈溢出钩子的整行性来自「**Fault 优先级 -1、外设中断 ≥5、任务全冻结** ⇒ 没有第二个写者能跑进来」。唯一残留 = **被抢占任务已在移位寄存器里的那 ≤1 个字节**,它出现在故障行**之前**,不影响 `[ERR]` 前缀可 grep。已明确否决「发送循环逐字节检查让位标志」那类修法——那会把正在发的启动日志行截断,换不来什么。
|
||||
- **崩溃上报也归一(task-26)**:`Src/stm32f4xx_it.c` 的 `hard_fault_report`(四个 Fault 共用,原本 **14 段**裸发)**自己调 `HAL_UART_Transmit`**,是绕过本模块行级独占的**第三个写者**;现改为 `dbg_console_write_raw`(**但刻意不包 `tx_begin()/tx_end()`**,见下面两条 bullet)。三条理由(详见该函数 `hard_fault_write` 头):① HAL 超时判据是 `HAL_GetTick()`(TIM7 停摆则永不成立,第 8a/8b 轮实证;正常上限也是 0xFFFF ≈ 65 s),本口是 DWT/指令计数双硬上界;② HAL 状态机在僵尸通道(ORE 锁存)下恒快速失败 ⇒ **`[ERR]` 崩溃行整条蒸发**,而它正是台架「出现即不通过」的判据来源;③ `huart1.Instance == NULL` 时本口立即短路,绝不解引用地址 0(机器判据 = `TC-CONLOG-100`/`TC-CONLOG-102`)。同处删除输出后的 `HAL_Delay(200)`:本口等到 TC 才返回,延时冗余,且 `HAL_Delay` 也依赖 TIM7 tick——tick 停摆会**卡在复位之前**(启动段 IWDG 尚未启动,无兜底)。
|
||||
- **⚠ 行为变化:让路会改变行序与时间戳顺序(不是回归)**。让路的整行落进环形缓冲,因此它在流里**位置后移**(最多一轮 drain,实测毫秒级)。台架 2026-10-26 复验 5 次(1 次烧录 + 4 次仅复位)稳定观察到 **`[NAND_FTL] Initializing NAND FTL...` 排在 `[PROT] uncalibrated -> protection blocked …` 前一行**;而缺陷形态下的旧一手记录正好相反(PROT 在前,NAND 缺 `[20` 行首,`docs/测试说明/boot_log_data/20261026_prod_console_interleave_evidence.txt`)。原因:谁先抢到整行所有权谁立即发完,另一方整行让路延后;常态下 `defaultTask` 的存储 bring-up 行先开火,`protectTask` 的未标定闭锁边沿要等 adcTask 首次给出标志才产生。**所以**:① **行序不是判据**——它是竞态结果,两台设备/两次启动都可能不同;② **时间戳先后也不是判据**——让路行带的是它**自己产生时刻**的时间戳(刻意不重打,见上面判据⑦),于是可能出现"后出现的那一行时间戳更早";③ 正确的判据写法是**按整行逐字节锚定**两行各自是否完整(本次台架就是这么判的,5/5 命中),不要锚定相对顺序、也不要锚定"某行必须在另一行之前"。
|
||||
- **⚠ 行为变化:让路会改变行序与时间戳顺序(不是回归)**。让路的整行落进环形缓冲,因此它在流里**位置后移**(最多一轮 drain,实测毫秒级)。台架 2026-10-26 复验 5 次(1 次烧录 + 4 次仅复位)稳定观察到 **`[NAND_FTL] Initializing NAND FTL...` 排在 `[PROT] uncalibrated -> protection blocked …` 前一行**;而缺陷形态下的旧一手记录正好相反(PROT 在前,NAND 缺 `[20` 行首,`docs/测试说明/测试数据/boot_log_data/20261026_prod_console_interleave_evidence.txt`)。原因:谁先抢到整行所有权谁立即发完,另一方整行让路延后;常态下 `defaultTask` 的存储 bring-up 行先开火,`protectTask` 的未标定闭锁边沿要等 adcTask 首次给出标志才产生。**所以**:① **行序不是判据**——它是竞态结果,两台设备/两次启动都可能不同;② **时间戳先后也不是判据**——让路行带的是它**自己产生时刻**的时间戳(刻意不重打,见上面判据⑦),于是可能出现"后出现的那一行时间戳更早";③ 正确的判据写法是**按整行逐字节锚定**两行各自是否完整(本次台架就是这么判的,5/5 命中),不要锚定相对顺序、也不要锚定"某行必须在另一行之前"。
|
||||
|
||||
- **哪些调用点包整行独占、哪些刻意不包(task-26 定案,不是遗漏)**:**任务态**多段裸发才包(现网唯一实例 = `App/util/task_watchdog.c` 的 STALL 行:既不空转,也不挂在 configASSERT 子树上)。**异常态与终点路径一律不包**——`hard_fault_report`(14 段)、`vApplicationStackOverflowHook`(3 段)、`vApplicationAssertFailed`(5 段):① `IPSR != 0` 时 `tx_begin()` 放行且**不持有**凭证、`tx_end()` 又只对持有者有效 ⇒ 包上是**纯空转**,保护本来就来自"Fault 优先级 -1 + 外设 ≥5 + 任务全冻结";② 这三处都挂在 `configASSERT` 子树上(`vPortEnterCritical/vPortExitCritical` 会进断言钩子),在那上面每加一句,armlink 就把它**乘进每一条含临界区的任务链**——实测包上时 `con_tx_release` 子树 24→152 B、发送环单趟贡献 128→208 B,`defaultTask`/`netTask`/`iec104Task` 三条链各 **+80 B**,`iec104Task` margin 从 1,096 被顶到 **1,016 < 1,024** ISR 底线(栈记账 FAIL);③ 崩溃行发完就 `NVIC_SystemReset()`,"归还所有权"没有下游读者。断言钩子那对 begin/end 还曾只包住"有文件名"一支(else 分支不在窗口内)——半套独比亚没有更误导人。
|
||||
- **⚠ 结构性失效模式(这条环是我们自己造的,随时可能复活)**:断言钩子为了留痕要写控制台,而写控制台若要进内核临界区,就形成 `taskEXIT_CRITICAL() ⇒ vPortExitCritical() ⇒ configASSERT() ⇒ vApplicationAssertFailed() ⇒ dbg_console_write_raw ⇒ …⇒ 再进临界区` 这条**静态互递归环**;armlink 不是按运行时报错,而是把它**记进每一条含临界区的任务链**——一次性污染 9 条链的栈记账,且没有任何编译期或运行期告警。为此本模块的裸发/入环/取还凭证一律用 PRIMASK 窗口(`CON_CRIT_ENTER/EXIT`,机器判据 = `TC-CONLOG-015` 的 `con_crit_enter == 0` + `TC-CONLOG-015b` 两种屏蔽水位恒 0)。**判据留给后来人**:任何人在 `con_tx_*` / `con_ring_try` / `dbg_console_write_raw` / `dbg_console_drain` 的窗口里再放一处 `taskENTER_CRITICAL()` 或任何含 `configASSERT` 的内核 API,这条环立刻复活;提交前必须跑 `scripts/stack_report.py`(且**注明数字出自哪棵工作树、哪次构建**——本仓今天两次错误归因都是拿错了树的数字)。反向风险同样要记(task-38):若哪天把 `configASSERT` 裁成空宏,每条链"回收"的 80~90 B 是**静态记账口径变化,不是固件变好**,不得写成优化收益。
|
||||
@@ -250,7 +250,7 @@ sequenceDiagram
|
||||
2. 判据**只用原子性**,不碰 `[ERR]` 计数:① 崩溃行**一整行**逐字节完整(`[ERR] MEMFAULT PC=… LR=… xPSR=… R0..R3=… CFSR=… HFSR=…` 字段齐全、无邻居行字节插入);② 该行在本次启动日志里**恰好出现一次**(既不丢也不重);③ `CONSOLE dropped` = 0。首个字符应为 `[`;前面若出现 ≤1 个移位寄存器残留字节,记为已知残余,不判失败。
|
||||
3. ⚠ **不得在同一条腿要求 `[ERR]` = 0**:崩溃上报本身就以 `[ERR]` 起头,在同一路径上要求「无 `[ERR]`」等于要求这条路径别工作(本次就是这么被台架纠正的)。`[ERR]` 零命中的判据只属于腿 B 之外的**常规回归腿**(3~5 次仅复位不重烧 + 两行整行锚定)。
|
||||
4. **故意复位的注入腿不得并入「连续 N 次仅复位不重烧」的计数**:注入会主动 `NVIC_SystemReset()`,混进常规序列会把正常行为判成异常(栈溢出钩子同理)。两条腿分开跑、分开记台账。
|
||||
5. `@test` 在注入腿**只在命令行运行时**放宽(故障注入的既有台架口径见 `docs/测试说明/实机测试实施指南.md` §4,其中已写明"故障注入用例会复位设备多次 → 确认设备非在用/非已部署"):放宽 `--forbidden` / `--max-boot-count`;**不改仓库配置**(改了就等于把"永不出崩溃日志"设成期望状态)。
|
||||
5. `@test` 在注入腿**只在命令行运行时**放宽(故障注入的既有台架口径见 `docs/测试说明/板级测试/实机测试实施指南.md` §4,其中已写明"故障注入用例会复位设备多次 → 确认设备非在用/非已部署"):放宽 `--forbidden` / `--max-boot-count`;**不改仓库配置**(改了就等于把"永不出崩溃日志"设成期望状态)。
|
||||
|
||||
### 4.5 `fputc` 重定向(MicroLIB `printf`)
|
||||
|
||||
@@ -407,25 +407,25 @@ sequenceDiagram
|
||||
|
||||
- `项目架构总览.md` —— 六层分层 / 启动时序 / 6 任务(写者任务与就绪屏障位置)
|
||||
- `运行与自检记录设计说明.md` —— sys_log 持久化日志(姊妹模块:同写者任务、不同通道)
|
||||
- `测试说明/链路延迟测试说明.md` —— D6 日志税 / 步骤 8 非阻塞日志(需求出处与 09-22 丢行实证)
|
||||
- `测试说明/自动化测试流程.md` —— `@test` 标记体系(Required / Forbidden 模式,`[ERR]` 语义)
|
||||
- `docs/测试说明/专项验证/链路延迟测试说明.md` —— D6 日志税 / 步骤 8 非阻塞日志(需求出处与 09-22 丢行实证)
|
||||
- `docs/测试说明/流程与规范/自动化测试流程.md` —— `@test` 标记体系(Required / Forbidden 模式,`[ERR]` 语义)
|
||||
- AGENTS.md —— 平台约束(内核前禁内核对象 / C 堆禁令 / 事件位语义 / 内存预算)
|
||||
|
||||
## 附录:日志静默观察项 × 步骤 8 合并评估(2026-10-25,道F 批 2 / task-18,零代码改动)
|
||||
|
||||
> 评估任务(登记簿曾登记的**日志静默观察项**,已销项;残余动作是「与步骤 8 合并评估」):该观察项
|
||||
> (49s 全系统日志静默,2026-09-22 L3 台架世代号 181)与步骤 8(日志非阻塞化,需求
|
||||
> 出处 = `docs/测试说明/链路延迟测试说明.md` §9.2/§10.2)的合并性价比判定。
|
||||
> 出处 = `docs/测试说明/专项验证/链路延迟测试说明.md` §9.2/§10.2)的合并性价比判定。
|
||||
> 评估纪律 = 结论即交付,不顺手重构;本节结论:**无需最小实现**(不新增代码)。
|
||||
|
||||
### A.1 步骤 8:目标已由「单写者形态」在**生产者侧**达成
|
||||
|
||||
步骤 8 要治的是阻塞式日志税(L10 实测 `logtax_line` **4402 µs/行**,`fputc` 逐字节
|
||||
@115200 阻塞调用方整行)与并发丢行(实测 `docs/测试说明/链路延迟测试说明.md` §9.2:
|
||||
@115200 阻塞调用方整行)与并发丢行(实测 `docs/测试说明/专项验证/链路延迟测试说明.md` §9.2:
|
||||
必检标记被竞态吞)。2026-09-24 单写者
|
||||
改造正是同一需求落的方案(§1/§2 G1-G5):
|
||||
|
||||
| 步骤 8 子项(需求出处 `docs/测试说明/链路延迟测试说明.md` §10.2 第 9 条) | 原案 | 现状(代码实证) |
|
||||
| 步骤 8 子项(需求出处 `docs/测试说明/专项验证/链路延迟测试说明.md` §10.2 第 9 条) | 原案 | 现状(代码实证) |
|
||||
|---|---|---|
|
||||
| `fputc` → 环形缓冲 | 串口 TX 环形 | ✅ 4KB BSS 环 + 事件位唤醒(§4.1/§4.2);生产者 = 亚微秒~µs 级临界区整行入环(≤192B 拷贝),日志税较 4402µs/行**降 3 个量级** |
|
||||
| TX 中断/DMA | 非阻塞发送 | ❌ 有意不做(轮询单写者,D4);复议时机见 A.2 |
|
||||
@@ -456,7 +456,7 @@ D4 否决理由对现状仍逐条成立(115200 发送率低、日志行稀疏
|
||||
dbg_console_tx_fault / dbg_console_tx_timeout` + syslog 的
|
||||
`queue full, drop` / `preboot full, drop` / `hold-over drop`
|
||||
(`App/log/sys_log_mcu.c`);任何“静默丢行”现形为 `[ERR]` → `@test` FAIL。
|
||||
- 判据①(复现 49s 并定位):V5 30min 未复现;实测(`docs/测试说明/实机测试实施指南.md` §7.2)
|
||||
- 判据①(复现 49s 并定位):V5 30min 未复现;实测(`docs/测试说明/板级测试/实机测试实施指南.md` §7.2)
|
||||
运行期 >10s 静默 24 处**全部落在 e02_probe 窗口、长度 ≈28s**——其
|
||||
同源阻塞机制(`drop_conn` 同步占用 netTask 400-600ms)已随登记式拆链改造修复
|
||||
(登记式拆链,`docs/网络/网络自愈架构设计.md` §4.6)。本评估补充一个此前
|
||||
|
||||
@@ -310,7 +310,7 @@ flowchart TD
|
||||
- `err` 是落盘失败或 CRC 自弃次数(**字节数不符就算失败**,见 §5.2);`ovf` 是冷却期丢弃的触发数;`drop` 是冻结窗口丢掉的录波点数;
|
||||
- **实际落地形态(逐字)**:打印点在 `App/task/adc_task.c`:782 行,格式串 `"wave: seg=%lu armed=%u src=%s pts=%u err=%lu ovf=%lu drop=%lu"`——**字段名与顺序就是上面的模板**(台架与 PC 脚本按行名 grep,动它就断脚本);`src` 取 M(手动)/ P(保护)/ T(定时自抓)/ `-`(本次上电还没触发过);`armed` 只在 FREEZE 与 SEALED 为 1(COOL 期只挡新触发不录新段,画进 armed 会被台架误读);`seg` 是累计**成功回执**的段数、不是轮转号;`err` = 落盘失败 + SEALED 滞留超时自弃(含 §5.2 第四条的 ring abandoned 判废),由环内计数收口,落盘道不数第二份账。`err` 与 `ovf` 的**已知容差**(lead 裁定 2026-10-29,不修只入档):这两个计数是跨上下文的读-改-自增(`ovf` 由任意上下文的拒绝路径加、`err` 由 adcTask 的滞留自弃与 defaultTask 的落盘失败分别加),本层双端编译、不许引 FreeRTOS / CMSIS 的临界区内在函数,所以并发拒绝或并发失败时**理论上可能少计一次**。定性为**观测计数的已知容差**:只用于趋势与判读,**不作为任何判据的唯一依据**——要坐实「冷却期内确实来了第二次触发」,同时看 `armed` 与那一刻 `/log/start.log` 的时刻。契约原文见 `App/algo/wave_ring.h` 文件头「观测计数的已知容差」段;
|
||||
- 只在原先静默的黑洞处补锚点,别重复已有步骤——每条 DBG 日志约 90 B Flash 加 216 B 栈(`AGENTS.md` 的日志与工具链节);
|
||||
- 该行已同步进 `docs/测试说明/ADC前端注入验证流程.md` 的读数出口表(2026-10-29;同一张表还登记了段文件出口与 PC 侧读段工具)。
|
||||
- 该行已同步进 `docs/测试说明/专项验证/ADC前端注入验证流程.md` 的读数出口表(2026-10-29;同一张表还登记了段文件出口与 PC 侧读段工具)。
|
||||
|
||||
---
|
||||
|
||||
@@ -319,7 +319,7 @@ flowchart TD
|
||||
| 层 | 内容 |
|
||||
|---|---|
|
||||
| 主机侧纯逻辑单测(新增,进 `test/host/`) | ① 环:预触发与后触发点数、冻结与解冻、冷却丢弃计数;② 段格式编解码往返,含 CRC 不符、零长度、字节数不符三条失败路径;③ 触发状态机三条来路(手动 / 保护 / bench)。**环与格式必须是纯逻辑**(不碰寄存器、不碰 RTOS)才能这样测——这是 `App/algo/` 既有分层纪律 |
|
||||
| PC 侧工具的定性 | `test/host/wave_read.py` 是 **bench 工具**(`test/host/` 下的 loose .py,先例 `test/host/ftp_capture.py`),**不是**主机单测套件 → 不建 `run_unit_test.py`、不加 pre-commit 专属钩子(专属钩子默认不补,按 Lead 裁定 2026-10-27);它自带 `--selftest` 就是它的自带回归,跑法与四个子命令见 `docs/测试说明/ADC前端注入验证流程.md` §4 |
|
||||
| PC 侧工具的定性 | `test/host/wave_read.py` 是 **bench 工具**(`test/host/` 下的 loose .py,先例 `test/host/ftp_capture.py`),**不是**主机单测套件 → 不建 `run_unit_test.py`、不加 pre-commit 专属钩子(专属钩子默认不补,按 Lead 裁定 2026-10-27);它自带 `--selftest` 就是它的自带回归,跑法与四个子命令见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §4 |
|
||||
| 跨工具链分叉(实证,写进来是为了下一个模块别重踩) | 两份录波 .c 只 include 自身头(链上只有 stdint.h)时,ARMCC 报 22 条 identifier "NULL" is undefined;而主机 MSVC / gcc 会传递性把 stddef.h 拉进来,**主机单测完全照不出这个分叉** → 新增模块需要用 NULL 就自己 include stddef.h(与 `App/algo/sample_ring.c` 同口径,别塞公共头) |
|
||||
| 板级 | 信号发生器注 1 V / 50 Hz → 手动一段 → FTP 拉回 → PC 脚本量出周波数、幅值、极性与注入一致;再把 PC 重算的基波有效值与板上 `meas:` 与 104 浮点 YC 对表。**判据只量四样:周波数、幅值、极性、钉轨路数——不比绝对相位**(理由见 §4.2「段内点序」:触发瞬间在工频周期内任意落点,段字节里没有绝对时间参考;真要比相位必须让发生器给同步触发,本波不做)。**钉轨对表的合格判据 = 头位图 ⊇ 实测钉轨路数,且差异必须能由注入条件解释**——因为 `clip_mask` 是按来源派生的链路可信性标记(§6.2 偏移 24 行),不是本段实测值:只加直流或小幅注入时那五路本就不该钉轨,硬取等式会假红。**同段另起一条强观察项**:V0.1 下这五路若在做**交流注入**时反而没钉轨,先怀疑接线或该路根本没被驱动——这是告警面,不是失败面(等式仍作为默认尺子留在 PC 侧 `shape --strict` 里,因为它有这个信号价值;要放行差异用那条判据的解释权,不靠改尺子)。**§5.2 第四条的板级观察项(代码与单测面已有、板级未测)**:bench 连续自抓期间人为把卷占住 2 s 以上(例如同一段跑 FTP 大文件读),看串口 `wave:` 行的 `err` 是否加一、是否只出现**一条** `[ERR] … seg drop: ring abandoned` 留痕(不是每拍刷屏)、且段号不推进(下一段仍写同号文件) |
|
||||
| UI | `ui-verify` 五步;回放页入 `ui-golden` 黄金参考(**参考图一旦入库只能改代码对齐,禁止刷参考掩盖**);新叶走 `gen_menu.py` 重生成 + 字库链 |
|
||||
@@ -328,7 +328,7 @@ flowchart TD
|
||||
| 板级(读路径耗时,2026-10-29 补) | 进回放页后**连续切段 + 连续切道**,读 `task_prof` 里 uiTask 的单轮工作耗时峰值与 800 ms 窗的余量;**不要为此新加埋点**(现成读数够用)。判读:峰值贴着窗走就是读路径该再加节流(先想缓存与分次,别去动心跳窗) |
|
||||
| 图与生成物 | 本设计文档的配图生成器受 `generated-fresh` 逐字节幂等约束;脚本与产物同一笔提交 |
|
||||
|
||||
**bench 定时自抓的红线**:定周期自抓在 1 kHz / 8 路下每 2 s 一段,每 5 分钟就是一轮 NAND 写。**长时间挂着它白烧写次数**,而 dhara 的坏块记账是持久代价、普通恢复清不掉(`AGENTS.md` 测试构建节,`docs/测试说明/存储维护与容量恢复.md`)→ 定时模式必须**默认关闭 + 有时长上限 + 启动时打一次告警**,用完立刻回产品构建。
|
||||
**bench 定时自抓的红线**:定周期自抓在 1 kHz / 8 路下每 2 s 一段,每 5 分钟就是一轮 NAND 写。**长时间挂着它白烧写次数**,而 dhara 的坏块记账是持久代价、普通恢复清不掉(`AGENTS.md` 测试构建节,`docs/测试说明/专项验证/存储维护与容量恢复.md`)→ 定时模式必须**默认关闭 + 有时长上限 + 启动时打一次告警**,用完立刻回产品构建。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
> 描述,已清理;实施史与逐次决策见 §10 与文末变更记录,未删)。
|
||||
> **相关文档**:
|
||||
> [`运行与自检记录设计说明.md`](运行与自检记录设计说明.md)(复位记录与 `selftest.log`)、
|
||||
> [`../测试说明/看门狗单元测试说明.md`](../测试说明/看门狗单元测试说明.md)(主机侧纯逻辑单测,判定状态机)、
|
||||
> [`../测试说明/实机测试实施指南.md`](../测试说明/实机测试实施指南.md)(故障注入台架流程)、
|
||||
> [`../测试说明/单元测试/看门狗单元测试说明.md`](../测试说明/单元测试/看门狗单元测试说明.md)(主机侧纯逻辑单测,判定状态机)、
|
||||
> [`../测试说明/板级测试/实机测试实施指南.md`](../测试说明/板级测试/实机测试实施指南.md)(故障注入台架流程)、
|
||||
> [`../架构设计/项目启动顺序管理.md`](../架构设计/项目启动顺序管理.md)(启动时序与就绪屏障)、
|
||||
> [`../测试说明/ST-LINK_CLI_复位使用说明.md`](../测试说明/ST-LINK_CLI_复位使用说明.md)(复位语义)、
|
||||
> [`../测试说明/测试工具/ST-LINK_CLI_复位使用说明.md`](../测试说明/测试工具/ST-LINK_CLI_复位使用说明.md)(复位语义)、
|
||||
> 《项目审查与优化建议报告》(本模块缺口的立项出处;该条已修复并按「修复即销项」从报告删除,**完整记录即本文**;报告本身 2026-10-25 已删除)
|
||||
|
||||
---
|
||||
@@ -445,7 +445,7 @@ snapshot == required → miss_streak=0、证据门闩复位、喂狗
|
||||
| 门禁触发 | 门禁接入 | ✅ | 改 `App/util/task_watchdog*.{c,h}` 或 `test/host/watchdog/**` 触发 |
|
||||
| 模拟器 | `--watchdogtest` | ⏳ **已降级不做** | 位图与判定逻辑已由主机单测覆盖;模拟器不编译本模块 |
|
||||
|
||||
用例细节见 [`../测试说明/看门狗单元测试说明.md`](../测试说明/看门狗单元测试说明.md);故障注入流程见 [`../测试说明/实机测试实施指南.md`](../测试说明/实机测试实施指南.md) §4。
|
||||
用例细节见 [`../测试说明/单元测试/看门狗单元测试说明.md`](../测试说明/单元测试/看门狗单元测试说明.md);故障注入流程见 [`../测试说明/板级测试/实机测试实施指南.md`](../测试说明/板级测试/实机测试实施指南.md) §4。
|
||||
|
||||
---
|
||||
|
||||
@@ -649,7 +649,7 @@ enter/exit 段还能读出"此刻仍在段内已多久"——**永久阻塞的
|
||||
> **复合停喂判据**问题(本窗缺 UI、下窗缺 IEC104/FTP 串成 16:24/16:28 两起误申报,
|
||||
> `mg=877/918` 均为复合链而非单任务链)已由 **v1.5 按位分账**根治:判据见 §2.2/§3.2/
|
||||
> §5.3,回归钉 = 主机单测 TC-WATCHDOG-017(交替缺席零申报、持续喂狗)/ 018(同位 8
|
||||
> 连击必报 + 恢复后账本重启)。原始日志判读材料:`docs/测试说明/boot_log_data/`
|
||||
> 连击必报 + 恢复后账本重启)。原始日志判读材料:`docs/测试说明/测试数据/boot_log_data/`
|
||||
> (megawin 同日摘录入库,gz)。
|
||||
|
||||
---
|
||||
@@ -700,7 +700,7 @@ enter/exit 段还能读出"此刻仍在段内已多久"——**永久阻塞的
|
||||
| 2026-09-29 | **第二次重生成验证 + 机制修正** | 审计脚本**实测有效**(准确检出 5 处覆盖)。⚠️ **关键发现**:CubeMX 换了一代中断函数模板(旧 `HardFault_Handler`/`HardFault_Report` 自造区 → 新函数体内 `HardFault_IRQn 0`/`W1_HardFault_IRQn 0`),**"生成区外的自造标记区"同样不被保留**——上一轮假设被证伪。据此升级恢复方案:报告实现迁入 `USER CODE BEGIN 0`(标准保护位);Handler 本体改为生成区整函数替换(`#define` 改名保留生成实体,链接器自动移除,`.map` 已验证)+ `HARD-FAULT-ANCHOR` 锚点。同步修正审计脚本(`hardfault-handler` 改 `wholefile` + 锚点)、`UNPROTECTED_LEGACY` 清单、§10.1/§10.2 全文。`@build` 0 错误 0 警告 |
|
||||
| 2026-09-29 | **3 个 Fault 升级为崩溃采集** | `MemManage` / `BusFault` / `UsageFault` 由空 `while(1)`(死机静默)升级为与 `HardFault` 同一套采集:生成区整函数替换(各带独立锚点 `MEMFAULT-ANCHOR` / `BUSFAULT-ANCHOR` / `USAGEFAULT-ANCHOR`)+ `#define X X_Gen` 改名保留生成实体(链接器各移除 2 字节)。新增 `fault_handler_enable()` 使能 `SHCSR` 后三者(默认只开 HardFault,不开则故障被升级、看不出根因),声明入 `Inc/stm32f4xx_it.h`、调用在 `app_main_init()` 第一行。因 ARMCC `__asm` 取不到 C 数据符号,改为 per-fault C 入口 `fault_entry_{hard,mem,bus,usage}` 带故障名调 `hard_fault_report(tag, frame)`。**刻意不启用** `UNALIGN_TRP` / `DIV_0_TRP`(避免把普通 bug 升级成死机)。审计脚本新增 `fault-handlers-3` / `fault-handler-enable` 两项、`UNPROTECTED_LEGACY` 清掉 3 个 Fault(WARN 2→1)、清单 16→18 项。`@build` 0 错误 0 警告;审计 18 通过 / 1 警告 / 0 失败 |
|
||||
| 2026-10-01 | **查证 `fault_handler_enable()` 的 CubeMX 可行性** | 用户问"能否通过 CubeMX 配置"→ **否**。查 CubeMX 安装目录模板源码得三重证据:① `tpl_main_c.ftl` 的 `MX_NVIC_Init()` 只在 `systemHandler=="false"` 时生成 `HAL_NVIC_EnableIRQ`,而 `NVIC-STM32F417_Modes.xml` 中三个 Fault 都标 `Y`(=systemHandler)→ 永不生成使能代码;② **全部模板中 `SHCSR` 只出现 1 次**且是 MPU 清理的 `&= ~MEMFAULTENA`(禁用),**无任何 `\|=` 置位**;③ `.ioc` 无 MPU(`Mcu.IP` 列表),且 `HAL_MPU_Enable` 只置 `MEMFAULTENA` 一位。实测印证:`HAL_MspInit()` 里三个 Fault 一行代码都没生成。结论:只能手工写,但属 **USER CODE 区**(`USER CODE BEGIN 1` 区)→ 重生成不丢,有审计项兜底。另新增警示:`.ioc` 的 `NVIC.MemoryManagement_IRQn=true` **不代表已使能**(第 1 段只是"向量可见")。写入 §10.2 与四个 Fault 采集小节 |
|
||||
| 2026-10-01 | **新增 §7.3 主机侧单元测试** | 硬件访问收敛到薄平台层(`App/util/task_watchdog.h` 末段声明 3 个 `__weak` 钩子:喂狗/启动/取 tick),MCU 端行为零变化(`@build` 0/0)。新建 `test/host/watchdog/`(`watchdog_test.c` 39 用例 + `run_unit_test.py` MSVC 运行器 + `stub/` 三桩头),`#include` 生产源码以保证测的是真代码。挂 pre-commit `watchdog-unit-test` 钩子。新增 `docs/测试说明/看门狗单元测试说明.md`;`App/util/README.md`、`test/host/README.md`、`测试开发标准流程.md`(新增主机侧纯逻辑单测层)同步。顺带改善:`s_last_tick` 由函数局部 static 提为文件 static(可测性 + 模块状态归一)。§5.1 文件表与 §10 步骤表登记;§7.2 S1 优先级降低(位图逻辑已由 U1 覆盖) |
|
||||
| 2026-10-01 | **新增 §7.3 主机侧单元测试** | 硬件访问收敛到薄平台层(`App/util/task_watchdog.h` 末段声明 3 个 `__weak` 钩子:喂狗/启动/取 tick),MCU 端行为零变化(`@build` 0/0)。新建 `test/host/watchdog/`(`watchdog_test.c` 39 用例 + `run_unit_test.py` MSVC 运行器 + `stub/` 三桩头),`#include` 生产源码以保证测的是真代码。挂 pre-commit `watchdog-unit-test` 钩子。新增 `docs/测试说明/单元测试/看门狗单元测试说明.md`;`App/util/README.md`、`test/host/README.md`、`测试开发标准流程.md`(新增主机侧纯逻辑单测层)同步。顺带改善:`s_last_tick` 由函数局部 static 提为文件 static(可测性 + 模块状态归一)。§5.1 文件表与 §10 步骤表登记;§7.2 S1 优先级降低(位图逻辑已由 U1 覆盖) |
|
||||
| 2026-10-02 | **P0 根因修复:IWDG 超时被静默配成复位默认值(比设计短 5 倍)** | round 3~8 反复出现的"空 STOR(0 字节截断)→ IWDG 误复位"**根因不是"poller 自身停摆"**。真因:`Src/iwdg.c` 为实现**延后启动**(§4.5 决策 C)删掉了 `HAL_IWDG_Init()`(`IWDG-DEFER-START-ANCHOR`),而 `HAL_IWDG_Init()` 是**唯一**会把 `hiwdg.Init.Prescaler/Reload` 写进 IWDG 寄存器的路径——删掉后 `MX_IWDG_Init()` 只填结构体,`WD_IWDG_PRESCALER`/`WD_IWDG_RELOAD` 沦为**死宏**,寄存器停在**复位默认值** `PR=0`(÷4)/`RLR=4095`。实测(SWD 回读)实际超时 = 4×4096/LSI ≈ **349~512 ms**,而设计是 64×1250/LSI ≈ **1701~2498 ms**。两个后果:① `WD_MISS_TOLERANCE`(8×100ms=800ms)**永远等不到**就被 IWDG 复位 → **停喂判定分支成死代码**(这正是 §7"STALL 从未执行"的真正原因,当时据此误判为"poller 停摆");② 任何 >400ms 的心跳缺口都直接误复位(空 STOR 的 FTL flush 使 NET/FTP/UI 心跳缺 ~400ms)。**修复**:`wd_platform_start()`(`__weak`,**不在 CubeMX 生成区**,重生成不丢)补上按设计值配置:解锁(`KR=0x5555`) → `PR` → 等 `SR.PVU` 清 → `RLR` → 等 `SR.RVU` 清 → `KR=0xCCCC`(不等同步会静默丢弃后写的那只,SWD 实测)。`.map` 证实 `Removing stm32f4xx_hal_iwdg.o(i.HAL_IWDG_Init), (94 bytes)`,故这是全固件**唯一**写 PR/RLR 的点。**验证**:SWD 现场改回设计值后,同一空 STOR 由 **5/5 复位 → 100% 成功**;固件烧录后 3 次开机回读均为 `PR=4/RLR=1249`。`@build` 0/0;本地 CI 静态门禁+主机侧纯逻辑单测全绿(278/278 断言) |
|
||||
| 2026-10-03 | **V2/V4/V5 台架验收闭环(N-03 销项)** | 三用例全部通过。**V2 任务饿死**:`netTask` 循环插 `while(1)` → 800ms 声明 `[WD] task stall: mask=0x00000001 req=0x00000037`,≤2.5s 触发 IWDG 复位(`reset cause: IWDG`,`RCC_CSR=0x24000000`)。⚠️ 首轮实测**不复位**(stall 已声明、`miss` 累至 1157≈115s):根因是**停摆证据落盘自身喂狗**——`wd_stall_evidence()`→`sys_log_evidence()` 在停喂窗口里每 100ms 轮都写 NAND(`/log/wdev.log` + `SYSLOG_RUN` flush 诱导),经 `nand_ftl_wd_feed()` **直接重装 IWDG**,"停喂"语义被证据机制抵消。修复:加 `s_stall_evidenced` **每 episode 门闩**(每轮停摆只落盘一次,此后不再触碰 NAND)→ 复测复位正常。**V4 关中断死循环**:`__disable_irq()` 后插 `while(1)` → 设备每 ~4.9s 稳定复位(20+ 周期,`reset cause: IWDG`),证实 IWDG **独立于中断**(PRIMASK 屏蔽 TIM7/SysTick/PendSV 仍能复位)。**V5 长期不误杀**:FTP 512KB 上/下传 + `e02_probe` 网络探针持续 **30 min** → **120/120 次 FTP 传输全 PASS(MATCH)、零 IWDG 复位**(唯一复位为起始烧录的 `software (NVIC_SystemReset)`)。Step 4 堆告警全程未触发(`min_ever=4728 B` > 3072 B)。**遗留观察(已登记 `待处理内容.md`)**:V5 期间 44 次 `task stall`(`mask=0x00000001` 持续 ≥800ms)**100% 与 `e02_probe` 的 30s 挂起客户端→`time_sync` 掉线+监听重建(`listen FAIL`×2,约 4s)重合**;隔离实验证实「仅 FTP(无探针)120s = 0 次 stall」→ 该停摆为**探针场景专属**,非一般负载误杀。因缺口(~1s)< IWDG 最坏超时(1701ms)而未复位,与 §4.3 包含关系一致 |
|
||||
| 2026-10-09 | **IWDG 延后启动由审计兜底升级为 USER CODE 区:不再需要每次重生成后手工删那一句** | 起因是提问"能否在初始化函数下方的自定义区里先反初始化"。查证:**反初始化不可行**——IWDG 一旦启动就**无法停止**(参考手册:唯一停止手段是复位),故不能在 `IWDG_Init 2` 区撤销。改用等价且免手工的做法:`Src/iwdg.c` 的 `USER CODE BEGIN 0`(标准保护位)放空实现 `iwdg_deferred_start()` + `#define HAL_IWDG_Init(a_h) iwdg_deferred_start(a_h)`,把**本编译单元里**那句生成调用 `HAL_IWDG_Init(&hiwdg)` 改名到空实现 → 生成区保持 CubeMX 原样、**重生成零 diff**。`.map` 证实 `Removing stm32f4xx_hal_iwdg.o(i.HAL_IWDG_Init), (94 bytes)`、`iwdg.o(i.MX_IWDG_Init)` 只引用 `.bss`(空实现被编译器消掉)。审计项 `iwdg-defer-start` 相应由 `wholefile`+锚点注释改为 `protected`(区 `0`)+ 代码符号断言(`iwdg_deferred_start` / `#define HAL_IWDG_Init`——`protected` 比对前会剥掉注释,锚点注释不能当断言)。§10.2 硬教训②与审计兜底存量清单同步:审计兜底只剩 4 个 Fault Handler 实体(同一招可根治,尚未做)。`@build` 0 错误 0 警告;审计 21 通过 / 1 警告 / 0 失败 |
|
||||
|
||||
@@ -344,7 +344,7 @@ ENTER 进入选中地址行 → `↑/↓` 调活动字节(0..255 **环绕**)
|
||||
| 主题 | 文档 |
|
||||
|---|---|
|
||||
| CH395F 已知陷阱 | `docs/问题记录/CH395F_Trap_Records.md` |
|
||||
| 网络测试指南 | `docs/测试说明/CH395F_Test_Guide.md` |
|
||||
| 网络测试指南 | `docs/测试说明/板级测试/CH395F_Test_Guide.md` |
|
||||
| 启动顺序 / 就绪屏障 | `docs/架构设计/项目启动顺序管理.md` |
|
||||
| 项目分层架构 | `docs/架构设计/项目架构总览.md` |
|
||||
| 内容页框架(含网口设置页) | `docs/UI设计/内容页架构.md` |
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
|---|---|------|
|
||||
| `App/log/sys_log.h` | 共享 | 公共 API + 记录格式常量 + 行拆分内联函数(无 OS 依赖) |
|
||||
| `App/log/sys_log_mcu.c` | MCU | FatFS 后端:待发队列(启动前静态数组 + FreeRTOS 消息队列)、defaultTask 落盘、容量截断、上电/重启分类 |
|
||||
| `sim/sim_syslog.c` | 模拟器 | 宿主文件后端(CWD 下与七类一一对应的 `sim_*.log` 七份),直接追加,`time()` 时间戳;**没有队列与丢弃**,`syslog_post_quiet()` 在本端等价于 `syslog_post()`(两端差异登记在 `docs/测试说明/模拟器差距清单.md` §2.2) |
|
||||
| `sim/sim_syslog.c` | 模拟器 | 宿主文件后端(CWD 下与七类一一对应的 `sim_*.log` 七份),直接追加,`time()` 时间戳;**没有队列与丢弃**,`syslog_post_quiet()` 在本端等价于 `syslog_post()`(两端差异登记在 `docs/测试说明/专项验证/模拟器差距清单.md` §2.2) |
|
||||
| `Drivers/BSP/UI/ui_standby.h/.c` | 共享 | 空闲检测 + 待机屏(屏幕覆盖层:保存/还原前屏与焦点) |
|
||||
| `Drivers/BSP/UI/ui_page_runlog.h/.c` | 共享 | 运行记录内容页描述符(动态行,数据源 = sys_log API) |
|
||||
| `Drivers/BSP/UI/ui_page_selftest.h/.c` | 共享 | 自检记录内容页描述符(同上) |
|
||||
|
||||
@@ -585,7 +585,7 @@ void adc_cfg_init(void)
|
||||
| 2026-09-15 | v1.10:**配置引擎属主任务变更** netTask → defaultTask(P1-3 跨任务竞态修复,P1-5 一并落地)——① 上电加载移入 defaultTask 的 STORAGE_READY 屏障之前(屏障语义 = 卷挂载 + 配置就绪);② UI 保存改跨任务交接:`net_cfg_save_request()`("待保存"标志 + `SYS_EVT_CFG_SAVE` 事件唤醒)→ defaultTask `net_cfg_save_run()` 执行写盘、成功触发"立即应用"(`SYS_EVT_NET_RECONFIG` → netTask 重建),保存行随交接状态显示 ENTER/WAIT/OK/ERR(写盘期间的新请求重位置位不丢失);③ 2s poll 收敛 defaultTask——引擎静态状态仅单任务触碰,竞态在结构上消除;④ netTask 只读 RAM 副本、不触碰配置文件引擎;D15-③ 单写者、§5.1~5.4 时序图与并发矩阵同步;双端构建 0/0、UI 五步门禁全绿 |
|
||||
| 2026-09-18 | v1.11:**P0-1 修复(临时缓冲改走平台堆)**——共享核心 4 处 `malloc`(读缓冲 4,097B / 模板输出 5,120B / 外科保存 Pass1 副本 + 输出 5,120B)此前落在 **MicroLIB C 堆**上,而该堆由 `startup_stm32f407xx.s` 的 `Heap_Size EQU 0x200` 限定为 **512 B**,真机必然分配失败 → 配置加载静默回落工厂默认(模拟器用宿主 CRT 堆,两端不一致,故双端 0 警告 0 错也照不出来)。① `cfg_file_store` 新增 `cfg_store_alloc/cfg_store_free/cfg_store_heap_free` 后端三件套(MCU = `pvPortMalloc/vPortFree`,与 `lftpd_io.c` 同模式;模拟器 = `malloc/free`),共享核心不再出现 C 库分配符号;② 新增编译期堆峰值预算 `CFG_HEAP_BUDGET = 10240B`(typedef 负数组实现,ARMCC 5 C99 无 `_Static_assert`),放大 `CFG_FILE_MAX_LEN`/`CFG_OUT_MAX` 直接编译失败;③ 四条失败路径(load 读失败 / 模板写失败 / 保存分配失败 / 保存写盘失败)增 `syslog_post(SYSLOG_SELFTEST, …)` 上报,不再只留串口行;`load: OK` 行附带 `heap free` 实测值;④ 属主任务注释同步为 defaultTask。map 复核:`malloc.o` 不参与链接、`Removing startup_stm32f407xx.o(HEAP), (512 bytes)`,静态区 126,584 → **126,064 B**(余 4,488 → **5,008 B**);双端 0 错 0 警、`--cfgtest` PASS |
|
||||
| 2026-09-22 | v1.12:**E-01 超长守卫根治**(错误码传播审计第一档 #3,commit d030cb0)——poll 的"超长=损坏"检查写在截断后读长(`s_load_file` 读长钉死 4096)上**恒假=死码**,超长文件被截断当有效解析 → 界外静默回工厂默认 → 基线粘住 → 用户配置销毁链。① poll 沉降分支判定改用 `cfg_store_stat` 真实 `st.size` 且**先于读取**,超长走"工厂默认 + 重建模板 + `cfg poll oversized` 自检留痕",**刻意不触发段回调**(避免按工厂 IP 重建网络造成静默失联,保留 FTP 修复通道,保存/重启收敛)② `s_surgical` 输出上限 `CFG_OUT_MAX`(5120) 收紧至 `CFG_FILE_MAX_LEN`(4096),超限走溢出中止路径(原文件不动 + `cfg save overflow` 自检)——消除"合法写出 4097~5120B 文件 = 下次开机销毁"的雷 ③ `s_write_doc` 唯一落盘闸口硬拒 >4096B(结构性保证)④ load 超长分支补 `cfg load oversized` 自检;`cfg_file.h` v1.2 契约同步;模拟器 cfgtest 新增两回归锁(4160B 伪造 → poll 判损坏重建;4000B 注释文件 → save 拒写且原文件未动)。**台架验证暴露并修复**:`cfg_store_write_atomic` MCU 后端 `f_rename` 对已存在目标返回 `FR_EXIST` 不覆盖 → 设备端一切"目标存在的覆盖写"(UI 保存/模板重建)静默失败、仅首启建文件成功——v1.9 已为模拟器后端修过同款(MSVC `rename()` C1117),MCU 侧漏了对称修复;修复 = rename 前先 `unlink` 目标(commit 70f1cc8)。双端 0 错 0 警、cfgtest PASS、台架 FTP 5047B 用例 poll/load 双路径自愈 PASS(重建 523B 工厂模板 + selftest 留痕 + 不掉线)、`@test` 默认闭环 PASS、ST-LINK 全片回读一致 |
|
||||
| 2026-10-03 | v1.13:**真机验证 PASS(A1 闭环)**——v1.11 的 P0-1 堆分配改造在真机上验证通过:`[CFG] load: OK (523B, heap free 8840B)`(**经 FreeRTOS 堆分配**,即 512B C 堆约束的验收点);Forbidden `FAIL`/`[ERR]` 零命中;FTP 改配置 IP→`192.168.1.101` 后**复位即加载生效**(`[NET_CFG] load: OK ip=192.168.1.101` + 芯片 `IP_INF` .101 + 21 端口探测可达),原档恢复后复测回 .100。真机全闭环 `@test` PASS 7/7。**台架步骤与判据见 `测试说明/实机测试实施指南.md` §3 / §10** |
|
||||
| 2026-10-03 | v1.13:**真机验证 PASS(A1 闭环)**——v1.11 的 P0-1 堆分配改造在真机上验证通过:`[CFG] load: OK (523B, heap free 8840B)`(**经 FreeRTOS 堆分配**,即 512B C 堆约束的验收点);Forbidden `FAIL`/`[ERR]` 零命中;FTP 改配置 IP→`192.168.1.101` 后**复位即加载生效**(`[NET_CFG] load: OK ip=192.168.1.101` + 芯片 `IP_INF` .101 + 21 端口探测可达),原档恢复后复测回 .100。真机全闭环 `@test` PASS 7/7。**台架步骤与判据见 `docs/测试说明/板级测试/实机测试实施指南.md` §3 / §10** |
|
||||
| 2026-10-04 | **P0-1 真机独立复跑 PASS(二次确认,代码零改动)**——`@build` 0/0(增量,无源文件新于镜像)→ `@test` **VERDICT PASS(rc=0)**:`[2026-10-04 00:01:21][CFG] load: OK (523B, heap free 8840B)` + `[NET_CFG] load: OK ip=192.168.1.100`,Forbidden `FAIL`/`ERROR`/`HardFault`/`[ERR]` 零命中,`selftest: no fault record`(先清掉 2026-10-02/03 故障注入窗口遗留的 67 条台账)→ ST-LINK 全片回读 `No difference found`(`0x08000000~0x08040F9B`)。**本次为 `待处理内容.md` §4.1「待验证」唯一未闭环项(P0-1)的收口**,该节现已清空 |
|
||||
| 2026-10-10 | v1.14:**删除旧档 NCFG 迁移(D10 撤销)**——`Drivers/BSP/NETCFG/net_cfg_legacy.{c,h}` 整体移除、`cfg_store_legacy_path()` 撤销(MCU / 模拟器后端与主机单测 `test/host/cfg_file/cfg_file_test.c` 同步删除),`net_cfg_load` 不再调用 `net_cfg_legacy_migrate()`;旧档 `/cfg/netcfg.bin` 若存在则被**忽略**(不读、不删、不迁移),配置回落工厂默认。理由:该一次性路径把整条配置写链挂进启动期调用图,defaultTask 静态最坏栈链 **+600 B**(该链整体 5312 → 2776 B,另三个杠杆见 `docs/内存管理/RAM使用分析与优化方案.md`),而本仓库不存在携带旧档的设备。连带影响:`App/util` 的 CRC-16/MODBUS 失去唯一调用者(现为零调用者);模拟器 `--cfgtest` 不再覆盖迁移场景;§2 D10 / §3.5 / §4.2 / §5.1 / §6.2 / §6.4 / §7 / §9 / §11.1 同步 |
|
||||
| 2026-10-26 | v1.15:**新增 `[comm]` 段(道G task-8,「UI 补齐」波次里的非 UI 前置项)**——`App/protocol/iec104/iec104_comm.h/.c` 配对模块(104 公共地址 / 监听端口 2 键,getter 合法带自愈,adc_cal 先例);内核前 `iec104_comm_init()` 注册([adc_cal] / [run_par] 同「先注册后 load」契约);生效 = **改后重启**(不挂回调、不新增事件位,区别于 [network] 免重启重建);段占位 5→6 / 8,键表与主站地址不做理由 → `docs/子系统设计/网络配置说明.md` §3.6;机器钉 = `test/host/cfg_file` TC-CONFIG-056/057(段/键上限)+ `test/host/iec104` TC-IEC104-031~033(模板/重载/带外/ca 端到端)
|
||||
|
||||
+15
-1
@@ -14,6 +14,7 @@
|
||||
|---|---|
|
||||
| **目录名一律不含空格** | 空格迫使脚本/链接/CI 处处加引号,且 URL 编码形态(`UI%20设计`)极易被漏改(2026-09-25 起强制;全库已无含空格目录) |
|
||||
| **按领域归入子目录** | 顶层不放散落 `.md`;新领域先建无空格子目录,再在 [`README.md`](README.md) 登记 |
|
||||
| **子目录内文件过多时再分一层(只多分一层)** | `docs/测试说明/` 2026-11-01 起按用途分 `流程与规范/` `单元测试/` `板级测试/` `专项验证/` `测试工具/` `测试数据/` 六个子目录,**归层判据 → `docs/测试说明/README.md` §2**。再往下分不会让引用更短,只会让按目录递归的门禁 glob 更难核对 |
|
||||
| 现有目录 | `架构设计/` `子系统设计/` `算法/` `网络/` `测试说明/` `代码规范/` `内存管理/` `问题记录/` `环境与部署/` `UI设计/` `硬件平台/` `芯片手册/` `images/` |
|
||||
|
||||
### 1.1b 代码目录的 README.md
|
||||
@@ -160,11 +161,24 @@
|
||||
|
||||
它覆盖的引用形态:反引号根相对引用、Markdown 链接(根相对与文档相对都按原风格改写)、**图片链接的 `../` 层级换算**(§3.2 那条实证坑由它兜住)、`#include "x.h"` 裸文件名、`MDK-ARM/*.uvprojx` 的 `<FilePath>`、`simulator/CMakeLists.txt` 的 `${PROJECT_ROOT}/…` 与 `${VAR}/…`、以及 skill / 脚本 / 配置里的路径串。
|
||||
|
||||
**它管不到的三件事**(脚本会在结尾提示):
|
||||
**它管不到的五件事**(脚本会在结尾提示):
|
||||
|
||||
1. **昵称式引用**(「内存方案 §2.1」)与正文里的裸文件名散文 → 落盘后 `git grep -n '<旧文件名>'` 扫一遍;
|
||||
2. **生成物**(`docs/images/引用关系图.*`)不改写 → 重跑 `& 'tools\refgraph\gen_refgraph.bat'`;
|
||||
3. 改的是 `.c/.h` 且**新增了目录** → 还要把目录加进 `uvprojx` 的 `<IncludePath>`(→ `new-source-file` skill),随后 `@build` 验证。
|
||||
4. ⚠ **搬整目录时会改写目录内部文件的内容**(2026-11-01 `docs/测试说明/` 分层实测):脚本把内部文件里"不是路径的斜杠片段"
|
||||
当成旧目录前缀的引用 —— `1/1 PASSED` 被改成 `test_data/1/1 PASSED`、日志日期占位 `[----/--/-- --:--:--]` 也被插前缀。
|
||||
**一手证据与测试数据不接受这种改写** → 落盘后用 `git show HEAD:<旧路径>` 的原始字节逐文件还原,并核对
|
||||
`git diff --stat` 里**不该出现**"数据目录内容变更"(只该有改名)。
|
||||
5. ⚠ **搬整目录时,目录内部文件指向外部的 `../` 出链不补层级**(目录变深一层 → 静默断链;搬**单个**文件不受此影响,
|
||||
出链会正确加一层)→ 落盘后逐条核对数据目录内部 README 的出链。
|
||||
|
||||
> 同批实测的另两条工具侧事实:新路径**以 `/` 结尾**才是"挪进该目录并保留文件名"(见上例注释);`--apply` 收尾会自动跑
|
||||
> `check_doc_links.py --all`,在带 junction 联接(`.venv`、`simulator/SDL2`)的任务工作树里会把联接目录扫成**假红**,
|
||||
> 所以树内批量搬迁要加 `--no-verify`,全库 `--all` 复核留到主工作树跑(→ `docs/环境与部署/并行任务工作树方案.md`)。
|
||||
> 另:脚本结尾的 `ℹ` 提示在 GBK 代码页会抛 `UnicodeEncodeError` 让进程**以退出码 1 收场**(此时 `git mv` 与改写**已经落盘**,
|
||||
> RC 与真实结果相反)→ 2026-11-01 已在 `scripts/rename_ref.py` 内把 stdout/stderr `reconfigure(encoding="utf-8")`,
|
||||
> 与 `check_ids.py` / `check_doc_links.py` / `check_test_traceability.py` 同法。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -590,7 +590,7 @@ if (nand_ftl_format() == 0) {
|
||||
8. **内存布局与 DMA/CCM 约束** — FreeRTOS 堆(含全部任务栈)已迁至 **CCM `0x10000000`**(64KB,直连 M4 零等待),但 **DMA1/DMA2 物理不可达 CCM**。GD5F 驱动 `GD5F_DMA_THRESHOLD = 1024`:栈上的小缓冲(dhara meta 读 132B、`dhara_nand_is_free` 64B)一律走 **CPU 轮询**、绝不经 DMA;页级大块(2048)才走 DMA 且源/目的**全部是文件作用域静态缓冲**(落 SRAM)。新增任何 DMA 收发缓冲必须①文件作用域静态②大小≥阈值③确认落 SRAM。违反任一条 = 静默数据损坏(CCM 首轮扩容实验实证)。换料注意:克隆片可能缺 SRAM3(CCM),必须重测。
|
||||
9. **LVGL 绘制缓冲越界护栏** — LVGL 9.3.0 对 I1(1bpp) 整帧渲染会在其算出的 `stride*h`(160×160/8=3200) 之后**多写 1 个字节**,紧邻 `g_ui_draw_buf` 之后的 `.bss`(如 `ui_menu_view` 的 `s_frame_box`)指针最低字节被打成 `0xFF` → 野指针 → HardFault(`PC=lv_obj_get_scroll_y`)。`ui_port.c` 的 `g_ui_draw_buf` 已预留 `UI_DRAW_BUF_GUARD=32` 字节护栏吸收该越界写(逻辑尺寸仍按 `UI_FB_SIZE` 上报,渲染数学不变)。**勿删护栏、勿把缓冲缩到与邻接 `.bss` 紧邻**。Lib/LVGL 为第三方不改。
|
||||
10. **FatFs 严格 8.3 短名** — 本移植 `Lib/FatFs/ffconf.h` 为 `FF_USE_LFN=0`,**只支持严格 8.3 短名**:主名 ≤8 字符、扩展 ≤3 字符、**不得以点开头**(2026-09-20 台架实证,`.fschk` 无限重格式化事故根因)。
|
||||
- **推论(2026-10-24 补齐,代码侧唯一入口 `s_is_selfheal_code()`)**:既然名字/参数类错误码在 8.3 配置下**必然重现**(同名同因),它们就**严禁**被归进任何"卷/文件坏了"的自愈触发集——否则自愈会退化成反复删自己的数据。本仓落点:`App/log/sys_log_mcu.c` 的触发集只收 `FR_DISK_ERR` / `FR_INT_ERR` / `FR_NO_FILESYSTEM` / `FR_DENIED`,`FR_INVALID_NAME` / `FR_NO_PATH` / `FR_NO_FILE` / `FR_INVALID_OBJECT` 一律立即失败(逐码依据 + `Lib/FatFs/ff.c` 行号写在该函数上方资料块;`App/log/soe_store.c` 侧同源取更保守子集并互指)。**本条拦下的真事**:旧集合含名字类码,后果是路径/卷异常期间**每轮排空删一次自己的历史日志且永远修不好**,由主机单测照出(TC-SYSLOG-101 / 102、TC-SOESTORE-022b),详见 `docs/测试说明/主机单测覆盖率口径.md` §9「第 1 轮修复处置」。。`.fschk` 会被 `ff.c` 的 `create_short` 把「点之后」当扩展域解析而超限 → `f_open` 恒返 `FR_INVALID_NAME`(6);这是**纯 RAM 里的名字判定,不碰盘**。`ff.c` `create_short` 全部拒绝点的地方已加 DEBUG 打印:`[ERR][FATFS] SFN reject (原因) seg='名字片段' bad_ch=坏字符`——非法名字调用看开机日志即可定位。自愈类逻辑**严禁**把名字/参数类错误码(`FR_INVALID_NAME` 等)归入"卷损坏"触发集(整卷重格式化不可逆)。补充:含冒号 `:` 的名字被 FatFs 先解析为**盘符前缀** → `f_open` 返回 `FR_INVALID_DRIVE`(11) 而非 `FR_INVALID_NAME`(6);两者都属合法拒绝(测试用例须同时接受)。
|
||||
- **推论(2026-10-24 补齐,代码侧唯一入口 `s_is_selfheal_code()`)**:既然名字/参数类错误码在 8.3 配置下**必然重现**(同名同因),它们就**严禁**被归进任何"卷/文件坏了"的自愈触发集——否则自愈会退化成反复删自己的数据。本仓落点:`App/log/sys_log_mcu.c` 的触发集只收 `FR_DISK_ERR` / `FR_INT_ERR` / `FR_NO_FILESYSTEM` / `FR_DENIED`,`FR_INVALID_NAME` / `FR_NO_PATH` / `FR_NO_FILE` / `FR_INVALID_OBJECT` 一律立即失败(逐码依据 + `Lib/FatFs/ff.c` 行号写在该函数上方资料块;`App/log/soe_store.c` 侧同源取更保守子集并互指)。**本条拦下的真事**:旧集合含名字类码,后果是路径/卷异常期间**每轮排空删一次自己的历史日志且永远修不好**,由主机单测照出(TC-SYSLOG-101 / 102、TC-SOESTORE-022b),详见 `docs/测试说明/单元测试/主机单测覆盖率口径.md` §9「第 1 轮修复处置」。。`.fschk` 会被 `ff.c` 的 `create_short` 把「点之后」当扩展域解析而超限 → `f_open` 恒返 `FR_INVALID_NAME`(6);这是**纯 RAM 里的名字判定,不碰盘**。`ff.c` `create_short` 全部拒绝点的地方已加 DEBUG 打印:`[ERR][FATFS] SFN reject (原因) seg='名字片段' bad_ch=坏字符`——非法名字调用看开机日志即可定位。自愈类逻辑**严禁**把名字/参数类错误码(`FR_INVALID_NAME` 等)归入"卷损坏"触发集(整卷重格式化不可逆)。补充:含冒号 `:` 的名字被 FatFs 先解析为**盘符前缀** → `f_open` 返回 `FR_INVALID_DRIVE`(11) 而非 `FR_INVALID_NAME`(6);两者都属合法拒绝(测试用例须同时接受)。
|
||||
11. **FA_OPEN_APPEND 陷阱 / 短写** — `FA_OPEN_APPEND`(0x30) = `FA_OPEN_ALWAYS|FA_SEEKEND`,**不含 `FA_WRITE`(0x02)**——不带写位打开的文件 `f_write` 恒返回 `FR_DENIED`(7)(这是当年 `/log` 写失败的真根因);追加写必须写 `FA_WRITE | FA_OPEN_APPEND`(2026-09-20 台架实测,`Lib/FatFs` 移植版)。该移植的 `f_write` 在簇分配失败时返回 `FR_OK` + 短写(**没有错误码**)→ 判失败必须校验写回的字节数。标志位为**旧式编号**:`FA_READ`=0x01 / `FA_WRITE`=0x02 / `FA_CREATE_NEW`=0x04 / `FA_CREATE_ALWAYS`=0x08 / `FA_OPEN_ALWAYS`=0x10 / `FA_OPEN_APPEND`=0x30 / `FA_SEEKEND`=0x20(`ff.c` 内部定义),与上游 FatFs R0.14 不同,**勿照抄上游代码示例**。
|
||||
12. **崩溃可观测性(勿屏蔽)** — 已开启 `configCHECK_FOR_STACK_OVERFLOW=2` + `configUSE_MALLOC_FAILED_HOOK` + HardFault 现场报告(`Src/stm32f4xx_it.c`:裸 UART 打印 PC/LR/xPSR + CFSR/HFSR/BFAR/MMFAR 后复位,对照 `.map` 定位符号)。defaultTask **1024** words、testTask **2048** words 是**实测下限,勿降**。开机日志出现 `[ERR] STACK OVERFLOW task=` / `[ERR] HARDFAULT ...` / `MALLOC FAILED` 是精确定位线索,禁止屏蔽或降级。
|
||||
13. **BBT 恢复模式** — 运行期坏块会随 TC-STORAGE-03 注入累积;当介质被**误标脏**(如 DMA 误打 CCM 栈导致随机块被写坏并持久化)时,打开 `test/board/storage_test.h` 的 `ENABLE_STORAGE_RECOVERY_TESTS` 编译**恢复构建**,testTask 会执行 `gd5f2gq5ue_bbt_rebuild()`(出厂扫描清除运行期误标)+ `nand_ftl_format()` 清账后复位。恢复后容量回到基线(即扣除 BBT 保留池后的正常容量,非出厂裸容量)。
|
||||
@@ -644,7 +644,7 @@ LPN 与原始码的位置**就地分类并打印(`ftl_err_name()` 给可读名
|
||||
| dhara 错误 | 归类 | 处置上为什么不同 |
|
||||
|---|---|---|
|
||||
| `ECC` / `TOO_BAD` | `BSP_ERR_CRC` | 位翻转不可纠或页太坏:**是页级问题**,读重试 / 由 dhara 换页,不代表卷坏 |
|
||||
| `JOURNAL_FULL` / `MAP_FULL` | `BSP_ERR_NO_SPACE` | 介质还健康,是 **journal / 映射层块池见底**:该走容量恢复(`../测试说明/存储维护与容量恢复.md`),此时重格式化只是把问题推回去 |
|
||||
| `JOURNAL_FULL` / `MAP_FULL` | `BSP_ERR_NO_SPACE` | 介质还健康,是 **journal / 映射层块池见底**:该走容量恢复(`../测试说明/专项验证/存储维护与容量恢复.md`),此时重格式化只是把问题推回去 |
|
||||
| `BAD_BLOCK` / `RECOVER` / `NOT_FOUND` / `CORRUPT_MAP` / 越界 | `BSP_ERR_IO` | 映射或介质**完整性**故障:保卷 + 上报,不许自愈重格式化 |
|
||||
|
||||
- 这条分类与真空白卷判据是同一条纪律的两端:那边规定"只有扫描全程 I/O 干净且无
|
||||
|
||||
+3
-3
@@ -220,8 +220,8 @@ flowchart TB
|
||||
|
||||
**单连接约束**:CH395F 配置为 8 Socket(索引寻址)+ TCP Server 单连接(`set_fun_para(0x08)`,bit3 SOCKET_CLOSE;bit0 保留必须为 0),Socket 0 复用监听与数据通道;FTP / 对时 / 远程显示 / IEC104 四个 TCP 服务**串行**占用连接,连接断开后自动回到 LISTEN。人机显存的另一路出口(屏板)走 USART1 串口、不经 TCP——显存**一份三出**:屏板(主)/ :7003(网络镜像)/ 模拟器(同源像素)。
|
||||
|
||||
> **FTP 启动门(2026-09-21 修复)**:`ftpTask` 必须等 `NET_READY` **且** `STORAGE_READY`(两位均 `NoClear`)才 `lftpd_start`——此前就绪位被其它等待者消费,FTP **静默不监听**(详见 §2.2 与 `docs/测试说明/FTP_Test_Guide.md` §8.6)。
|
||||
> **单客户端实测注意**:同一时刻只服务 1 个会话,旧会话异常断开后经 `net_listener` 重建监听(实测恢复窗 p50 **208 ms**,n=30;口径见 `docs/网络/网络自愈架构设计.md`)。测试脚本必须内置连接重试(`test/host/ftp_up_dl_test.py`、`test/host/ftp_regression.py` 已内置),且**不要用裸 TCP 工具探测 21 端口**(探测会占掉唯一会话,见 `docs/测试说明/FTP_Test_Guide.md` §8.7)。
|
||||
> **FTP 启动门(2026-09-21 修复)**:`ftpTask` 必须等 `NET_READY` **且** `STORAGE_READY`(两位均 `NoClear`)才 `lftpd_start`——此前就绪位被其它等待者消费,FTP **静默不监听**(详见 §2.2 与 `docs/测试说明/板级测试/FTP_Test_Guide.md` §8.6)。
|
||||
> **单客户端实测注意**:同一时刻只服务 1 个会话,旧会话异常断开后经 `net_listener` 重建监听(实测恢复窗 p50 **208 ms**,n=30;口径见 `docs/网络/网络自愈架构设计.md`)。测试脚本必须内置连接重试(`test/host/ftp_up_dl_test.py`、`test/host/ftp_regression.py` 已内置),且**不要用裸 TCP 工具探测 21 端口**(探测会占掉唯一会话,见 `docs/测试说明/板级测试/FTP_Test_Guide.md` §8.7)。
|
||||
> **阻塞模型(2026-10-14 SEND 二期落地)**:阻塞 recv/send 经 `net_pending` 挂起请求表续作,调用方铁律 `sent < len`(末块写完即返回、不得登记挂起);架构与五路语义见 `docs/网络/Net层阻塞模型架构设计.md`,监听重建/沉降隔离/周期对账见 `docs/网络/网络自愈架构设计.md`。
|
||||
> 2026-10-14 实测:FTP 回归连续 19 次 11/11;`ftp_integrity_test` 20 轮 × 64 KB STOR/RETR SHA-256 20/20 一致,吞吐稳定 ≈80 KB/s。
|
||||
|
||||
@@ -391,7 +391,7 @@ flowchart LR
|
||||
| 看门狗 / CubeMX 重生成存活方法论 | `docs/子系统设计/看门狗设计说明.md` §10 |
|
||||
| RAM 预算与优化 | `docs/内存管理/RAM使用分析与优化方案.md` |
|
||||
| 栈/内存观测工具 | `scripts/stack_report.py`(Keil 静态调用图 × 串口 `[STACK]` 水位,判定取两者更坏者)· `scripts/ram_report.py`(.map 静态占用)—— 用法与基线见内存方案 §4.0.6 |
|
||||
| FTP 功能与陷阱 | `docs/测试说明/FTP_Test_Guide.md` §8.6(启动门)/ §8.7(单客户端)· 脚本 `test/host/ftp_up_dl_test.py`、`test/host/ftp_regression.py`、`test/host/ftp_integrity_test.py` |
|
||||
| FTP 功能与陷阱 | `docs/测试说明/板级测试/FTP_Test_Guide.md` §8.6(启动门)/ §8.7(单客户端)· 脚本 `test/host/ftp_up_dl_test.py`、`test/host/ftp_regression.py`、`test/host/ftp_integrity_test.py` |
|
||||
| UI 设计架构 / 内容页 / 菜单 | `docs/UI设计/UI_设计架构.md` · `内容页架构.md` · `菜单页面设计.md` |
|
||||
| UI 数据供给契约(rt/par/info 三帧) | `docs/UI设计/UI_数据供给设计说明.md` |
|
||||
| RemoDispBus 远程显示协议(:7003) | `docs/UI设计/RemoDispBus协议与接收设计说明.md` |
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
# 测试说明目录导航
|
||||
|
||||
> 本目录放**测试文档与测试采集数据**,2026-11-01 起按**用途**分六个子目录(原先 25 篇文档
|
||||
> 与 3 个数据目录平铺在一层,找文档靠记忆、命名靠约定)。
|
||||
> **全量索引与每篇文档的内容说明在 [`docs/README.md`](../README.md) §6**(同一事实只在一处详述,
|
||||
> 本文件不重复那些描述),这里只回答两件事:**东西该放哪一层**、**每层现在有什么**。
|
||||
|
||||
## 1. 结构与职责
|
||||
|
||||
```
|
||||
docs/测试说明/
|
||||
├── 流程与规范/ 测试开发的标准动作、门禁决策表、测试文档模板(3 篇)
|
||||
├── 单元测试/ 主机侧纯逻辑单测的说明 + 跨全部套件的覆盖率口径(9 篇)
|
||||
├── 板级测试/ 上板测试:芯片/模块测试指南 + 实机测试实施流程(5 篇)
|
||||
├── 专项验证/ 针对一个问题或一次复验的台架专项流程、存储恢复操作(5 篇)
|
||||
├── 测试工具/ PC 侧工具用法:串口助手、ST-LINK_CLI 烧录与复位(3 篇)
|
||||
└── 测试数据/ 测试跑出来的原始证据:boot_log_data/ m2_data/ m3_data/
|
||||
```
|
||||
|
||||
**归层的分界线是"这份文档随什么一起演进"**:跟着测试**方法**走 → 流程与规范;跟着**主机侧
|
||||
单测代码**走 → 单元测试;跟着**真机套件与硬件**走 → 板级测试;跟着**一次结论**走(写完即定稿
|
||||
的专项)→ 专项验证;跟着**一个工具**走 → 测试工具;不是文档而是**证据** → 测试数据。
|
||||
|
||||
## 2. 归层判据(新文档该放哪)
|
||||
|
||||
| 你手上的东西 | 去处 | 判据 |
|
||||
|---|---|---|
|
||||
| 任何测试都要遵守的流程、命名、门禁口径 | `流程与规范/` | 它约束**别的测试文档**怎么写 |
|
||||
| `test/host/<模块>/` 那套主机侧单测的说明(用例数、断言点、抓出的缺陷) | `单元测试/` | 跑它不需要真机;文件名用 `<模块>单元测试说明.md` |
|
||||
| 需要真机/台架、对应 `test/board/` 套件或某颗芯片的验收步骤 | `板级测试/` | 涉及硬件接线、烧录、板端标记;模块指南命名 `<芯片>_Test_Guide.md` |
|
||||
| 针对**一个具体缺陷或一次复验**的验证动作(非常跑套件)、或一类恢复操作 | `专项验证/` | 有明确的"做完就结束"边界,结论沉淀进模块文档/问题记录 |
|
||||
| 讲一个 PC 侧工具怎么用(命令、参数、排障) | `测试工具/` | 主体是工具本身,不是被测对象 |
|
||||
| 测试产出的原始数据(JSON、串口片段、二进制快照) | `测试数据/<采集批次目录>/` | 它是一手证据,不是说明 |
|
||||
|
||||
判据冲突时按这个顺序裁决:**是否需要真机执行** → 是则 `板级测试/`;否则**是否只服务一次专项
|
||||
结论** → 是则 `专项验证/`;否则按**对象类型**(单测说明 / 工具 / 流程)归层。拿不准就放
|
||||
`专项验证/` 并在提交说明里写明理由——`专项验证/` 是唯一允许"先收下再迁移"的层。
|
||||
|
||||
## 3. 现有文件清单(按子目录)
|
||||
|
||||
| 子目录 | 文件 |
|
||||
|---|---|
|
||||
| `流程与规范/` | `测试开发标准流程.md` · `自动化测试流程.md` · `测试文档模板规范.md` |
|
||||
| `单元测试/` | `看门狗单元测试说明.md` · `系统时钟单元测试说明.md` · `开机账本单元测试说明.md` · `配置文件单元测试说明.md` · `ADC输入层单元测试说明.md` · `相量层单元测试说明.md` · `卷锁单元测试说明.md` · `时间同步单元测试说明.md` · `主机单测覆盖率口径.md` |
|
||||
| `板级测试/` | `CH395F_Test_Guide.md` · `GD5F2GQ5UE_Test_Guide.md` · `SD2506_Test_Guide.md` · `FTP_Test_Guide.md` · `实机测试实施指南.md` |
|
||||
| `专项验证/` | `ADC前端注入验证流程.md` · `启动日志原子性复验流程.md` · `链路延迟测试说明.md` · `存储维护与容量恢复.md` · `模拟器差距清单.md` |
|
||||
| `测试工具/` | `串口助手使用指南.md` · `串口助手设计说明.md` · `ST-LINK_CLI_复位使用说明.md` |
|
||||
| `测试数据/` | `boot_log_data/`(39 个文件,串口/SoE 一手证据)· `m2_data/`(8 个,链路时延安静档)· `m3_data/`(11 个,链路时延 M3 各档) |
|
||||
|
||||
各子目录**内部不再加下一层**:一层子目录 + 文件名前缀(模块名 / 芯片名)已足够定位,再加层只会
|
||||
让引用变长、让下面第 4 条的递归门禁 glob 更难核对。
|
||||
|
||||
## 4. 四条硬约束
|
||||
|
||||
1. **`测试数据/` 里的文件是一手证据:只增不改**。数值被"顺手格式化"就等于基线失效;要更正
|
||||
结论请改文档并另存新证据文件,不动旧文件。
|
||||
2. **两类文件名有机器面**,被 `scripts/check_test_traceability.py` 按目录递归扫描(自本目录
|
||||
根往下找 `*_Test_Guide.md` 与 `*单元测试说明.md`):模块指南落 `板级测试/`、单测说明落
|
||||
`单元测试/`,**换层等于让追溯门禁看不见它**。
|
||||
3. **改名 / 挪目录一律走 `scripts/rename_ref.py`**(先 dry-run 再 `--apply`),它会同步改写
|
||||
全库引用;手工扫引用既慢又漏 → `docs/文档规范.md` §3.6。⚠ 该脚本目前有两个已实测的坑,见
|
||||
下面第 5 节。
|
||||
4. 引用本目录文档时用**仓库根相对路径**(形如 `docs/测试说明/<子目录>/<文件名>.md`);只有图片用
|
||||
文档所在目录相对 → `docs/文档规范.md` §3.1 / §3.2。
|
||||
|
||||
## 5. 本次分层的处置记录(2026-11-01)
|
||||
|
||||
`scripts/rename_ref.py` 搬目录时有两个坑(**权威记录在 `docs/文档规范.md` §3.6 第 4/5 条**,这里只留本目录的处置):
|
||||
|
||||
- `测试数据/` 下 23 个证据文件的**内容**曾被脚本误改 → 已用 `git show HEAD:<旧路径>` 的原始字节逐字节还原,
|
||||
现在这三个目录是**纯改名**(内容与 HEAD 逐字节一致)。
|
||||
- 数据 README 指向外部的 `../` 出链未自动补层级 → 已手工核对补齐(本目录 `测试数据/*/README.md`
|
||||
与 `专项验证/链路延迟测试说明.md`)。
|
||||
@@ -28,7 +28,7 @@
|
||||
2026-10-27 按 `docs/硬件平台/V0.1.tel` 逐通道追线,以 UA 为例(图由
|
||||
`tools/arch_diagram/gen_adc_frontend_svg.py` 生成,改图请改脚本重跑,勿手改 SVG):
|
||||
|
||||

|
||||

|
||||
|
||||
`ADC7` 这个节点上**只有** R31、C44、U3.61 三样东西,**没有对地电阻**。所谓"1k 到地"是 R32,
|
||||
它接在 TPAFE 的**负输入脚 AIN_7GND**(芯片手册 pin62)上,是把差分负端经 1k 拴到 AGND,
|
||||
@@ -101,7 +101,7 @@
|
||||
同一个整数落在两把刻度尺上代表不同电压(图由 `tools/arch_diagram/gen_adc_code_scale_svg.py`
|
||||
生成,改图请改脚本重跑,勿手改 SVG):
|
||||
|
||||

|
||||

|
||||
|
||||
**两把尺子不能混用**:同样是"1000",在 TPAFE 上是 0.153 V,在 STM32 上是 0.806 V,差 5.3 倍。
|
||||
所以 §5 各步的记录表里每一格都必须写明是哪一路(UA/UB/… 属 TPAFE,T 属 STM32),
|
||||
@@ -326,7 +326,7 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,
|
||||
| 万用表 AC 档 | 能读到 mV;**记明型号与响应类型**(真 RMS / 均值响应) | 基准就是它;波形轮那一步两种表的读数都与基波期望差很多,不记响应类型就说不清是谁错 |
|
||||
| 板子 | 产品构建(`test/board/test_config.h` 四个 `TEST_SUITE_*` 全注释)+ `@build` 0 错误 0 警告 + 烧录 `-Rst -Run` 与回读校验 | → `stlink-flash` skill 与 AGENTS.md「构建与验证」 |
|
||||
| `[adc_cal]` 状态 | **保持未标定**(`eng=0`),别为"读数好看"先写标定值 | 现在 `meas:` / `phasor` 的量纲是 **ADC 引脚电压 V**(`App/algo/meas.h` 文件头的 A-lite 口径);标定一生效就换成二次值,本节全部期望值作废 |
|
||||
| 串口 | 全程抓 RX 落盘:用 `serial-assistant` skill(`open` → `clear` → 跑 → 读日志文件或 `log --tail`) | 日志文件就是证据本体,§8.10 归档归档的就是它;**长跑别用 `@test`**——它绑定一轮启动语义(静默 8 s、总超时 30 s、`max_boot_count` = 1,且 forbidden 含 `[ERR]`,而削顶轮故意造 `[ERR]`),约 135 min 的 session 必然超时或误判;daemon 全量写 `state/serial.log`(20 MB 上限自动截头保尾 10 MB)→ `docs/测试说明/自动化测试流程.md` 长时间采集一节 |
|
||||
| 串口 | 全程抓 RX 落盘:用 `serial-assistant` skill(`open` → `clear` → 跑 → 读日志文件或 `log --tail`) | 日志文件就是证据本体,§8.10 归档归档的就是它;**长跑别用 `@test`**——它绑定一轮启动语义(静默 8 s、总超时 30 s、`max_boot_count` = 1,且 forbidden 含 `[ERR]`,而削顶轮故意造 `[ERR]`),约 135 min 的 session 必然超时或误判;daemon 全量写 `state/serial.log`(20 MB 上限自动截头保尾 10 MB)→ `docs/测试说明/流程与规范/自动化测试流程.md` 长时间采集一节 |
|
||||
| 网口(可选) | 要读 104 那一路就插网线、PC 与板同网段(出厂 192.168.1.100),跑现成主站 `test/host/iec104_master.py`(`--ip` / `--port` / `--addr`) | 104 是浮点无量化 + 带品质,是 `meas:` 之外的第二条腿 |
|
||||
| FTP 客户端 | 走现成 21 端口取段文件(出厂 `[ftp]` 账号,连续 5 次失败锁 60 s) | 段文件是相位 / 谐波轮定量档的样本出口;段文件名 `/wave/WAVE<NN>.BIN`(00~99 轮转),**取完立刻改名归档**,否则下一次触发把它盖掉 |
|
||||
| 录波触发路径 | 产品构建里唯一**免改代码**的路径 = UI 菜单第 26 叶「手动录波」确认页(`Drivers/BSP/UI/ui_page_wave_manual.c` → `App/task/ui_task.c:605`) | 保护启动上升沿也算一次触发,但保护判据现处**未标定闭锁**态(AGENTS.md「现状」),别指望它自动来段;bench 定时自抓在双层编译门 `DTU_BENCH` 且 `WAVE_BENCH_AUTOCAP` 非 0 之内(默认 0,`App/task/adc_task.c:153`),开它就走 §8.9 的还原判据 |
|
||||
@@ -625,7 +625,7 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,
|
||||
|
||||
### 8.10 归档与回写(跑完必做,缺一算没收尾)
|
||||
|
||||
1. **证据归档** → `docs/测试说明/boot_log_data/`,沿用现有命名惯例(日期_主题_类型.txt):
|
||||
1. **证据归档** → `docs/测试说明/测试数据/boot_log_data/`,沿用现有命名惯例(日期_主题_类型.txt):
|
||||
`20261104_ac_amp_meas_log.txt`、`20261104_ac_clip_rail_log.txt`、`20261104_ac_iec104_log.txt`;UI 目检照片同目录
|
||||
(该目录若不收图,就在抬头里写清照片存放位置)。**走段文件定量档的用例另加两样**:取回的段原件(原始字节,
|
||||
`20261104_ac_phase_wave<nn>.BIN`)与脚本输出(`fft` / `shape` / `dump` 三份文本 + `plot` 的图)——定量档的证据本体是
|
||||
@@ -1,7 +1,7 @@
|
||||
# 启动日志原子性复验流程(台架)
|
||||
|
||||
> **这篇是什么**:验证"控制台整行独占 / 崩溃遗言原子性"这类**行级完整性**判据的固定动作与口径。
|
||||
> 它补的是 `../子系统设计/控制台单写者日志设计说明.md` 的**验收侧**:那边讲怎么修,这边讲怎么证明修好了、
|
||||
> 它补的是 `../../子系统设计/控制台单写者日志设计说明.md` 的**验收侧**:那边讲怎么修,这边讲怎么证明修好了、
|
||||
> 以及**为什么"标记全中"不等于"日志没坏"**。
|
||||
> 来源:2026-10-26 台架实测(缺陷立项 task-23、收口复验 task-30、工具与流程吸收 task-36)。
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
6. **逐块校验**:`--exact` 锚定受害行 + `--max-boot-count 1` + Forbidden 默认含 `[ERR]`;
|
||||
崩溃注入腿才加 `--pair\ --allow-residual 1\ --head-char '['`。
|
||||
7. **非空跑对照**:每换一版校验器,至少跑一次 `--selftest`,并把**缺陷发生时的原始捕获**再判一遍——必须 FAIL。
|
||||
8. **收尾**:最后一次硬件动作是 `cmp`(排在全批日志之后);台账与证据按 `boot_log_data/README.md` 的口径归档。
|
||||
8. **收尾**:最后一次硬件动作是 `cmp`(排在全批日志之后);台账与证据按 `../测试数据/boot_log_data/README.md` 的口径归档。
|
||||
|
||||
## 4. 三条容易踩的纪律
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
而**产品构建的正常启动根本不走 IPSR 路径**(多段裸发只在 `Src/freertos.c` 的两个内核钩子里),
|
||||
所以"跑 5 次正常启动、[ERR] 零命中"**证不到 IPSR**——那是定义上的必然,是空跑。
|
||||
IPSR 主张交给主机侧套件(假 USART + IPSR + 临界区深度水位);要硬件证据就得由代码道**提交触发器**,
|
||||
判据写"崩溃遗言一整行、恰好一次、`dropped=0`",并按 `boot_log_data/README.md` §2「故障注入日志」
|
||||
判据写"崩溃遗言一整行、恰好一次、`dropped=0`",并按 `../测试数据/boot_log_data/README.md` §2「故障注入日志」
|
||||
运行时放宽 `@test`(`--forbidden` 去掉 `[ERR]`、`--max-boot-count 2`)——**不改仓库配置**。
|
||||
|
||||
## 5. 栈判据(task-32 定稿:三档分权,不再是"待定")
|
||||
@@ -154,9 +154,9 @@ SHA 只当坐标(2026-10-26 那天 SHA 被 amend 挪了三轮)。同镜像
|
||||
|
||||
## 8. 关联
|
||||
|
||||
- 修法与设计口径:`../子系统设计/控制台单写者日志设计说明.md`(O1 两实例与字节账、§4.4.1 崩溃路径验证设计)
|
||||
- 闭环与标记口径:`./自动化测试流程.md`
|
||||
- 证据归档与命名:`./boot_log_data/README.md`
|
||||
- 复位语义与回读次序:`./ST-LINK_CLI_复位使用说明.md`
|
||||
- 烧录 / 采集 / 校验脚本:`../../.dsh/skills/serial-boot-test/SKILL.md`、`../../.dsh/skills/stlink-flash/SKILL.md`、
|
||||
`../../.dsh/skills/serial-assistant/SKILL.md`
|
||||
- 修法与设计口径:`../../子系统设计/控制台单写者日志设计说明.md`(O1 两实例与字节账、§4.4.1 崩溃路径验证设计)
|
||||
- 闭环与标记口径:`../流程与规范/自动化测试流程.md`
|
||||
- 证据归档与命名:`../测试数据/boot_log_data/README.md`
|
||||
- 复位语义与回读次序:`../测试工具/ST-LINK_CLI_复位使用说明.md`
|
||||
- 烧录 / 采集 / 校验脚本:`../../../.dsh/skills/serial-boot-test/SKILL.md`、`../../../.dsh/skills/stlink-flash/SKILL.md`、
|
||||
`../../../.dsh/skills/serial-assistant/SKILL.md`
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> 版本:v1.0 日期:2026-09-21
|
||||
> 适用工程:STM32F4-Base(STM32F407ZGTx + GD5F2GQ5UE SPI NAND + dhara FTL + FatFs)
|
||||
> 关联:`docs/测试说明/GD5F2GQ5UE_Test_Guide.md`(破坏性用例清单)、`docs/内存管理/内存内容分配策略.md`(DMA 可达性守卫)
|
||||
> 关联:`docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md`(破坏性用例清单)、`docs/内存管理/内存内容分配策略.md`(DMA 可达性守卫)
|
||||
|
||||
## 1. 三个维护动作,别混用
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
- 验收(两条判定路径都要过):`--require-selftest-pass` → `SELFTEST_BASELINE: 既有记录 0 条
|
||||
(status=absent)` → PASS;`--selftest-scope all` → `selftest: no fault record` → **PASS**
|
||||
(清零前这条是 `29 fault record(s)` FAIL)。设备侧无此文件时 lftpd 回 450,被按"台账干净"
|
||||
处理,这条映射见 `../架构设计/STM32F4-Base存储架构说明.md` §10.3 与 S7 判定表。
|
||||
处理,这条映射见 `../../架构设计/STM32F4-Base存储架构说明.md` §10.3 与 S7 判定表。
|
||||
|
||||
### 4.3 恢复流程里的 ECC 开关:不能只看"跑完了"(2026-10-23)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
> **性质**:**登记册**(living document)。新增模拟器后端差异时必须在此登记一行,不得只写在别处。
|
||||
> **上游依据**:`docs/网络/Net层阻塞模型架构设计.md` §10(net 层 pending 化现状)。
|
||||
> **相关**:`UI设计/LVGL模拟器部署与使用说明.md`(部署与使用)、`simulator/README.md`(目录与架构)、
|
||||
> `测试说明/测试开发标准流程.md`(模拟器回归门禁在测试分层中的位置)。
|
||||
> `docs/测试说明/流程与规范/测试开发标准流程.md`(模拟器回归门禁在测试分层中的位置)。
|
||||
|
||||
---
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
> **文档目的**:链路时延的**唯一权威文档**——怎么测、当前实测值是多少、慢在哪一段、
|
||||
> 哪些缺陷已修/未修、新异常出现时查什么。
|
||||
> **数据日期**:2026-09-22 台架(COM6 @115200;STM32F407ZGTx @168MHz + CH395F,SPI2 分频 8)
|
||||
> **数据文件**:`m2_data/`、`m3_data/`(JSON + 串口证据片段);本文所有数字均可回溯到这些文件
|
||||
> **数据文件**:`../测试数据/m2_data/`、`../测试数据/m3_data/`(JSON + 串口证据片段);本文所有数字均可回溯到这些文件
|
||||
> **代码状态**:D10 / D17 / D12 / D14 / D15 / D16 已修复并台架复验(§8);
|
||||
> D1(重传周期 200ms)/ D6(per-recv 日志)2026-09-22 已实施并台架复验(P0-a/P0-b,§10.1);
|
||||
> D20(开机首个 FTP 会话第 2 个数据连接 425)已定位未修(§8.2)
|
||||
@@ -259,7 +259,7 @@ DTU-RemoteLCD 客户端;输出每帧 `req2first / total / recv 批次到达时
|
||||
# 1) 先 clear 再起 peer(顺序不可反:wait-idle 需要看到会话活跃期)
|
||||
& '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py clear
|
||||
& '.venv\Scripts\python.exe' test\latency_peer.py --host 192.168.1.100 --port 8080 `
|
||||
--json "docs\测试说明\m2_data\m2_quiet.json" --wait 170 # 后台作业
|
||||
--json "docs\测试说明\测试数据\m2_data\m2_quiet.json" --wait 170 # 后台作业
|
||||
# 2) 烧录(Reset&Run 不可省)
|
||||
& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash
|
||||
# 3) 等空闲:会话本身约 2s,但 peer 首连常因"芯片空闲超时 RST"失败一次并 2s 后重试
|
||||
@@ -285,16 +285,16 @@ DTU-RemoteLCD 客户端;输出每帧 `req2first / total / recv 批次到达时
|
||||
& '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py clear
|
||||
& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash # 先烧录,再起 peer(顺序不可反!)
|
||||
& '.venv\Scripts\python.exe' test\latency_peer.py --mode remo --host 192.168.1.100 --port 7003 `
|
||||
--samples 45 --stress-from 15 --ftp-stress --json "docs\测试说明\m3_data\m3_dev_stress.json"
|
||||
--samples 45 --stress-from 15 --ftp-stress --json "docs\测试说明\测试数据\m3_data\m3_dev_stress.json"
|
||||
# 模拟器基线(Δ 的对照端)
|
||||
& "simulator\build_sim.bat"; .\simulator\build\Debug\lvgl_sim.exe # 等 7003 就绪
|
||||
& '.venv\Scripts\python.exe' test\latency_peer.py --mode remo --host 127.0.0.1 --port 7003 `
|
||||
--samples 50 --json "docs\测试说明\m3_data\m3_sim_quiet.json"
|
||||
--samples 50 --json "docs\测试说明\测试数据\m3_data\m3_sim_quiet.json"
|
||||
# 尾批定性/解法(都不需要抓包工具)
|
||||
& '.venv\Scripts\python.exe' test\latency_peer.py --mode remo --host 192.168.1.100 --port 7003 `
|
||||
--samples 30 --ack-probe --json "docs\测试说明\m3_data\m3_tail_ackprobe.json" # 带内补 ACK
|
||||
--samples 30 --ack-probe --json "docs\测试说明\测试数据\m3_data\m3_tail_ackprobe.json" # 带内补 ACK
|
||||
& '.venv\Scripts\python.exe' test\latency_peer.py --mode remo --host 192.168.1.100 --port 7003 `
|
||||
--samples 30 --ack-fast --json "docs\测试说明\m3_data\m3_tail_ackfast.json" # 关延迟 ACK
|
||||
--samples 30 --ack-fast --json "docs\测试说明\测试数据\m3_data\m3_tail_ackfast.json" # 关延迟 ACK
|
||||
```
|
||||
|
||||
### 5.4 D20 回归(`test/host/ftp_regression.py`)
|
||||
@@ -406,7 +406,7 @@ D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故
|
||||
| 连接 / 断开重连(+INIT) | 20.9ms / 22.6ms(3/32.6) | 10.5ms / 32.0ms | — | ≤150ms |
|
||||
|
||||
(模拟器列为 2026-09-21 基线,模拟器工程不受发送分块握手影响(公开 API 不变);真机列 =
|
||||
**2026-09-22 16:42 挂起 recv 构建重锁**(`m3_data/m3_pending_quiet.json`,50/50 帧全 OK、零尖峰)。
|
||||
**2026-09-22 16:42 挂起 recv 构建重锁**(`../测试数据/m3_data/m3_pending_quiet.json`,50/50 帧全 OK、零尖峰)。
|
||||
上一档真机值(P0-a/P0-b 分片代码,同日 11:35):帧周期 61.6ms / 首字节 9.6ms / 尾批 52.6ms /
|
||||
重连 17.1/22.4ms → pending 构建:帧周期 med **58.9ms**(−2.7ms)、尾批 **50.4ms**(−2.2ms)——
|
||||
执行器零占用使生产路径净缩短(更早的空闲窗口)。)
|
||||
@@ -422,7 +422,7 @@ D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故
|
||||
med 65.0ms/max 133.5ms(133.5 = 压力启动瞬态单帧);**挂起 recv 化后 med 60.1ms/max 69.3ms**
|
||||
——p99 尾部较分片档压缩近半(133.5→69.3),MCU 侧 `prod_cycle_mcu` 6706µs 在压力下纹丝不动
|
||||
(min 6698/max 6720):头阻塞工况不再向 UI 帧周期传导 = 结构性收益。本档重锁 =
|
||||
`m3_data/m3_pending_stress.json`,2026-09-22 16:43。)
|
||||
`../测试数据/m3_data/m3_pending_stress.json`,2026-09-22 16:43。)
|
||||
|
||||
### 6.4 全段基线总表
|
||||
|
||||
@@ -447,10 +447,10 @@ med 65.0ms/max 133.5ms(133.5 = 压力启动瞬态单帧);**挂起 recv 化
|
||||
(µs 级)——机制上不影响队列往返;M2 重验未在本轮执行(低风险,留待 Phase 13 下次窗口,见 `docs/任务规划/README.md` 条目「队列往返基线待重验」)。
|
||||
|
||||
数据来源:SPI 字节命令/SPI DMA = §6.1;发送分块握手/队列往返/请求→首字节/整帧 3209B 往返 = M2 B2 档(200ms、per-recv 日志已删)串口 `[LAT]` 行
|
||||
(`m2_data/m2_quiet_r200.json`);生产路径帧周期/连接/重监听/uiTask 节拍 = **挂起 recv 构建 2026-09-22 16:42/16:43 重锁**
|
||||
(`m3_data/m3_pending_quiet.json` / `m3_pending_stress.json` 之 MCU 侧 `[LAT]` 行);日志税 = M3 静默档
|
||||
(`m3_data/m3_dev_quiet_r200.json`,与发送分块握手无关的串口税段);A/B 对照档 = `m2_quiet_r500.json`(旧条件);
|
||||
peer 侧 = `m3_data/m3_pending_*.json`(发送分块握手重锁)与 `m3_data/m3_dev_*_r200.json`(上一档,历史对照)。
|
||||
(`../测试数据/m2_data/m2_quiet_r200.json`);生产路径帧周期/连接/重监听/uiTask 节拍 = **挂起 recv 构建 2026-09-22 16:42/16:43 重锁**
|
||||
(`../测试数据/m3_data/m3_pending_quiet.json` / `m3_pending_stress.json` 之 MCU 侧 `[LAT]` 行);日志税 = M3 静默档
|
||||
(`../测试数据/m3_data/m3_dev_quiet_r200.json`,与发送分块握手无关的串口税段);A/B 对照档 = `m2_quiet_r500.json`(旧条件);
|
||||
peer 侧 = `../测试数据/m3_data/m3_pending_*.json`(发送分块握手重锁)与 `../测试数据/m3_data/m3_dev_*_r200.json`(上一档,历史对照)。
|
||||
旧 run15 摘录(`m2_serial_excerpt_run15.txt`)保留作 A/B 历史对照。
|
||||
|
||||
### 6.5 重锁规则
|
||||
@@ -516,7 +516,7 @@ peer 侧 = `m3_data/m3_pending_*.json`(发送分块握手重锁)与 `m3_data
|
||||
| 4 | 对照:满块批量(M2 发送分块握手,16×4096B) | — | 无累积惩罚(64KB/125ms) | — | **满 MSS 段不受影响** |
|
||||
|
||||
> 实验 1/2 已固化为 peer 选项:`--ack-probe`(可移植:任何 OS/客户端只要在帧未收齐时发一个字节即可)、
|
||||
> `--ack-fast`(仅 Windows,无需改协议)。原始数据:`m3_data/m3_tail_ackprobe.json`、`m3_data/m3_tail_ackfast.json`。
|
||||
> `--ack-fast`(仅 Windows,无需改协议)。原始数据:`../测试数据/m3_data/m3_tail_ackprobe.json`、`../测试数据/m3_data/m3_tail_ackfast.json`。
|
||||
|
||||
### 7.4 解法与生产客户端实装
|
||||
|
||||
@@ -709,7 +709,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
||||
9. **日志非阻塞化:已实施·形态变更(生产者侧 2026-09-24 单写者;2026-10-25 与日志静默观察项合并评估收口)**:
|
||||
`fputc` → 环形缓冲**已落地**(4KB 环 + 单写者 + 事件位;4402µs/行 → µs 级入环,
|
||||
溢出 = 有界 200ms + dropped 账 + `[ERR]` 留痕;冲刷 = 有界裸发,见
|
||||
`../子系统设计/控制台单写者日志设计说明.md` §4);**TX 中断/DMA 维持否决**
|
||||
`../../子系统设计/控制台单写者日志设计说明.md` §4);**TX 中断/DMA 维持否决**
|
||||
(该文档 D4),原绑定的复议条件(根治项落地后实测 `tx_timeout`)已随 2026-10-26 裁定不做而失效——日志静默观察项 × 日志单写者化合并评估全文
|
||||
结论见同文档文末附录;
|
||||
10. **S9** 客户端侧(DTU-RemtoeLCD):按键后立即取帧、不传 PNG(直接发 1bpp/差量 + canvas 绘制)、
|
||||
@@ -723,7 +723,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
||||
+ 中断/DMA,溢出丢弃策略需定义)。
|
||||
**现状(2026-10-25)**:根治已随单写者落地——行级原子 = 临界区整行入环、单写者发出,
|
||||
交错/丢行结构性消除;「写者注册前」窗口为裸发例外,纪律 = `dbg_console_writer_ready()`
|
||||
门控(`../子系统设计/控制台单写者日志设计说明.md` §3.4)。
|
||||
门控(`../../子系统设计/控制台单写者日志设计说明.md` §3.4)。
|
||||
|
||||
---
|
||||
|
||||
@@ -747,24 +747,24 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
||||
|
||||
| 数据文件 | 内容 |
|
||||
|---|---|
|
||||
| `m2_data/m2_quiet.json` | M2 安静档 peer 侧(run15 最终代码):发送分块握手~整帧 3209B 往返端到端 + 逐帧尾批明细 |
|
||||
| `m2_data/m2_quiet_run13.json` | M2 run13(独立 PASS 对照) |
|
||||
| `m2_data/m2_quiet_run14.json` | M2 run14(仅 peer 侧有效;MCU 侧因热路径日志洪水不作基线,D12-b) |
|
||||
| `m2_data/m2_serial_excerpt_run13/15.txt` | M2 串口 `[LAT]`/`[NET]` 证据片段(旧基线,A/B 历史对照) |
|
||||
| `m2_data/m2_quiet_r500.json` | 2026-09-22 A/B 对照档 B1(500ms + per-recv 日志 = 旧基线条件;复跑与 run15 重合 ±0.2%) |
|
||||
| `m2_data/m2_quiet_r200.json` | **2026-09-22 M2 重锁基线** B2(200ms、per-recv 日志已删 = 当前代码) |
|
||||
| `m2_data/README.md` | M2 数据说明(逐帧尾批明细、方法学约束) |
|
||||
| `m3_data/m3_dev_quiet.json` | 真机 65 帧生产周期(D10/头阻塞/D17 修复前基线) |
|
||||
| `m3_data/m3_dev_quiet_fixed.json` | 真机 65 帧(修复后:帧周期 65.7ms、relisten OK、INIT framebytes=3200) |
|
||||
| `m3_data/m3_dev_stress.json` | 头阻塞压力档(修复前:17.7s 尖峰) |
|
||||
| `m3_data/m3_dev_stress_fixed.json` | 头阻塞压力档(修复后:med 74.7ms / max 106.8ms,零尖峰) |
|
||||
| `m3_data/m3_dev_quiet_r200.json` | **2026-09-22 M3 静默档重锁基线**(50 帧,P0-a/P0-b 代码:帧周期 61.6ms) |
|
||||
| `m3_data/m3_dev_stress_r200.json` | **2026-09-22 M3 压力档重锁基线**(45 帧,第 15 帧起 FTP stress:med 65.0ms / max 133.5ms,零尖峰)——分片时代数值,**已被发送分块握手档取代**(历史对照) |
|
||||
| `m3_data/m3_pending_quiet.json` | **2026-09-22 M3 静默档发送分块握手重锁基线(当前)**(50 帧,pending 构建 16:42:帧周期 58.9ms / 首字节 9.2ms / 尾批 50.4ms,零尖峰,CRC 50/0) |
|
||||
| `m3_data/m3_pending_stress.json` | **2026-09-22 M3 压力档发送分块握手重锁基线(当前)**(50 帧,第 25 帧起 FTP 空闲登录保持:stress 段 med 60.1ms / p95 66.4ms / max 69.3ms,零尖峰,CRC 50/0;MCU 侧 prod_cycle_mcu 6706µs 压力下平坦) |
|
||||
| `m3_data/m3_sim_quiet.json` | 模拟器基线 50 帧(Δ 对照,tail=0) |
|
||||
| `m3_data/m3_tail_ackprobe.json` | 尾批实验 ①:帧未收齐即回 1 字节(捎带 ACK)→ tail 3.9ms |
|
||||
| `m3_data/m3_tail_ackfast.json` | 尾批实验 ②:Windows 立即 ACK(不发探测字节)→ tail 3.9ms |
|
||||
| `../测试数据/m2_data/m2_quiet.json` | M2 安静档 peer 侧(run15 最终代码):发送分块握手~整帧 3209B 往返端到端 + 逐帧尾批明细 |
|
||||
| `../测试数据/m2_data/m2_quiet_run13.json` | M2 run13(独立 PASS 对照) |
|
||||
| `../测试数据/m2_data/m2_quiet_run14.json` | M2 run14(仅 peer 侧有效;MCU 侧因热路径日志洪水不作基线,D12-b) |
|
||||
| `../测试数据/m2_data/m2_serial_excerpt_run13/15.txt` | M2 串口 `[LAT]`/`[NET]` 证据片段(旧基线,A/B 历史对照) |
|
||||
| `../测试数据/m2_data/m2_quiet_r500.json` | 2026-09-22 A/B 对照档 B1(500ms + per-recv 日志 = 旧基线条件;复跑与 run15 重合 ±0.2%) |
|
||||
| `../测试数据/m2_data/m2_quiet_r200.json` | **2026-09-22 M2 重锁基线** B2(200ms、per-recv 日志已删 = 当前代码) |
|
||||
| `../测试数据/m2_data/README.md` | M2 数据说明(逐帧尾批明细、方法学约束) |
|
||||
| `../测试数据/m3_data/m3_dev_quiet.json` | 真机 65 帧生产周期(D10/头阻塞/D17 修复前基线) |
|
||||
| `../测试数据/m3_data/m3_dev_quiet_fixed.json` | 真机 65 帧(修复后:帧周期 65.7ms、relisten OK、INIT framebytes=3200) |
|
||||
| `../测试数据/m3_data/m3_dev_stress.json` | 头阻塞压力档(修复前:17.7s 尖峰) |
|
||||
| `../测试数据/m3_data/m3_dev_stress_fixed.json` | 头阻塞压力档(修复后:med 74.7ms / max 106.8ms,零尖峰) |
|
||||
| `../测试数据/m3_data/m3_dev_quiet_r200.json` | **2026-09-22 M3 静默档重锁基线**(50 帧,P0-a/P0-b 代码:帧周期 61.6ms) |
|
||||
| `../测试数据/m3_data/m3_dev_stress_r200.json` | **2026-09-22 M3 压力档重锁基线**(45 帧,第 15 帧起 FTP stress:med 65.0ms / max 133.5ms,零尖峰)——分片时代数值,**已被发送分块握手档取代**(历史对照) |
|
||||
| `../测试数据/m3_data/m3_pending_quiet.json` | **2026-09-22 M3 静默档发送分块握手重锁基线(当前)**(50 帧,pending 构建 16:42:帧周期 58.9ms / 首字节 9.2ms / 尾批 50.4ms,零尖峰,CRC 50/0) |
|
||||
| `../测试数据/m3_data/m3_pending_stress.json` | **2026-09-22 M3 压力档发送分块握手重锁基线(当前)**(50 帧,第 25 帧起 FTP 空闲登录保持:stress 段 med 60.1ms / p95 66.4ms / max 69.3ms,零尖峰,CRC 50/0;MCU 侧 prod_cycle_mcu 6706µs 压力下平坦) |
|
||||
| `../测试数据/m3_data/m3_sim_quiet.json` | 模拟器基线 50 帧(Δ 对照,tail=0) |
|
||||
| `../测试数据/m3_data/m3_tail_ackprobe.json` | 尾批实验 ①:帧未收齐即回 1 字节(捎带 ACK)→ tail 3.9ms |
|
||||
| `../测试数据/m3_data/m3_tail_ackfast.json` | 尾批实验 ②:Windows 立即 ACK(不发探测字节)→ tail 3.9ms |
|
||||
|
||||
### 12.2 相关文档
|
||||
|
||||
@@ -774,8 +774,8 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
||||
| UI 设计架构(离屏渲染 + 推流) | `docs/UI设计/UI_设计架构.md` |
|
||||
| BSD Socket API 与双端后端 | `docs/网络/BSD_Socket_API_使用指南.md` |
|
||||
| CH395F 陷阱史(TRAP-NET-09/-16 等) | `docs/问题记录/CH395F_Trap_Records.md` |
|
||||
| CH395F 测试套件(吞吐 Phase 8 等) | `docs/测试说明/CH395F_Test_Guide.md` |
|
||||
| CH395F 测试套件(吞吐 Phase 8 等) | `docs/测试说明/板级测试/CH395F_Test_Guide.md` |
|
||||
| RAM 预算(`ui_net_sink` 6.4KB 常驻) | `docs/内存管理/RAM使用分析与优化方案.md` |
|
||||
| 串口助手(抓日志排查) | `docs/测试说明/串口助手使用指南.md` |
|
||||
| 串口助手(抓日志排查) | `docs/测试说明/测试工具/串口助手使用指南.md` |
|
||||
| 远端显示客户端(**与本仓库同级的独立工程**,延迟确认抑制实装处) | `../DTU-RemtoeLCD/remo_disp_server.py`、`README.md` |
|
||||
| 芯片手册(§5.17/§5.18 重传、§5.42 ARP、SENBUF_FREE 语义) | `docs/芯片手册/CH395F.md` |
|
||||
@@ -7,12 +7,12 @@
|
||||
> **状态**:✅ 已落地(**103** 用例,`/W4` 0 告警,已挂 pre-commit 钩子)
|
||||
> **日期**:2026-10-10
|
||||
> **关联文档**:
|
||||
> [`../../AGENTS.md`](../../AGENTS.md)(平台约束 · CubeMX 生成区铁律)、
|
||||
> [`测试开发标准流程.md`](测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`../../../AGENTS.md`](../../../AGENTS.md)(平台约束 · CubeMX 生成区铁律)、
|
||||
> [`测试开发标准流程.md`](../流程与规范/测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`配置文件单元测试说明.md`](配置文件单元测试说明.md)(同层"强符号桩"范本)、
|
||||
> [`相量层单元测试说明.md`](相量层单元测试说明.md)(同批落地的 全周傅氏相量姊妹篇)、
|
||||
> [`../硬件平台/ADC通道映射说明.md`](../硬件平台/ADC通道映射说明.md)(**语义映射权威口径**)、
|
||||
> [`../算法/继电保护功能复现规划.md`](../算法/继电保护功能复现规划.md)(「STM32 ADC1 启动与扫描」/「通道语义映射」设计依据)、
|
||||
> [`../../硬件平台/ADC通道映射说明.md`](../../硬件平台/ADC通道映射说明.md)(**语义映射权威口径**)、
|
||||
> [`../../算法/继电保护功能复现规划.md`](../../算法/继电保护功能复现规划.md)(「STM32 ADC1 启动与扫描」/「通道语义映射」设计依据)、
|
||||
> 快照语义约定的历史审计(属主文档已于 2026-10-15 删除)
|
||||
|
||||
---
|
||||
@@ -81,7 +81,7 @@ test/host/adc_input/adc_input_test.c
|
||||
| 硬件 | 无(不需要开发板 / 串口 / ST-LINK / 信号源) |
|
||||
|
||||
工具链探测 / `INCLUDE`-`LIB` 拼接 / 编译运行 / 退出码判定全部委托通用 harness
|
||||
[`../../test/host/common/unit_test_harness.py`](../../test/host/common/unit_test_harness.py),
|
||||
[`../../../test/host/common/unit_test_harness.py`](../../../test/host/common/unit_test_harness.py),
|
||||
本模块 `run_unit_test.py` 只**声明** `TestBuild`(源文件 / 桩目录 / 汇总行标记)。
|
||||
|
||||
### 1.4 运行方式
|
||||
@@ -5,11 +5,11 @@
|
||||
> **分支覆盖**:本机可实测拿到(§2.1 的 gcc/WSL 路),但**用户裁定 2026-10-23 不引入第二条工具链**
|
||||
> → 本文把它记为**已接受缺口**,不是待办
|
||||
> **日期**:2026-10-23
|
||||
> **脚本**:[`scripts/check_test_coverage.py`](../../scripts/check_test_coverage.py)(纯标准库)
|
||||
> **基线台账**:[`scripts/test_coverage_baseline.json`](../../scripts/test_coverage_baseline.json)
|
||||
> **脚本**:[`scripts/check_test_coverage.py`](../../../scripts/check_test_coverage.py)(纯标准库)
|
||||
> **基线台账**:[`scripts/test_coverage_baseline.json`](../../../scripts/test_coverage_baseline.json)
|
||||
> **关联文档**:
|
||||
> [`测试开发标准流程.md`](测试开发标准流程.md)(静态门禁~人工目检分层与门禁决策表)、
|
||||
> [`../代码规范/pre-commit使用说明.md`](../代码规范/pre-commit使用说明.md)(钩子通用机制)
|
||||
> [`测试开发标准流程.md`](../流程与规范/测试开发标准流程.md)(静态门禁~人工目检分层与门禁决策表)、
|
||||
> [`../../代码规范/pre-commit使用说明.md`](../../代码规范/pre-commit使用说明.md)(钩子通用机制)
|
||||
|
||||
---
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
## 5. 门禁姿态:只拦回退,不拦进步
|
||||
|
||||
台账 = [`scripts/test_coverage_baseline.json`](../../scripts/test_coverage_baseline.json)
|
||||
台账 = [`scripts/test_coverage_baseline.json`](../../../scripts/test_coverage_baseline.json)
|
||||
(`--update-baseline` 生成,含 `totals` / `modules` / `files` / 未触及清单)。
|
||||
|
||||
| 情况 | 判定 | 说明 |
|
||||
@@ -142,7 +142,7 @@
|
||||
→ 报告 §5.5 想要的"覆盖到哪些分支"**没有被本文满足**,被满足的是"哪些行根本没进过"。
|
||||
分支覆盖本机**能拿到**(§2.1 的 gcc + `gcov -b -c`),但**已裁定不引入第二条工具链** →
|
||||
它就是本口径的**已知缺口**:绿灯只代表行与函数被测到,`if (a && b)` 的另一半要自己读用例。
|
||||
补偿判据:TC 双向追溯 + 用例侧显式列边界值(`docs/测试说明/测试开发标准流程.md` §5);
|
||||
补偿判据:TC 双向追溯 + 用例侧显式列边界值(`docs/测试说明/流程与规范/测试开发标准流程.md` §5);
|
||||
真到要分支证据那天,先看 §2.1 的三条代价再决定,别顺手装个 `dotnet-coverage` 当第二套口径。
|
||||
2. **0 分母 ≠ 0%。** 125 个文件从没被任何主机单测编译过,它们**不在**覆盖率里;把"88%"读成
|
||||
"仓库八成代码被测"是最常见的误读。
|
||||
@@ -247,7 +247,7 @@
|
||||
|
||||
| 批次 | 文件(有效代码行) | 逻辑度 | 要桩什么 | 判据出处(直接抄成用例) | 为什么值得 |
|
||||
|---|---|---|---|---|---|
|
||||
| **FTP 一套** | `lftpd.c`(694)、`lftpd_io.c`(207)、`lftpd_inet.c`(171)、`lftpd_string.c`(11) = 1,083 | 0.99/0.90/0.93 | 真实 `ff.h` + 假 diskio;复用 `net_socket.h` | `docs/测试说明/FTP_Test_Guide.md`、`docs/子系统设计/网络配置说明.md` §3.4(`pwd_hash`=SHA-256(user‖password)、连续 5 次失败锁 60 s、默认口令启动告警) | **20 次提交里 6 次是 fix**,最近两条都是"静默型":LIST/NLST 满块被截断回 550、对端行为误打 `[ERR]`(2026-10-23)——覆盖率最擅长照的就是这类"日志看不出根因" |
|
||||
| **FTP 一套** | `lftpd.c`(694)、`lftpd_io.c`(207)、`lftpd_inet.c`(171)、`lftpd_string.c`(11) = 1,083 | 0.99/0.90/0.93 | 真实 `ff.h` + 假 diskio;复用 `net_socket.h` | `docs/测试说明/板级测试/FTP_Test_Guide.md`、`docs/子系统设计/网络配置说明.md` §3.4(`pwd_hash`=SHA-256(user‖password)、连续 5 次失败锁 60 s、默认口令启动告警) | **20 次提交里 6 次是 fix**,最近两条都是"静默型":LIST/NLST 满块被截断回 550、对端行为误打 `[ERR]`(2026-10-23)——覆盖率最擅长照的就是这类"日志看不出根因" |
|
||||
| **NET 拆出来的四块** | `net_pending.c`(287)、`net_events.c`(263)、`net_listener.c`(191)、`net_select.c`(162) = 903 | 0.90/0.78/–/0.93 | **新建 `stub/ch395f.h`**(芯片寄存器只到函数边界)+ 假任务通知;`net_socket.h` 已有 | `docs/网络/网络自愈架构设计.md` §4.10(socket 读清点审计 + 新增一处读清的三条准入判据)、`docs/网络/Net层阻塞模型架构设计.md` | 挂起 recv、监听按代次重建、退避这些**语义在真机上极难复现**;这一族的 B3("顺手全量清一遍把别的 socket 门焊死")与 N34 E14 都是 fix 出来的真事 |
|
||||
| **配置与工具(最便宜,建议第一个落地)** | `net_cfg.c`(167)、`task_prof.c`(160)、`ftp_cfg.c`(59)、`prot_set_store.c`(43) = 429 | 1.00/0.97/–/– | 真实头即可(`cfg_file.h` 已被现有单测证明能在 PC 上编),最多补 `dbg_log.h` | `docs/子系统设计/网络配置说明.md`(工厂默认 192.168.1.100/24、MAC 全零=芯片内置、保存立即生效)、`docs/算法/采集与算法层设计说明.md` | 硬件符号 0~2 处,纯解析/编解码/格式化。**一天内能出第一份绿**,用来把"新增 `files_tested`"这条路先跑通 |
|
||||
| **104 服务层** | `iec104_serv.c`(202) | 0.96 | 复用 `time_sync`/stub 的 `cmsis_os2.h` + 已有 `net_socket.h` | 与 `test/host/iec104/`(97 用例)同一套脚手架 | 同族的 `iec104_pts.c` 现在只有 **67.2%**(全仓最低之一);服务层进来才能把 YK/YX 编排的分支照全 |
|
||||
@@ -473,7 +473,7 @@ uint16_t ch395f_link_change_count(void);
|
||||
游标分别 `TC-NETSOCK-545`/`TC-SYSLOG-100`/`TC-CFGFST-053`/`TC-SOESTORE-024`/`TC-CONLOG-135`,
|
||||
属主登记处 `test/host/<目录>/*`,`cursor_owner_only`/`allow_orphans`/`subitem_ok` 照 B 层口径)。
|
||||
**先补族再引号**这条链本批又走了一遍,而且踩在收口前:`net_socket` 起初自取两字母码 `TC-NS-*`(465 处),
|
||||
那会整批落进通用 `TC` 族(属主 `docs/测试说明/*_Test_Guide.md`、**无** `allow_orphans`)
|
||||
那会整批落进通用 `TC` 族(属主 `docs/测试说明/板级测试/*_Test_Guide.md`、**无** `allow_orphans`)
|
||||
= 458 条台账外新账直接拦提交;正名为 `TC-NETSOCK-` 是 bytes 级替换(465 处 / 0 残留 / 兄弟目录 `git diff` 全空 /
|
||||
复跑 420 全绿)。**写死成纪律**:队友起手就按 Lead 给的模块码写号,两字母不可检索的码(`NS`)不要取。
|
||||
本批**未**给新套件单挂 `*-unit-test` 钩子(与 P1/P2 那 17 套同口径):聚合闸 `test-coverage` 的触发面
|
||||
@@ -6,11 +6,11 @@
|
||||
> **状态**:✅ 已落地(33 断言点,`/W4` 0 告警,已挂 pre-commit 钩子)
|
||||
> **日期**:2026-10-10
|
||||
> **关联文档**:
|
||||
> [`../../AGENTS.md`](../../AGENTS.md)(平台约束与看门狗铁律)、
|
||||
> [`测试开发标准流程.md`](测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`../../../AGENTS.md`](../../../AGENTS.md)(平台约束与看门狗铁律)、
|
||||
> [`测试开发标准流程.md`](../流程与规范/测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`看门狗单元测试说明.md`](看门狗单元测试说明.md)(同源的喂狗点语义)、
|
||||
> [`相量层单元测试说明.md`](相量层单元测试说明.md)(同批落地的姊妹篇)、
|
||||
> [`../子系统设计/看门狗设计说明.md`](../子系统设计/看门狗设计说明.md)(`required_mask` 与长耗时白名单)
|
||||
> [`../../子系统设计/看门狗设计说明.md`](../../子系统设计/看门狗设计说明.md)(`required_mask` 与长耗时白名单)
|
||||
|
||||
---
|
||||
|
||||
@@ -90,7 +90,7 @@ test/host/vol_lock/vol_lock_test.c
|
||||
| 硬件 | 无(不需要开发板 / 串口 / ST-LINK) |
|
||||
|
||||
工具链探测 / `INCLUDE`-`LIB` 拼接 / 编译运行 / 退出码判定全部委托通用 harness
|
||||
[`../../test/host/common/unit_test_harness.py`](../../test/host/common/unit_test_harness.py),
|
||||
[`../../../test/host/common/unit_test_harness.py`](../../../test/host/common/unit_test_harness.py),
|
||||
本模块 `run_unit_test.py` 只**声明** `TestBuild`(源文件 / 桩目录 / 汇总行标记)。
|
||||
|
||||
### 1.5 运行方式
|
||||
@@ -7,12 +7,12 @@
|
||||
> **状态**:✅ 已落地(21 断言点,MSVC `/W4` 与 cppcheck 均 0 告警)
|
||||
> **日期**:2026-10-27(道G task-12)
|
||||
> **关联文档**:
|
||||
> [`../../AGENTS.md`](../../AGENTS.md)(RTOS 与内存铁律、`[ERR]` 通道口径)、
|
||||
> [`测试开发标准流程.md`](测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`../../../AGENTS.md`](../../../AGENTS.md)(RTOS 与内存铁律、`[ERR]` 通道口径)、
|
||||
> [`测试开发标准流程.md`](../流程与规范/测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`主机单测覆盖率口径.md`](主机单测覆盖率口径.md)(覆盖率总闸如何收编本套)、
|
||||
> [`../子系统设计/系统墙钟时间维护说明.md`](../子系统设计/系统墙钟时间维护说明.md)
|
||||
> [`../../子系统设计/系统墙钟时间维护说明.md`](../../子系统设计/系统墙钟时间维护说明.md)
|
||||
> §13.1(同一块 70 B 用户 SRAM 的**占用分配表**,本模块占 0..7)、
|
||||
> [`../子系统设计/IEC104上行设计说明.md`](../子系统设计/IEC104上行设计说明.md)
|
||||
> [`../../子系统设计/IEC104上行设计说明.md`](../../子系统设计/IEC104上行设计说明.md)
|
||||
> (同一张运行报告页的另一半数据源:104 观测计数)
|
||||
|
||||
---
|
||||
@@ -7,13 +7,13 @@
|
||||
> **状态**:✅ 已落地(80 断言点,`/W4` 0 告警,已挂 pre-commit 钩子)
|
||||
> **日期**:2026-10-10
|
||||
> **关联文档**:
|
||||
> [`../../AGENTS.md`](../../AGENTS.md)(平台约束与看门狗铁律)、
|
||||
> [`测试开发标准流程.md`](测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`../../../AGENTS.md`](../../../AGENTS.md)(平台约束与看门狗铁律)、
|
||||
> [`测试开发标准流程.md`](../流程与规范/测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`看门狗单元测试说明.md`](看门狗单元测试说明.md)(喂狗位图判定状态机)、
|
||||
> [`卷锁单元测试说明.md`](卷锁单元测试说明.md)(同批落地的姊妹篇)、
|
||||
> [`../子系统设计/看门狗设计说明.md`](../子系统设计/看门狗设计说明.md)(`required_mask` / 抽样窗 / 长耗时白名单)、
|
||||
> [`../任务规划/README.md`](../任务规划/README.md)(登记条目「探针窗口心跳缺口」)、
|
||||
> 历史审计(netTask 头阻塞;属主文档已于 2026-10-15 删除,现状见 [`../网络/Net层阻塞模型架构设计.md`](../网络/Net层阻塞模型架构设计.md))
|
||||
> [`../../子系统设计/看门狗设计说明.md`](../../子系统设计/看门狗设计说明.md)(`required_mask` / 抽样窗 / 长耗时白名单)、
|
||||
> [`../../任务规划/README.md`](../../任务规划/README.md)(登记条目「探针窗口心跳缺口」)、
|
||||
> 历史审计(netTask 头阻塞;属主文档已于 2026-10-15 删除,现状见 [`../../网络/Net层阻塞模型架构设计.md`](../../网络/Net层阻塞模型架构设计.md))
|
||||
|
||||
---
|
||||
|
||||
@@ -98,7 +98,7 @@ test/host/time_sync/time_sync_test.c
|
||||
| 硬件 | 无(不需要开发板 / 串口 / ST-LINK / 对端 PC) |
|
||||
|
||||
工具链探测 / 编译运行 / 退出码判定全部委托通用 harness
|
||||
[`../../test/host/common/unit_test_harness.py`](../../test/host/common/unit_test_harness.py),
|
||||
[`../../../test/host/common/unit_test_harness.py`](../../../test/host/common/unit_test_harness.py),
|
||||
本模块 `run_unit_test.py` 只**声明** `TestBuild`。
|
||||
|
||||
### 1.5 运行方式
|
||||
@@ -6,12 +6,12 @@
|
||||
> **状态**:✅ 已落地(57 用例,`/W4` 0 告警,已挂 pre-commit 钩子)
|
||||
> **日期**:2026-10-10
|
||||
> **关联文档**:
|
||||
> [`../../AGENTS.md`](../../AGENTS.md)(平台约束)、
|
||||
> [`测试开发标准流程.md`](测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`../../../AGENTS.md`](../../../AGENTS.md)(平台约束)、
|
||||
> [`测试开发标准流程.md`](../流程与规范/测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`ADC输入层单元测试说明.md`](ADC输入层单元测试说明.md)(同批落地的 语义取数与有效性姊妹篇)、
|
||||
> [`../算法/傅氏算法详解.md`](../算法/傅氏算法详解.md)(**系数约定权威口径** §2.3)、
|
||||
> [`../算法/继电保护功能复现规划.md`](../算法/继电保护功能复现规划.md)(§3.2 全周傅氏相量设计点 / §10.2 术语表)、
|
||||
> [`../硬件平台/ADC通道映射说明.md`](../硬件平台/ADC通道映射说明.md)(语义取数与有效性输入口径 / 「双转换器无共同采样触发」约束)
|
||||
> [`../../算法/傅氏算法详解.md`](../../算法/傅氏算法详解.md)(**系数约定权威口径** §2.3)、
|
||||
> [`../../算法/继电保护功能复现规划.md`](../../算法/继电保护功能复现规划.md)(§3.2 全周傅氏相量设计点 / §10.2 术语表)、
|
||||
> [`../../硬件平台/ADC通道映射说明.md`](../../硬件平台/ADC通道映射说明.md)(语义取数与有效性输入口径 / 「双转换器无共同采样触发」约束)
|
||||
|
||||
---
|
||||
|
||||
@@ -67,7 +67,7 @@ test/host/phasor/phasor_test.c
|
||||
| 硬件 | 无(不需要开发板 / 串口 / ST-LINK / 信号源) |
|
||||
|
||||
工具链探测 / `INCLUDE`-`LIB` 拼接 / 编译运行 / 退出码判定全部委托通用 harness
|
||||
[`../../test/host/common/unit_test_harness.py`](../../test/host/common/unit_test_harness.py),
|
||||
[`../../../test/host/common/unit_test_harness.py`](../../../test/host/common/unit_test_harness.py),
|
||||
本模块 `run_unit_test.py` 只**声明** `TestBuild`(源文件 / 汇总行标记)。
|
||||
|
||||
### 1.5 运行方式
|
||||
@@ -6,9 +6,9 @@
|
||||
> **状态**:✅ 已落地(47 断言,`@build` 0/0,已挂 pre-commit 钩子)
|
||||
> **日期**:2026-10-01(2026-10-25 v1.5 按位分账改造;改造史与设计依据见 `docs/子系统设计/看门狗设计说明.md` 变更记录——本文档不再设变更记录节)
|
||||
> **关联文档**:
|
||||
> [`../子系统设计/看门狗设计说明.md`](../子系统设计/看门狗设计说明.md)(被测行为的设计依据)、
|
||||
> [`测试开发标准流程.md`](测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`测试文档模板规范.md`](测试文档模板规范.md)(本文命名规范)
|
||||
> [`../../子系统设计/看门狗设计说明.md`](../../子系统设计/看门狗设计说明.md)(被测行为的设计依据)、
|
||||
> [`测试开发标准流程.md`](../流程与规范/测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`测试文档模板规范.md`](../流程与规范/测试文档模板规范.md)(本文命名规范)
|
||||
|
||||
---
|
||||
|
||||
@@ -72,9 +72,9 @@ test/host/watchdog/watchdog_test.c
|
||||
> 路径调 `cl.exe`(只需 MSVC 版本目录 + Windows SDK 的 include/lib),无副作用、可重复。
|
||||
>
|
||||
> 该工具链逻辑**不在本模块目录内**(2026-10-01 抽取):已沉淀为通用 harness
|
||||
> [`../../test/host/common/unit_test_harness.py`](../../test/host/common/unit_test_harness.py),
|
||||
> [`../../../test/host/common/unit_test_harness.py`](../../../test/host/common/unit_test_harness.py),
|
||||
> 本模块的 `run_unit_test.py` 只**声明** `TestBuild`(源文件 / 桩目录 / 汇总行标记)。
|
||||
> 新增主机侧纯逻辑单测时直接复用 harness,见 [`../../test/host/common/README.md`](../../test/host/common/README.md)。
|
||||
> 新增主机侧纯逻辑单测时直接复用 harness,见 [`../../../test/host/common/README.md`](../../../test/host/common/README.md)。
|
||||
|
||||
### 1.4 运行方式
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
> **状态**:✅ 已落地(20 用例 / 100 断言点,`@build` 0/0,已挂 pre-commit 钩子)
|
||||
> **日期**:2026-10-02
|
||||
> **关联文档**:
|
||||
> [`../../AGENTS.md`](../../AGENTS.md)(平台约束)、
|
||||
> [`测试开发标准流程.md`](测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`../../../AGENTS.md`](../../../AGENTS.md)(平台约束)、
|
||||
> [`测试开发标准流程.md`](../流程与规范/测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`看门狗单元测试说明.md`](看门狗单元测试说明.md)(同层范本)
|
||||
|
||||
---
|
||||
@@ -75,7 +75,7 @@ test/host/sys_clock/sys_clock_test.c
|
||||
| 硬件 | 无(不需要开发板 / 串口 / ST-LINK) |
|
||||
|
||||
工具链探测 / `INCLUDE`-`LIB` 拼接 / 编译运行 / 退出码判定全部委托通用 harness
|
||||
[`../../test/host/common/unit_test_harness.py`](../../test/host/common/unit_test_harness.py),
|
||||
[`../../../test/host/common/unit_test_harness.py`](../../../test/host/common/unit_test_harness.py),
|
||||
本模块 `run_unit_test.py` 只**声明** `TestBuild`(源文件 / 桩目录 / 汇总行标记)。
|
||||
|
||||
### 1.4 运行方式
|
||||
@@ -249,7 +249,7 @@ TC-SYSCLK-019 的期望星期由 Python `datetime.date(...).weekday()` 独立生
|
||||
| 层 | 覆盖 | 状态 |
|
||||
|---|---|---|
|
||||
| **本单测(主机侧纯逻辑单测)** | 换算逻辑 / 星期 / 再基准化 / 故障降级 | ✅ 已落地(100 断言点) |
|
||||
| 板端测试套件 / 主机侧回归 | 真机 SD2506 I2C 读写、掉电保持、与 PC 对时联动 | 见 [`SD2506_Test_Guide.md`](SD2506_Test_Guide.md) |
|
||||
| 板端测试套件 / 主机侧回归 | 真机 SD2506 I2C 读写、掉电保持、与 PC 对时联动 | 见 [`SD2506_Test_Guide.md`](../板级测试/SD2506_Test_Guide.md) |
|
||||
|
||||
> 本单测**不替代**板端验证:I2C 时序、BCD 编解码、掉电保持、温度读等真机行为,
|
||||
> 仍需 `@test` 台架闭环确认。
|
||||
@@ -6,11 +6,11 @@
|
||||
> **状态**:✅ 已落地(20 用例 / 139 断言点,`@build` 0/0,已挂 pre-commit 钩子)
|
||||
> **日期**:2026-10-02
|
||||
> **关联文档**:
|
||||
> [`../../AGENTS.md`](../../AGENTS.md)(平台约束 · FatFs/内存铁律)、
|
||||
> [`测试开发标准流程.md`](测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`../../../AGENTS.md`](../../../AGENTS.md)(平台约束 · FatFs/内存铁律)、
|
||||
> [`测试开发标准流程.md`](../流程与规范/测试开发标准流程.md)(测试分层与门禁总览)、
|
||||
> [`看门狗单元测试说明.md`](看门狗单元测试说明.md)、
|
||||
> [`系统时钟单元测试说明.md`](系统时钟单元测试说明.md)(同层范本)、
|
||||
> [`../子系统设计/配置文件设计说明.md`](../子系统设计/配置文件设计说明.md)(模块设计)
|
||||
> [`../../子系统设计/配置文件设计说明.md`](../../子系统设计/配置文件设计说明.md)(模块设计)
|
||||
|
||||
---
|
||||
|
||||
@@ -79,7 +79,7 @@ test/host/cfg_file/cfg_file_test.c
|
||||
| 硬件 | 无(不需要开发板 / 串口 / ST-LINK / NAND) |
|
||||
|
||||
工具链探测 / `INCLUDE`-`LIB` 拼接 / 编译运行 / 退出码判定全部委托通用 harness
|
||||
[`../../test/host/common/unit_test_harness.py`](../../test/host/common/unit_test_harness.py),
|
||||
[`../../../test/host/common/unit_test_harness.py`](../../../test/host/common/unit_test_harness.py),
|
||||
本模块 `run_unit_test.py` 只**声明** `TestBuild`(源文件 / 桩目录 / 汇总行标记)。
|
||||
|
||||
### 1.4 运行方式
|
||||
@@ -12,7 +12,7 @@
|
||||
- 监听端口 **21**,根目录 `/`(即 NAND 上的 FatFS 卷)。**需要账号鉴权,设备没有匿名通道**:账号取
|
||||
`/config.ini` 的 `[ftp]` 段(`user` / `pwd_hash` = SHA-256(user‖password) / `write`),出厂默认
|
||||
**admin/admin**(用默认口令时启动日志有告警);**连续 5 次失败锁定 60 秒**。完整口径见
|
||||
`../子系统设计/网络配置说明.md`。
|
||||
`../../子系统设计/网络配置说明.md`。
|
||||
- 仅支持 **1 个并发客户端**(控制通道 Socket0 + PASV 数据通道动态 Socket2,backlog=1)。
|
||||
- 测试分两类:
|
||||
- **PC 端手测(推荐,覆盖真实 FTP 行为)**:用 `test/` 下 Python 脚本或 GUI 客户端。
|
||||
@@ -94,7 +94,7 @@
|
||||
装满就 break 并回 −1,`cmd_list` 据此回 **550** —— 目录一大,客户端拿到的是**静默截断**
|
||||
的清单外加一个错误码,而清单看起来完全像"目录里就这些"。台架实测 30 条目的根目录只回
|
||||
24 条目(1512 B),6 个文件凭空消失。修完之后,**目录清空的设备上这颗雷再也暴露不出来**,
|
||||
所以需要一个自己把目录撑过一块的回归。机理与修复见 `../问题记录/CH395F_Trap_Records.md`
|
||||
所以需要一个自己把目录撑过一块的回归。机理与修复见 `../../问题记录/CH395F_Trap_Records.md`
|
||||
的 LIST 吞包定案(定案三)增补。
|
||||
- 命令:`& '.venv\Scripts\python.exe' test/host/ftp_list_fill_test.py`(`--files 26` 默认)
|
||||
- 做什么:造 26 个 8.3 短名小文件(`ZZFTnn.TXT`)→ `LIST` → 三条判据 → 逐个 `DELE` 还原
|
||||
@@ -118,7 +118,7 @@
|
||||
- `TC-NET-801`:100KB 文件上发(MCU→PC);
|
||||
- `TC-NET-802`:100KB 文件下发(PC→MCU);
|
||||
- `TC-NET-803`:round-trip(可选)。
|
||||
- 详见 `docs/测试说明/CH395F_Test_Guide.md` 阶段 8。
|
||||
- 详见 `docs/测试说明/板级测试/CH395F_Test_Guide.md` 阶段 8。
|
||||
|
||||
---
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
## 10. 参考文档
|
||||
|
||||
- `docs/测试说明/CH395F_Test_Guide.md` —— 网络测试总说明(含阶段 8 文件传输、FTP 陷阱清单)
|
||||
- `docs/测试说明/板级测试/CH395F_Test_Guide.md` —— 网络测试总说明(含阶段 8 文件传输、FTP 陷阱清单)
|
||||
- `[计划]` FTP / PASV Socket 改造方案(尚未创建)
|
||||
- `docs/问题记录/CH395F_Trap_Records.md` —— CH395F 已知陷阱
|
||||
- `docs/网络/BSD_Socket_API_使用指南.md` —— BSD Socket API 用法
|
||||
@@ -1,6 +1,6 @@
|
||||
# GD5F2GQ5UE NAND Flash 测试规范
|
||||
|
||||
> 本规范参照 `docs/测试说明/CH395F_Test_Guide.md` 结构编写,覆盖 `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c`
|
||||
> 本规范参照 `docs/测试说明/板级测试/CH395F_Test_Guide.md` 结构编写,覆盖 `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c`
|
||||
> 全部公开/私有函数,并向上延伸到 FTL(`nand_ftl.c`)与 FatFS diskio。
|
||||
> 详细芯片行为见 `docs/芯片手册/GD5F2GQ5UExxG.md`,已知陷阱见 `docs/问题记录/GD5F2GQ5UE_Trap_Records.md`。
|
||||
>
|
||||
@@ -273,13 +273,13 @@ $cli = if ($env:DTU_STLINK_CLI) { $env:DTU_STLINK_CLI } else { (Get-Command ST-L
|
||||
日志静默观察项降级为**低风险**(保留登记,若再现则借 `[ERR] CONSOLE dropped` 计数定位)。
|
||||
- **后续(2026-10-25,道F 批 2 合并评估)**:窗内静默的同源阻塞机制
|
||||
(`drop_conn` 同步占用 netTask 400-600ms)已随「登记式拆链」修复
|
||||
(`../网络/网络自愈架构设计.md` §4.6);日志静默观察项与日志单写者化的合并评估已完成,结论与「无源 vs
|
||||
真停滞」判别口径落 `../子系统设计/控制台单写者日志设计说明.md` 文末附录——
|
||||
(`../../网络/网络自愈架构设计.md` §4.6);日志静默观察项与日志单写者化的合并评估已完成,结论与「无源 vs
|
||||
真停滞」判别口径落 `../../子系统设计/控制台单写者日志设计说明.md` 文末附录——
|
||||
再现静默先按三本账(`dbg_console_dropped/_tx_fault/_tx_timeout`)+ syslog 丢弃
|
||||
账对照定性,再决定是否开卡;销项条件 = 探针窗口心跳缺口修复版 V5 复跑(e02_probe + FTP
|
||||
≥30 min)运行期 `task stall` 与真停滞嫌疑静默段双零(2026-10-25 v1.1 起
|
||||
`MISS start` 降级为诊断行不计销项——见下方判读工具与
|
||||
`../子系统设计/看门狗设计说明.md` §6.1)。
|
||||
`../../子系统设计/看门狗设计说明.md` §6.1)。
|
||||
- **判读工具 v1.1(2026-10-25 大窗判读 F1 起)**:
|
||||
`'.venv/Scripts/python.exe' scripts/v5_log_gap_report.py <serial-assistant 日志路径>`
|
||||
——自动列 `>10s` 静默段(`--gap-threshold-s` 可调),每段带判定(NO-SOURCE /
|
||||
@@ -288,13 +288,13 @@ $cli = if ($env:DTU_STLINK_CLI) { $env:DTU_STLINK_CLI } else { (Get-Command ST-L
|
||||
2=日志无有效时戳;`--json` 机读、`--report-only` 只出报告、`--selftest`
|
||||
内嵌合成样例自检(无台架可跑)。**v1.1 变更(判读口径,先文档后脚本)**:
|
||||
① `MISS start` 降级为**诊断行**(看门狗 v1.5 按位分账后它只是复合缺席边沿,
|
||||
不代表停喂,`../子系统设计/看门狗设计说明.md` §6.1)——报告改出归因诊断:
|
||||
不代表停喂,`../../子系统设计/看门狗设计说明.md` §6.1)——报告改出归因诊断:
|
||||
开机良性 / 探针窗内 / 窗外运行期 + 窗外每分钟速率 top;v1.0 把运行期 MISS
|
||||
计违规属收紧过头(2026-10-25 台架 70min 窗 1262 条经逐窗归因实为风暴复合边沿
|
||||
与传输窗抖动),予以纠正;② `task stall` 行语义 = v1.5 起「同一任务 800ms
|
||||
单串真停摆」(行文本不变,`../子系统设计/看门狗设计说明.md` §5.3),每行都是
|
||||
单串真停摆」(行文本不变,`../../子系统设计/看门狗设计说明.md` §5.3),每行都是
|
||||
真猎物;开机豁免口径(§9 第 8 条)保留、仅作用于 MISS 诊断分类。口径唯一
|
||||
来源 = `../子系统设计/控制台单写者日志设计说明.md` 文末附录 + §9 第 8 条 +
|
||||
来源 = `../../子系统设计/控制台单写者日志设计说明.md` 文末附录 + §9 第 8 条 +
|
||||
看门狗设计说明——改口径先改文档再改脚本(自检断言会拦漂移)。
|
||||
|
||||
**执行步骤**:长跑(§4.2 V5)期间周期性打点 + 对照 `CH395F` 无关的 SD2506 侧日志判别卡点。
|
||||
@@ -346,7 +346,7 @@ cppcheck --enable=warning --error-exitcode=1 test/ 2>&1 | tee test_cppcheck_base
|
||||
但**双向是否一一对应无人校验**。
|
||||
|
||||
**目标**:新增 `[计划] scripts/check_test_traceability.py`——
|
||||
输入 `test/board/*_test_task.c` 的 TC 注释 + `docs/测试说明/*Test_Guide.md` 的 TC 编号;
|
||||
输入 `test/board/*_test_task.c` 的 TC 注释 + `docs/测试说明/板级测试/*Test_Guide.md` 的 TC 编号;
|
||||
输出 ① 文档有、代码无(未实现)② 代码有、文档无(未登记)。
|
||||
**默认仅告警(warning),不阻断提交**(与 `doc-links` 演进路径一致)。
|
||||
|
||||
@@ -461,7 +461,7 @@ CH395F / STORAGE / GD5F,未含 RTC;怀疑 RTC 构建下 `testTask` 不被创
|
||||
|
||||
| 事项 | 状态 | 实施细节 / 证据所在 |
|
||||
|---|---|---|
|
||||
| **S7** 自检结果判定 | ✅ 已落地并投用 | `测试说明/自动化测试流程.md`;提交 `4a4cd29` |
|
||||
| **S7** 自检结果判定 | ✅ 已落地并投用 | `docs/测试说明/流程与规范/自动化测试流程.md`;提交 `4a4cd29` |
|
||||
| **A1** `cfg_file` 堆分配改造 | ✅ 已闭环(含真机持久化) | `子系统设计/配置文件设计说明.md`(实施 v1.11 + 2026-10-03 真机验证记录 + 2026-10-04 独立复跑记录) |
|
||||
| **A2** 网络重建失败恢复 | ✅ 已闭环(正常路径零回归;故障分支见「网络负向场景台架验证」) | `网络/Net层阻塞模型架构设计.md` |
|
||||
| **A3** CH395F 字节命令超时 | ✅ 已闭环(正常路径零回归;故障分支待专项窗口) | — |
|
||||
@@ -477,14 +477,14 @@ CH395F / STORAGE / GD5F,未含 RTC;怀疑 RTC 构建下 `testTask` 不被创
|
||||
|
||||
| 本文项 | 上游文档 | 下游落地文档 |
|
||||
|---|---|---|
|
||||
| S7 自检判定 | —(原复审项,已闭环 2026-10-02) | `测试说明/自动化测试流程.md`(参数已落地,`4a4cd29`) |
|
||||
| S7 自检判定 | —(原复审项,已闭环 2026-10-02) | `docs/测试说明/流程与规范/自动化测试流程.md`(参数已落地,`4a4cd29`) |
|
||||
| V2/V4/V5 | `子系统设计/看门狗设计说明.md` §7 验证记录 | `子系统设计/看门狗设计说明.md` 变更记录(2026-10-03) |
|
||||
| S11 堆告警 | —(原复审项,已闭环 2026-10-03) | `内存管理/RAM使用分析与优化方案.md`(基线更新) |
|
||||
| S9 GD5F | —(第二档 #1) | `问题记录/GD5F2GQ5UE_Trap_Records.md`、`测试说明/GD5F2GQ5UE_Test_Guide.md` |
|
||||
| S9 GD5F | —(第二档 #1) | `问题记录/GD5F2GQ5UE_Trap_Records.md`、`docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md` |
|
||||
| 日志静默观察项 | `docs/任务规划/登记簿.md` | `网络/Net层阻塞模型架构设计.md`(头阻塞,历史编号) |
|
||||
| 网络重建 | —(原台账项,已闭环 2026-10-02) | `网络/Net层阻塞模型架构设计.md` |
|
||||
| S5/S4 | —(原复审项,已闭环 2026-10-03) | `测试说明/测试开发标准流程.md` |
|
||||
| 模拟器差距 | `测试说明/模拟器差距清单.md` §3 决策规则 | 本文为"需回真机"项的执行面 |
|
||||
| S5/S4 | —(原复审项,已闭环 2026-10-03) | `docs/测试说明/流程与规范/测试开发标准流程.md` |
|
||||
| 模拟器差距 | `docs/测试说明/专项验证/模拟器差距清单.md` §3 决策规则 | 本文为"需回真机"项的执行面 |
|
||||
|
||||
> **模拟器差距清单 §3 的六条"必须回真机"规则**决定"哪些改动**必须在本规划内验证——
|
||||
> 改动触及 `Drivers/BSP/` 寄存器时序 / 模拟器差距清单的硬件专属项 / 配置变更检测与回调 / 网络重建并发 / 启动段 / 内存预算,
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
| 文档 | 内容 |
|
||||
|---|---|
|
||||
| `docs/测试说明/自动化测试流程.md` | @test 闭环细节(命令 / 标记 / 失败模式) |
|
||||
| `docs/测试说明/测试文档模板规范.md` | 测试文档模板、命名规则(TM / TC / DP) |
|
||||
| `docs/测试说明/串口助手设计说明.md` | 串口调试 / 采集工具与陷阱(Python 串口助手) |
|
||||
| `docs/测试说明/串口助手使用指南.md` | 串口助手命令用法 / 工作流 / 排障 |
|
||||
| `docs/测试说明/流程与规范/自动化测试流程.md` | @test 闭环细节(命令 / 标记 / 失败模式) |
|
||||
| `docs/测试说明/流程与规范/测试文档模板规范.md` | 测试文档模板、命名规则(TM / TC / DP) |
|
||||
| `docs/测试说明/测试工具/串口助手设计说明.md` | 串口调试 / 采集工具与陷阱(Python 串口助手) |
|
||||
| `docs/测试说明/测试工具/串口助手使用指南.md` | 串口助手命令用法 / 工作流 / 排障 |
|
||||
| `docs/UI设计/UI_自动化测试流程.md` | UI 模拟器回归(ui-verify)细节 |
|
||||
| `docs/代码规范/pre-commit使用说明.md` | pre-commit 门禁配置与范围 |
|
||||
| `docs/环境与部署/项目部署环境要求.md` | 构建 / 测试工具链环境 |
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
> **主机侧纯逻辑单测与主机侧回归的区别**:主机侧回归的模拟器回归依赖 SDL / LVGL 与图形输出;主机侧纯逻辑单测是**纯计算**单测
|
||||
> (无窗口、无硬件、秒级),专测"判定逻辑"。目前仅看门狗模块使用,见
|
||||
> [`看门狗单元测试说明.md`](看门狗单元测试说明.md)。适格对象:算法 / 状态机 / 协议编解码 /
|
||||
> [`看门狗单元测试说明.md`](../单元测试/看门狗单元测试说明.md)。适格对象:算法 / 状态机 / 协议编解码 /
|
||||
> 参数校验等**无副作用**的模块。
|
||||
>
|
||||
> **CI**:**静态门禁 + 主机侧纯逻辑单测已上 CI**(Gitea Actions,`.gitea/workflows/ci.yml`,2026-10-01);
|
||||
@@ -284,17 +284,17 @@ static void phaseN_run(void) {
|
||||
**适用对象**:**无副作用**的纯逻辑模块——算法、状态机、协议编解码、参数校验等
|
||||
(例:看门狗的位图判定 / 掩码 / 计数阈值 / 整数回绕)。
|
||||
|
||||
**做法**(以看门狗为范式,见 [`看门狗单元测试说明.md`](看门狗单元测试说明.md)):
|
||||
**做法**(以看门狗为范式,见 [`看门狗单元测试说明.md`](../单元测试/看门狗单元测试说明.md)):
|
||||
|
||||
1. 模块的**硬件访问**收敛到薄平台层(`__weak` 钩子或后端函数)——参照
|
||||
`App/cfg/cfg_file_store.h` 的"共享核心 + 平台后端";
|
||||
2. 测试单元 `#include` **生产源文件**(保证测的是真代码,非副本),用桩替换平台层;
|
||||
3. 写模块侧运行器:**只声明** `TestBuild`(源码 / 桩目录 / 汇总行标记)+ 调
|
||||
`test/host/common/unit_test_harness.py`(工具链探测与编译运行细节在 harness 内,
|
||||
见 [`../../test/host/common/README.md`](../../test/host/common/README.md));
|
||||
见 [`../../../test/host/common/README.md`](../../../test/host/common/README.md));
|
||||
4. 挂 pre-commit 钩子,被改动时自动跑(**只 commit 不烧录**,秒级)。
|
||||
|
||||
**环境要求**(详见 [`../环境与部署/项目部署环境要求.md`](../环境与部署/项目部署环境要求.md) §2.3 / §2.7):
|
||||
**环境要求**(详见 [`../../环境与部署/项目部署环境要求.md`](../../环境与部署/项目部署环境要求.md) §2.3 / §2.7):
|
||||
|
||||
| 项 | 要求 | 说明 |
|
||||
|---|---|---|
|
||||
@@ -477,7 +477,7 @@ flowchart TD
|
||||
| 代码变更影响判定标准 | 立即把模块 Test_Guide **正文**改到与代码一致(现状说了算,不再记流水) |
|
||||
| 有意改视觉 | 刷黄金参考 + 重生成目检 PNG + 把新口径写进 `UI_自动化测试流程.md` 正文对应小节 |
|
||||
| 新增测试工具 / 新标记 | `自动化测试流程.md` 命令清单登记(§4.2) |
|
||||
| 栈 / 堆预算相关改动或基线重采 | 把 `@test` 的 boot_log 快照(`%TEMP%\serial-boot-test\boot_log_*.txt`)存入 `docs/测试说明/boot_log_data/` 并在其 §3 清单登记(防临时目录被清理 / 长跑日志截头丢 `[STACK]` 行) |
|
||||
| 栈 / 堆预算相关改动或基线重采 | 把 `@test` 的 boot_log 快照(`%TEMP%\serial-boot-test\boot_log_*.txt`)存入 `docs/测试说明/测试数据/boot_log_data/` 并在其 §3 清单登记(防临时目录被清理 / 长跑日志截头丢 `[STACK]` 行) |
|
||||
|
||||
> 文档与代码一体两面:**代码改了文档没同步 = 未完成**。
|
||||
|
||||
@@ -530,7 +530,7 @@ flowchart LR
|
||||
> 新增任务/栈/缓冲/代码导致的体积增长**不会在 CI 被拦**。故该跳过以 `::warning::` 明示
|
||||
> (不是弱化的 notice)并写入 step-summary。**兜底必须靠本地**:改代码后 `@build`(0/0)
|
||||
> → `python scripts/check_mem_numbers.py --scan`。详见
|
||||
> [`../CI/远程CI完整指南.md`](../CI/远程CI完整指南.md) §0.0。
|
||||
> [`../../CI/远程CI完整指南.md`](../../CI/远程CI完整指南.md) §0.0。
|
||||
|
||||
> 🔴 **`gitlint` 属 `commit-msg` stage,`--all-files` 永远跑不到它(2026-10-11 审计)**:
|
||||
> `.pre-commit-config.yaml` 当时定义 **18** 个钩子,而 CI 日志只报 **17** 个(`passed=16 skipped=1`)——
|
||||
@@ -539,7 +539,7 @@ flowchart LR
|
||||
> push 用 `event.before..sha`、跳过 merge 提交)与本地 `ci_local.py` 的 **提交信息门禁** 段分别逐条校验。
|
||||
> ⚠️ 机制根因(`stages: [commit-msg]` 写在 **gitlint 上游** 的 `.pre-commit-hooks.yaml` 里,
|
||||
> 项目配置中 grep 不到)与完整排障口径见
|
||||
> [`../CI/远程CI完整指南.md`](../CI/远程CI完整指南.md) §7"钩子条数对不上"行。
|
||||
> [`../../CI/远程CI完整指南.md`](../../CI/远程CI完整指南.md) §7"钩子条数对不上"行。
|
||||
|
||||
### 9.2 两个 job
|
||||
|
||||
@@ -553,7 +553,7 @@ flowchart LR
|
||||
两个 job 都写 step-summary + `::notice::` 汇总行,日志落 `ci-artifacts/*.log`。
|
||||
|
||||
> 📖 **步骤级细节不在本文**(探测链顺序、`GITHUB_OUTPUT` 跳过决策、`Tee` 落盘、产物存档、
|
||||
> 内网拉不到 action 的处置):见 [`../CI/远程CI完整指南.md`](../CI/远程CI完整指南.md) §5.5 / §5.2 / §5.3 / §5.4(依次为:两个 job 的步骤要点 / 触发条件 / 内网 action 拉取 / 产物与汇总)。
|
||||
> 内网拉不到 action 的处置):见 [`../../CI/远程CI完整指南.md`](../../CI/远程CI完整指南.md) §5.5 / §5.2 / §5.3 / §5.4(依次为:两个 job 的步骤要点 / 触发条件 / 内网 action 拉取 / 产物与汇总)。
|
||||
|
||||
### 9.3 本地等价:`scripts/ci_local.py`
|
||||
|
||||
@@ -586,7 +586,7 @@ CI 只在 push / PR 时跑,且需 runner 就绪。**提交前自查、或 runn
|
||||
|
||||
CI 能不能跑起来,取决于 runner 机器上四件事是否就位:**服务端开关 / runner 注册与 labels /
|
||||
看门狗常驻 / 机器级 `DTU_*` 工具变量**。清单与逐项部署步骤都在
|
||||
[`../CI/远程CI完整指南.md`](../CI/远程CI完整指南.md):§0.2(前置清单)、§2(注册)、§2.4(**看门狗**)、§4.1.3(runner 以 SYSTEM 跑,必须写 MACHINE 级变量)。
|
||||
[`../../CI/远程CI完整指南.md`](../../CI/远程CI完整指南.md):§0.2(前置清单)、§2(注册)、§2.4(**看门狗**)、§4.1.3(runner 以 SYSTEM 跑,必须写 MACHINE 级变量)。
|
||||
注册细节:`--instance` 用回环、labels 必须精确匹配 `runs-on`;看门狗缺了它 Gitea 一重启
|
||||
CI 就静默停摆(2026-10-11 实测 run 16~21 共 12 个 job 零日志)。
|
||||
|
||||
@@ -615,13 +615,13 @@ CI 就静默停摆(2026-10-11 实测 run 16~21 共 12 个 job 零日志)。
|
||||
|
||||
| 文档 | 模块 / 套件 |
|
||||
|---|---|
|
||||
| `docs/测试说明/CH395F_Test_Guide.md` | CH395F(11 阶段,TC-NET-xxx) |
|
||||
| `docs/测试说明/GD5F2GQ5UE_Test_Guide.md` | GD5F + 存储集成(TC-GD5F / TC-STO) |
|
||||
| `docs/测试说明/SD2506_Test_Guide.md` | RTC(TC-RTC-xxx) |
|
||||
| `docs/测试说明/FTP_Test_Guide.md` | FTP 服务(手动 + 阶段 8 自动化) |
|
||||
| `docs/测试说明/串口助手设计说明.md` | 串口调试工具(Python 串口助手) |
|
||||
| `docs/测试说明/自动化测试流程.md` | @test 闭环细节 |
|
||||
| `docs/测试说明/测试文档模板规范.md` | 测试文档模板与命名 |
|
||||
| `docs/测试说明/看门狗单元测试说明.md` | 看门狗判定状态机(主机侧纯逻辑单测) |
|
||||
| `docs/测试说明/系统时钟单元测试说明.md` | 系统时钟换算(主机侧纯逻辑单测) |
|
||||
| `docs/测试说明/配置文件单元测试说明.md` | 配置引擎解析/契约(主机侧纯逻辑单测) |
|
||||
| `docs/测试说明/板级测试/CH395F_Test_Guide.md` | CH395F(11 阶段,TC-NET-xxx) |
|
||||
| `docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md` | GD5F + 存储集成(TC-GD5F / TC-STO) |
|
||||
| `docs/测试说明/板级测试/SD2506_Test_Guide.md` | RTC(TC-RTC-xxx) |
|
||||
| `docs/测试说明/板级测试/FTP_Test_Guide.md` | FTP 服务(手动 + 阶段 8 自动化) |
|
||||
| `docs/测试说明/测试工具/串口助手设计说明.md` | 串口调试工具(Python 串口助手) |
|
||||
| `docs/测试说明/流程与规范/自动化测试流程.md` | @test 闭环细节 |
|
||||
| `docs/测试说明/流程与规范/测试文档模板规范.md` | 测试文档模板与命名 |
|
||||
| `docs/测试说明/单元测试/看门狗单元测试说明.md` | 看门狗判定状态机(主机侧纯逻辑单测) |
|
||||
| `docs/测试说明/单元测试/系统时钟单元测试说明.md` | 系统时钟换算(主机侧纯逻辑单测) |
|
||||
| `docs/测试说明/单元测试/配置文件单元测试说明.md` | 配置引擎解析/契约(主机侧纯逻辑单测) |
|
||||
@@ -207,7 +207,7 @@ TC-{MOD}-{NNN}
|
||||
### 7.5 引用
|
||||
|
||||
- 引用函数、宏、文件名使用反引号(`` `net_poll()` ``)
|
||||
- 引用其他文档使用仓库相对路径:`docs/问题记录/CH395F_Trap_Records.md`、`docs/测试说明/自动化测试流程.md`
|
||||
- 引用其他文档使用仓库相对路径:`docs/问题记录/CH395F_Trap_Records.md`、`docs/测试说明/流程与规范/自动化测试流程.md`
|
||||
- 代码位置引用:`文件路径:行号` 或函数名
|
||||
|
||||
### 7.6 文档维护(与代码同步)
|
||||
@@ -72,7 +72,7 @@
|
||||
实测抓基线排在采集武装之后时,`net init: OK` 从 612 ms 被拉到 7997 ms)。基线抓取因此固定在
|
||||
`open/clear` **之前**。(原先更要命的是客户端退出会打 `[ERR] [FTP] error reading next command`
|
||||
→ 直接命中 Forbidden 里的 `[ERR]`;该措辞与级别已在 2026-10-22 归入"对端行为"级,见
|
||||
`../架构设计/STM32F4-Base存储架构说明.md` §10.3。注意:RST 硬拆仍会留一条 `[ERR][NET] sockN`
|
||||
`../../架构设计/STM32F4-Base存储架构说明.md` §10.3。注意:RST 硬拆仍会留一条 `[ERR][NET] sockN`
|
||||
`TIMEOUT`——那是网络自愈架构要读的套接字超时锚点,不在降级范围内。
|
||||
- `--selftest-scope all` = 保留旧的累计口径(任一记录即 FAIL),用于**审计**或第一次建基线。
|
||||
- 给了 `--selftest-log`(本地副本)就没有基线可比 → 自动降级为累计口径并打印一行说明。
|
||||
@@ -106,7 +106,7 @@
|
||||
| 抓到日志缺 `Network Init` | `-SettleMs` 太小(boot 任务间有 ~3-4s 自然静默间隙),用默认 8000ms;2026-10-10 起首字节到达前不启动静默计时(`--first-wait-ms` 默认 12000),首行晚到不再被提前收尾 |
|
||||
| 烧录后无数据(`no_data`) | 2026-10-10 起 `no_data` = **本次等待期间零字节**(旧实现比 daemon 累计字节,常驻 daemon 下永不触发,只能靠"日志里没有 [RX] 行"兜底);开串口 + clear 必须在烧录**前**完成(`run_boot_test.py` 已保证);核对 COM 号、板子供电,看 `state/serial.log` 有无 SYS 异常行 |
|
||||
| `[MISS] fw build: <戳>`(其余标记全中) | 芯片里跑的不是这份构建:烧录没落地 / 烧错文件 / hex 未重编译。处置:`stlink_flash.py flash <hex>` 重烧并看 `READBACK: OK`;确认 `@build` 已重跑(戳取自编译时刻)。⚠ 若戳**命中**但里面的 `suite=` 与本次要跑的套件不符(想跑 CH395F 却显示 `suite=NONE dstr=off`)→ 烧的是产品镜像,`@build` 不会替你切宏(→ `board-test-suite` skill) |
|
||||
| `READBACK: FAIL` / `flash readback mismatch` | 芯片内容与 hex 逐字节不一致(写入未落地、选项字节/RDP 异常、烧错目标)。处置:按 `docs/测试说明/ST-LINK_CLI_复位使用说明.md` §7 排查;`stlink_flash.py flash` 重烧后闭环会自动复核 |
|
||||
| `READBACK: FAIL` / `flash readback mismatch` | 芯片内容与 hex 逐字节不一致(写入未落地、选项字节/RDP 异常、烧错目标)。处置:按 `docs/测试说明/测试工具/ST-LINK_CLI_复位使用说明.md` §7 排查;`stlink_flash.py flash` 重烧后闭环会自动复核 |
|
||||
| `boot banner x2 > allowed 1` | 采集窗口内板子自己复位过(IWDG 咬狗 / Fault 后 `NVIC_SystemReset` / 掉电重启)。处置:看判定里逐条打印的 `reset cause:` 定位;跑**故意复位**的套件用 `--max-boot-count N` 放宽 |
|
||||
| `marker order violated` | 标记全中但**先后顺序颠倒** = 某步在另一步之后补做(就绪屏障失序 / 失败重试补跑)。处置:看判定打印的各标记首次行号定位;`--require-order` 只在需要强约束时启用 |
|
||||
| `boot time N ms > limit` | 能开机但慢(mount 重试 / PHY 重协商 / 复位重试)。实测基线:`net init: OK` 在 **+537ms**(2026-10-10 台架);默认只报告不判(`--max-boot-ms 0`),要设门禁再给预算 |
|
||||
@@ -344,7 +344,7 @@ Get-Content '.dsh\skills\serial-assistant\scripts\state\daemon.log' -Tail 30 #
|
||||
|
||||
- **daemon 会一直占着内存吗?** 一个 Python 进程约 20MB;不需要时 `stop` 即释放。常驻与否都不影响正确性。
|
||||
- **daemon 被强杀(taskkill)会怎样?** 端口由系统自动释放;下次任何命令自动拉起新 daemon。**串口不会自动重开**,需要时再 `open`(这是设计:避免在设备异常时盲目重连)。
|
||||
- **能同时开两个串口吗?** v1 单口(一个 daemon 管一个口)。多口需求见 `docs/测试说明/串口助手设计说明.md` §8 v2 候选。
|
||||
- **能同时开两个串口吗?** v1 单口(一个 daemon 管一个口)。多口需求见 `docs/测试说明/测试工具/串口助手设计说明.md` §8 v2 候选。
|
||||
- **能直接删 `serial.log` 吗?** 可以,但代际 `gen` 不会变、写句柄不变——建议用 `clear`(原子 + 代际 +1 + 标记行)。
|
||||
- **为什么 TX 日志里是字面 `\r\n` 而不是真换行?** 日志按行存储;真换行会把一条 TX 劈成两行,转义后一条 TX 恒一行。
|
||||
- **ST-Link 烧录会抢串口吗?** 不会(烧录走 SWD,不走 COM)——这正是"串口全程保持打开、烧录前后不重开"的设计基础,也彻底绕开了 CH340 释放/重开陷阱。
|
||||
@@ -206,7 +206,7 @@ flowchart LR
|
||||
| `测试说明/serial-mcp-server_串口调试.md` | **已删除**(内容精华并入本文;工具历史见 §12) |
|
||||
| `AGENTS.md` | "串口调试"节改写为 serial_tool(配置源仍 `serial_config.json`);"自动化测试"节同步新流程 |
|
||||
| `.opencode/command/test.md` | Step 0/2/Notes 改写(前置检查 = serial_tool 可用性 + `ports`;流程 = §7.1) |
|
||||
| `docs/测试说明/自动化测试流程.md` | 采集机制描述同步(去 serial-mcp-server 表述) |
|
||||
| `docs/测试说明/流程与规范/自动化测试流程.md` | 采集机制描述同步(去 serial-mcp-server 表述) |
|
||||
| `.opencode/serial_config.json` | 结构不变(可选增 `httpPort`);`note` 更新 |
|
||||
|
||||
## 8. 非目标与 v2 候选
|
||||
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user