From f754d59218969d19dcaf65a8cf161596b616cf67 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Fri, 30 Oct 2026 07:06:38 +0800 Subject: [PATCH] =?UTF-8?q?docs(=E6=B5=8B=E8=AF=95=E8=AF=B4=E6=98=8E):=20?= =?UTF-8?q?=E6=8C=89=E7=94=A8=E9=80=94=E5=88=86=E5=85=AD=E4=B8=AA=E5=AD=90?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E5=B9=B6=E5=90=8C=E6=AD=A5=E5=85=A8=E5=BA=93?= =?UTF-8?q?=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 分层:流程与规范/ 单元测试/ 板级测试/ 专项验证/ 测试工具/ 测试数据/, 顶层只留新增的目录导航 README.md(归层判据 + 硬约束 + 本次处置记录)。 - 搬迁 28 个路径:测试数据三个目录 58 个文件为纯改名(R100,内容逐字节不变) - 全库引用同步 124 个文件:AGENTS / docs 索引 / skills / 门禁注释 / scripts - 门禁面:scripts/check_test_traceability.py 的 glob 改 rglob (分层后不递归扫描=追溯门禁直接瞎掉) - scripts/rename_ref.py:收尾的 ℹ 提示在 GBK 代码页抛 UnicodeEncodeError, 让进程以退出码 1 收场而改写其实已落盘(RC 与真实结果相反);改为把 stdout/stderr reconfigure 成 UTF-8,与 check_doc_links.py 等同法 - docs/文档规范.md §1.1 补「子目录文件过多时再分一层」;§3.6 补 rename_ref 搬整目录的两个实测坑:① 会改写目录内部文件的内容 ② 内部文件的 ../ 出链 不补层级(本次 23 个被误改的证据文件已按 HEAD 原始字节逐字节还原) - docs/README.md §6 改为与六个子目录一一对应,并补登原先漏登记的 「启动日志原子性复验流程」一行 - .cubemx_survival_baseline.json:App/util/task_watchdog.c 的注释路径也随分层更新, 该文件是存活审计的 watchdog-module 漂移锚点,按脚本自己的提示跑 --write 重建基线 (实测重建后仅 watchdog-module 一条哈希变化) - 铁律 4 例外(本次在任务树里改了单写者文件):AGENTS.md 与 .pre-commit-config.yaml 只被 rename_ref 改写路径字面量(后者全在注释行), 任务表块与钩子声明一字未动 验证:check_doc_links.py --sections-strict 覆盖全部 88 个改动 .md 全绿; check_test_traceability.py 输出与主树逐行一致;196 个文本文件无 BOM、无新增 CR、无 U+FFFD、无行尾空白;陈旧引用面由主树 25 处降到 6 处(无新增断链)。 --- .cubemx_survival_baseline.json | 2 +- .dsh/skills/board-test-suite/SKILL.md | 6 +- .../reference/steps-chinese-prefix-family.md | 2 +- .dsh/skills/lvgl-simulator/SKILL.md | 2 +- .../serial-assistant/scripts/serial_tool.py | 2 +- .dsh/skills/serial-boot-test/SKILL.md | 2 +- .../serial-boot-test/scripts/verify_log.py | 2 +- .dsh/skills/stlink-flash/SKILL.md | 2 +- .gitea/workflows/ci.yml | 2 +- .pre-commit-config.yaml | 6 +- AGENTS.md | 12 +-- App/algo/README.md | 2 +- App/task/adc_task.c | 2 +- App/util/README.md | 4 +- App/util/task_watchdog.c | 6 +- App/util/task_watchdog.h | 2 +- Drivers/BSP/CH395F/README.md | 2 +- Drivers/BSP/GD5F2GQ5UE/README.md | 4 +- Drivers/BSP/GD5F2GQ5UE/nand_ftl.h | 2 +- Drivers/BSP/NET/README.md | 2 +- Drivers/BSP/NET/lftpd/README.md | 2 +- Drivers/BSP/README.md | 2 +- Drivers/BSP/SD2506/README.md | 2 +- Drivers/BSP/bsp_err.h | 2 +- MDK-ARM/README.md | 4 +- README.md | 6 +- docs/CI/README.md | 2 +- docs/CI/远程CI完整指南.md | 6 +- docs/README.md | 78 ++++++++------ docs/UI设计/RemoDispBus协议与接收设计说明.md | 2 +- docs/UI设计/UI_数据供给设计说明.md | 2 +- docs/UI设计/UI_自动化测试流程.md | 6 +- docs/产品需求/产品需求设计文档.md | 12 +-- docs/代码规范/pre-commit使用说明.md | 2 +- docs/任务规划/README.md | 2 +- docs/任务规划/UI补齐.md | 2 +- docs/任务规划/数据可信.md | 28 ++--- docs/任务规划/登记簿.md | 8 +- docs/内存管理/RAM使用分析与优化方案.md | 6 +- docs/子系统设计/IEC104上行设计说明.md | 2 +- docs/子系统设计/控制台单写者日志设计说明.md | 20 ++-- docs/子系统设计/故障录波设计说明.md | 6 +- docs/子系统设计/看门狗设计说明.md | 12 +-- docs/子系统设计/网络配置说明.md | 2 +- docs/子系统设计/运行与自检记录设计说明.md | 2 +- docs/子系统设计/配置文件设计说明.md | 2 +- docs/文档规范.md | 16 ++- docs/架构设计/STM32F4-Base存储架构说明.md | 4 +- docs/架构设计/项目架构总览.md | 6 +- docs/测试说明/README.md | 73 +++++++++++++ .../{ => 专项验证}/ADC前端注入验证流程.md | 8 +- .../{ => 专项验证}/启动日志原子性复验流程.md | 18 ++-- .../{ => 专项验证}/存储维护与容量恢复.md | 4 +- .../测试说明/{ => 专项验证}/模拟器差距清单.md | 2 +- .../{ => 专项验证}/链路延迟测试说明.md | 70 ++++++------- .../{ => 单元测试}/ADC输入层单元测试说明.md | 10 +- .../{ => 单元测试}/主机单测覆盖率口径.md | 16 +-- .../{ => 单元测试}/卷锁单元测试说明.md | 8 +- .../{ => 单元测试}/开机账本单元测试说明.md | 8 +- .../{ => 单元测试}/时间同步单元测试说明.md | 12 +-- .../{ => 单元测试}/相量层单元测试说明.md | 12 +-- .../{ => 单元测试}/看门狗单元测试说明.md | 10 +- .../{ => 单元测试}/系统时钟单元测试说明.md | 8 +- .../{ => 单元测试}/配置文件单元测试说明.md | 8 +- .../{ => 板级测试}/CH395F_Test_Guide.md | 0 .../测试说明/{ => 板级测试}/FTP_Test_Guide.md | 8 +- .../{ => 板级测试}/GD5F2GQ5UE_Test_Guide.md | 2 +- .../{ => 板级测试}/SD2506_Test_Guide.md | 0 .../{ => 板级测试}/实机测试实施指南.md | 24 ++--- .../{ => 流程与规范}/测试开发标准流程.md | 46 ++++----- .../{ => 流程与规范}/测试文档模板规范.md | 2 +- .../{ => 流程与规范}/自动化测试流程.md | 4 +- .../ST-LINK_CLI_复位使用说明.md | 0 .../{ => 测试工具}/串口助手使用指南.md | 2 +- .../{ => 测试工具}/串口助手设计说明.md | 2 +- .../20261010_prod_adc_l1_boot_log.txt | 0 .../20261010_prod_adc_tim6_boot_log.txt | 0 .../20261011_prod_adc_health_boot_log.txt | 0 .../20261011_prod_phasor_boot_log.txt | 0 .../20261012_B6_iec104_roundtrip_log.txt | Bin ...261012_B6_iec104_roundtrip_pre-fix_log.txt | Bin .../20261012_B6_prod_boot_log.txt | 0 ...20261012_B6_prod_boot_log_PROTECT_MISS.txt | 0 .../20261012_B7_iec104_persist_log.txt | 0 .../20261012_B7_persist_boot_log.txt | 0 .../20261012_B9_iec104_soe_post_log.txt | Bin .../20261012_B9_iec104_soe_pre_log.txt | Bin .../20261012_B9_prod_boot_log.txt | Bin .../20261012_B9_soe_decode_post.txt | Bin .../20261012_B9_soe_decode_pre.txt | Bin .../20261021_probe_stale_gate_boot_log.txt | 0 .../20261025_uinav_blindwalk_cascade.png | Bin .../20261025_uinav_blindwalk_pwd512.png | Bin .../20261025_uinav_popup_clipped.png | Bin .../20261026_bench23_flash_boot_log.txt | 0 .../20261026_bench23_recheck_verdicts.txt | 0 ...0261026_bench23_reset_only_boots_r1_r4.txt | 0 .../20261026_prod_77779d49_boot_log.txt | 0 ...1026_prod_77779d49_boot_log_reset_only.txt | 0 ...1026_prod_77779d49_iec104_setpoint_leg.txt | 0 .../20261026_prod_77779d49_ui_nav_trace.json | 0 ...61026_prod_77779d49_ui_set_badge_uncal.png | Bin ...od_77779d49_ui_set_edit_enter_accepted.png | Bin ...026_prod_77779d49_ui_set_view_readonly.png | Bin ...61026_prod_console_interleave_evidence.txt | 0 ...261026_task24_boardnav_standby_unknown.png | Bin .../20261026_task24_boardnav_trace.json | 0 .../20261026_task24_boardnav_view_set.png | Bin ...0261027_bench42_reset_only_boots_r1_r4.txt | 0 .../20261027_bench42_ui_clock_page.png | Bin .../20261027_bench42_verdicts.txt | 0 .../{ => 测试数据}/boot_log_data/README.md | 14 +-- .../f3rounds_r1_7003_churn_30min.log.gz | Bin .../f3rounds_r2_probe_30min.log.gz | Bin .../测试说明/{ => 测试数据}/m2_data/README.md | 6 +- .../{ => 测试数据}/m2_data/m2_quiet.json | 0 .../{ => 测试数据}/m2_data/m2_quiet_r200.json | 0 .../{ => 测试数据}/m2_data/m2_quiet_r500.json | 0 .../m2_data/m2_quiet_run13.json | 0 .../m2_data/m2_quiet_run14.json | 0 .../m2_data/m2_serial_excerpt_run13.txt | 0 .../m2_data/m2_serial_excerpt_run15.txt | 0 .../{ => 测试数据}/m3_data/m3_dev_quiet.json | 0 .../m3_data/m3_dev_quiet_fixed.json | 0 .../m3_data/m3_dev_quiet_r200.json | 0 .../{ => 测试数据}/m3_data/m3_dev_stress.json | 0 .../m3_data/m3_dev_stress_fixed.json | 0 .../m3_data/m3_dev_stress_r200.json | 0 .../m3_data/m3_pending_quiet.json | 0 .../m3_data/m3_pending_stress.json | 0 .../{ => 测试数据}/m3_data/m3_sim_quiet.json | 0 .../m3_data/m3_tail_ackfast.json | 0 .../m3_data/m3_tail_ackprobe.json | 0 docs/环境与部署/并行任务工作树方案.md | 4 +- docs/环境与部署/项目部署环境要求.md | 14 +-- docs/硬件平台/ADC通道映射说明.md | 2 +- docs/算法/继电保护功能复现规划.md | 12 +-- docs/算法/采样有效性校验设计说明.md | 4 +- docs/算法/采集与算法层设计说明.md | 8 +- docs/网络/BSD_Socket_API_函数调用关系.md | 4 +- docs/网络/Net层阻塞模型架构设计.md | 4 +- docs/网络/网络自愈架构设计.md | 2 +- docs/门禁说明/README.md | 2 +- docs/门禁说明/bsp-err.md | 2 +- docs/门禁说明/host-unit-tests.md | 2 +- docs/门禁说明/test-suite-switch.md | 2 +- docs/问题记录/ADC_Trap_Records.md | 2 +- docs/问题记录/CH395F_Trap_Records.md | 6 +- scripts/README.md | 4 +- scripts/archive/id_gate/id_aliases.json | 20 ++-- scripts/archive/id_gate/id_registry.json | 34 +++---- scripts/archive/id_gate/编号治理历史.md | 8 +- scripts/check_test_coverage.py | 14 +-- scripts/check_test_suite.py | 2 +- scripts/check_test_traceability.py | 16 +-- scripts/ci_local.py | 8 +- scripts/rename_maps/batch-lprot-semantic.json | 96 +++++++++--------- scripts/rename_maps/batch3-trap.json | 4 +- scripts/rename_maps/batch8-s-review-dead.json | 28 ++--- scripts/rename_ref.py | 8 ++ scripts/stack_tolerance.tsv | 2 +- scripts/test_coverage_baseline.json | 2 +- scripts/v5_log_gap_report.py | 4 +- simulator/README.md | 6 +- simulator/main.c | 4 +- simulator/sim/sim_syslog.c | 2 +- test/README.md | 8 +- test/board/README.md | 4 +- test/board/ch395f_test.h | 10 +- test/board/ch395f_test_task.c | 4 +- test/board/gd5f_test.h | 2 +- test/board/net_latency_test.c | 2 +- test/board/net_latency_test.h | 2 +- test/board/net_test_task.c | 6 +- test/board/sd2506_test_task.c | 2 +- test/board/test_common.h | 2 +- test/board/test_config.h | 4 +- test/host/README.md | 28 ++--- test/host/adc_health/run_unit_test.py | 2 +- test/host/cfg_file/cfg_file_test.c | 2 +- test/host/cfg_file/run_unit_test.py | 2 +- test/host/cfg_file_store_mcu/run_unit_test.py | 2 +- test/host/common/README.md | 4 +- test/host/common/unit_test_harness.py | 8 +- test/host/console_log/console_log_test.c | 5 +- test/host/console_log/run_unit_test.py | 2 +- test/host/ftp_cfg/run_unit_test.py | 2 +- test/host/iec104_serv/run_unit_test.py | 2 +- test/host/latency_peer.py | 2 +- test/host/lftpd/run_unit_test.py | 4 +- test/host/lftpd_inet/run_unit_test.py | 4 +- test/host/lftpd_io/run_unit_test.py | 2 +- test/host/net_cfg/run_unit_test.py | 2 +- test/host/net_events/run_unit_test.py | 2 +- test/host/net_listener/run_unit_test.py | 2 +- test/host/net_pending/run_unit_test.py | 2 +- test/host/net_select/run_unit_test.py | 2 +- test/host/net_socket/run_unit_test.py | 2 +- test/host/phasor/run_unit_test.py | 2 +- test/host/prot_set_store/run_unit_test.py | 2 +- test/host/soe_store/run_unit_test.py | 2 +- test/host/sys_clock/run_unit_test.py | 2 +- test/host/sys_clock/sys_clock_test.c | 2 +- test/host/sys_log_mcu/run_unit_test.py | 2 +- test/host/task_prof/run_unit_test.py | 2 +- test/host/watchdog/run_unit_test.py | 2 +- test/host/watchdog/watchdog_test.c | 2 +- test/run_all_suites.py | 2 +- tools/README.md | 2 +- 209 files changed, 644 insertions(+), 528 deletions(-) create mode 100644 docs/测试说明/README.md rename docs/测试说明/{ => 专项验证}/ADC前端注入验证流程.md (99%) rename docs/测试说明/{ => 专项验证}/启动日志原子性复验流程.md (94%) rename docs/测试说明/{ => 专项验证}/存储维护与容量恢复.md (97%) rename docs/测试说明/{ => 专项验证}/模拟器差距清单.md (99%) rename docs/测试说明/{ => 专项验证}/链路延迟测试说明.md (93%) rename docs/测试说明/{ => 单元测试}/ADC输入层单元测试说明.md (96%) rename docs/测试说明/{ => 单元测试}/主机单测覆盖率口径.md (98%) rename docs/测试说明/{ => 单元测试}/卷锁单元测试说明.md (96%) rename docs/测试说明/{ => 单元测试}/开机账本单元测试说明.md (95%) rename docs/测试说明/{ => 单元测试}/时间同步单元测试说明.md (95%) rename docs/测试说明/{ => 单元测试}/相量层单元测试说明.md (93%) rename docs/测试说明/{ => 单元测试}/看门狗单元测试说明.md (95%) rename docs/测试说明/{ => 单元测试}/系统时钟单元测试说明.md (97%) rename docs/测试说明/{ => 单元测试}/配置文件单元测试说明.md (97%) rename docs/测试说明/{ => 板级测试}/CH395F_Test_Guide.md (100%) rename docs/测试说明/{ => 板级测试}/FTP_Test_Guide.md (97%) rename docs/测试说明/{ => 板级测试}/GD5F2GQ5UE_Test_Guide.md (99%) rename docs/测试说明/{ => 板级测试}/SD2506_Test_Guide.md (100%) rename docs/测试说明/{ => 板级测试}/实机测试实施指南.md (96%) rename docs/测试说明/{ => 流程与规范}/测试开发标准流程.md (93%) rename docs/测试说明/{ => 流程与规范}/测试文档模板规范.md (99%) rename docs/测试说明/{ => 流程与规范}/自动化测试流程.md (98%) rename docs/测试说明/{ => 测试工具}/ST-LINK_CLI_复位使用说明.md (100%) rename docs/测试说明/{ => 测试工具}/串口助手使用指南.md (99%) rename docs/测试说明/{ => 测试工具}/串口助手设计说明.md (99%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261010_prod_adc_l1_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261010_prod_adc_tim6_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261011_prod_adc_health_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261011_prod_phasor_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B6_iec104_roundtrip_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B6_iec104_roundtrip_pre-fix_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B6_prod_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B6_prod_boot_log_PROTECT_MISS.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B7_iec104_persist_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B7_persist_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B9_iec104_soe_post_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B9_iec104_soe_pre_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B9_prod_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B9_soe_decode_post.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261012_B9_soe_decode_pre.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261021_probe_stale_gate_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261025_uinav_blindwalk_cascade.png (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261025_uinav_blindwalk_pwd512.png (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261025_uinav_popup_clipped.png (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_bench23_flash_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_bench23_recheck_verdicts.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_bench23_reset_only_boots_r1_r4.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_prod_77779d49_boot_log.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_prod_77779d49_boot_log_reset_only.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_prod_77779d49_iec104_setpoint_leg.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_prod_77779d49_ui_nav_trace.json (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_prod_77779d49_ui_set_badge_uncal.png (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_prod_77779d49_ui_set_edit_enter_accepted.png (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_prod_77779d49_ui_set_view_readonly.png (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_prod_console_interleave_evidence.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_task24_boardnav_standby_unknown.png (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_task24_boardnav_trace.json (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261026_task24_boardnav_view_set.png (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261027_bench42_reset_only_boots_r1_r4.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261027_bench42_ui_clock_page.png (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/20261027_bench42_verdicts.txt (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/README.md (96%) rename docs/测试说明/{ => 测试数据}/boot_log_data/f3rounds_r1_7003_churn_30min.log.gz (100%) rename docs/测试说明/{ => 测试数据}/boot_log_data/f3rounds_r2_probe_30min.log.gz (100%) rename docs/测试说明/{ => 测试数据}/m2_data/README.md (95%) rename docs/测试说明/{ => 测试数据}/m2_data/m2_quiet.json (100%) rename docs/测试说明/{ => 测试数据}/m2_data/m2_quiet_r200.json (100%) rename docs/测试说明/{ => 测试数据}/m2_data/m2_quiet_r500.json (100%) rename docs/测试说明/{ => 测试数据}/m2_data/m2_quiet_run13.json (100%) rename docs/测试说明/{ => 测试数据}/m2_data/m2_quiet_run14.json (100%) rename docs/测试说明/{ => 测试数据}/m2_data/m2_serial_excerpt_run13.txt (100%) rename docs/测试说明/{ => 测试数据}/m2_data/m2_serial_excerpt_run15.txt (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_dev_quiet.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_dev_quiet_fixed.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_dev_quiet_r200.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_dev_stress.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_dev_stress_fixed.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_dev_stress_r200.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_pending_quiet.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_pending_stress.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_sim_quiet.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_tail_ackfast.json (100%) rename docs/测试说明/{ => 测试数据}/m3_data/m3_tail_ackprobe.json (100%) diff --git a/.cubemx_survival_baseline.json b/.cubemx_survival_baseline.json index 8626cd24..0bddc59f 100644 --- a/.cubemx_survival_baseline.json +++ b/.cubemx_survival_baseline.json @@ -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", diff --git a/.dsh/skills/board-test-suite/SKILL.md b/.dsh/skills/board-test-suite/SKILL.md index 9f1f91a8..8796e52d 100644 --- a/.dsh/skills/board-test-suite/SKILL.md +++ b/.dsh/skills/board-test-suite/SKILL.md @@ -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。 ## 其它项目怎么套 diff --git a/.dsh/skills/id-family-semantic-migration/reference/steps-chinese-prefix-family.md b/.dsh/skills/id-family-semantic-migration/reference/steps-chinese-prefix-family.md index c6aa16e3..820aed0a 100644 --- a/.dsh/skills/id-family-semantic-migration/reference/steps-chinese-prefix-family.md +++ b/.dsh/skills/id-family-semantic-migration/reference/steps-chinese-prefix-family.md @@ -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 :<文档> | 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 行删除并注明证据属主)。 diff --git a/.dsh/skills/lvgl-simulator/SKILL.md b/.dsh/skills/lvgl-simulator/SKILL.md index b703fefb..224c5fdf 100644 --- a/.dsh/skills/lvgl-simulator/SKILL.md +++ b/.dsh/skills/lvgl-simulator/SKILL.md @@ -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`「四、已知坑(构建/运行)」) diff --git a/.dsh/skills/serial-assistant/scripts/serial_tool.py b/.dsh/skills/serial-assistant/scripts/serial_tool.py index d4a18735..617e2471 100644 --- a/.dsh/skills/serial-assistant/scripts/serial_tool.py +++ b/.dsh/skills/serial-assistant/scripts/serial_tool.py @@ -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) diff --git a/.dsh/skills/serial-boot-test/SKILL.md b/.dsh/skills/serial-boot-test/SKILL.md index 9a775cfb..1a16da61 100644 --- a/.dsh/skills/serial-boot-test/SKILL.md +++ b/.dsh/skills/serial-boot-test/SKILL.md @@ -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=` 是显式逃生口,不是默认)。子串 `--required` 不能用于"可能丢行首/被插字节"的行。来龙去脉与固定动作见本仓 `docs/测试说明/启动日志原子性复验流程.md`。 +> **判据取向(重要,会复发)**:`--exact` 默认**只锚文本、不钉长度**——字节长度属于某一份构建,钉死它会在无辜改动上假红(`@@LEN=` 是显式逃生口,不是默认)。子串 `--required` 不能用于"可能丢行首/被插字节"的行。来龙去脉与固定动作见本仓 `docs/测试说明/专项验证/启动日志原子性复验流程.md`。 交互式串口操作(open/send/log/wait-idle/status 等)不属于本 skill—— **用 `serial-assistant` skill**。 diff --git a/.dsh/skills/serial-boot-test/scripts/verify_log.py b/.dsh/skills/serial-boot-test/scripts/verify_log.py index 77348e25..d454fb7b 100644 --- a/.dsh/skills/serial-boot-test/scripts/verify_log.py +++ b/.dsh/skills/serial-boot-test/scripts/verify_log.py @@ -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 后 diff --git a/.dsh/skills/stlink-flash/SKILL.md b/.dsh/skills/stlink-flash/SKILL.md index 868e8f9a..09ed4c2c 100644 --- a/.dsh/skills/stlink-flash/SKILL.md +++ b/.dsh/skills/stlink-flash/SKILL.md @@ -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 的衔接 diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index b5e15eac..0048ba23 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -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 强制) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f6d32632..f9081c8c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -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,套件数 diff --git a/AGENTS.md b/AGENTS.md index 9c605aff..5078abc4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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` 的 ``**——否则报错落在**消费者 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:`) | **`task-worktree` skill**(`@task`,用到自动加载;插件桥 → 其 F 节)、`docs/环境与部署/并行任务工作树方案.md` §3.4 | diff --git a/App/algo/README.md b/App/algo/README.md index 27659538..d1411daf 100644 --- a/App/algo/README.md +++ b/App/algo/README.md @@ -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` diff --git a/App/task/adc_task.c b/App/task/adc_task.c index 10c2f87c..93a29873 100644 --- a/App/task/adc_task.c +++ b/App/task/adc_task.c @@ -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; diff --git a/App/util/README.md b/App/util/README.md index 39661683..1816eb8c 100644 --- a/App/util/README.md +++ b/App/util/README.md @@ -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` diff --git a/App/util/task_watchdog.c b/App/util/task_watchdog.c index 48184d15..e9236da2 100644 --- a/App/util/task_watchdog.c +++ b/App/util/task_watchdog.c @@ -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 守卫:该宏下不编入默认实现,仅留桩。 diff --git a/App/util/task_watchdog.h b/App/util/task_watchdog.h index 7c9aff28..78820e0b 100644 --- a/App/util/task_watchdog.h +++ b/App/util/task_watchdog.h @@ -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 寄存器 / diff --git a/Drivers/BSP/CH395F/README.md b/Drivers/BSP/CH395F/README.md index 667a7835..6b76cb1b 100644 --- a/Drivers/BSP/CH395F/README.md +++ b/Drivers/BSP/CH395F/README.md @@ -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` diff --git a/Drivers/BSP/GD5F2GQ5UE/README.md b/Drivers/BSP/GD5F2GQ5UE/README.md index f09710f3..513c39d3 100644 --- a/Drivers/BSP/GD5F2GQ5UE/README.md +++ b/Drivers/BSP/GD5F2GQ5UE/README.md @@ -42,5 +42,5 @@ GD5F2GQ5UE 芯片 ## 相关文档 - 存储架构:`docs/架构设计/STM32F4-Base存储架构说明.md` -- 测试指南:`docs/测试说明/GD5F2GQ5UE_Test_Guide.md` -- 容量恢复:`docs/测试说明/存储维护与容量恢复.md` +- 测试指南:`docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md` +- 容量恢复:`docs/测试说明/专项验证/存储维护与容量恢复.md` diff --git a/Drivers/BSP/GD5F2GQ5UE/nand_ftl.h b/Drivers/BSP/GD5F2GQ5UE/nand_ftl.h index 86dea1d8..a89a786f 100644 --- a/Drivers/BSP/GD5F2GQ5UE/nand_ftl.h +++ b/Drivers/BSP/GD5F2GQ5UE/nand_ftl.h @@ -40,7 +40,7 @@ int nand_ftl_init(void); * 限定条件:只允许走显式命令或恢复流程调用;不得因"某次读写失败"自动调用 * 函数说明:新卷从空树写起,避免旧 journal 残留与新卷共存(结构卫生)。 * 容量恢复动作的区分(A 清日志 / B 重挂载 / C 全片擦除 / D 残留清理) - * → ../测试说明/存储维护与容量恢复.md。 + * → docs/测试说明/专项验证/存储维护与容量恢复.md。 */ int nand_ftl_format(void); diff --git a/Drivers/BSP/NET/README.md b/Drivers/BSP/NET/README.md index 0845caa9..0a5b2c18 100644 --- a/Drivers/BSP/NET/README.md +++ b/Drivers/BSP/NET/README.md @@ -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` diff --git a/Drivers/BSP/NET/lftpd/README.md b/Drivers/BSP/NET/lftpd/README.md index 257a95d8..a835da52 100644 --- a/Drivers/BSP/NET/lftpd/README.md +++ b/Drivers/BSP/NET/lftpd/README.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 diff --git a/Drivers/BSP/README.md b/Drivers/BSP/README.md index aef28018..04463172 100644 --- a/Drivers/BSP/README.md +++ b/Drivers/BSP/README.md @@ -44,4 +44,4 @@ - 架构全景:`docs/架构设计/项目架构总览.md` - 存储栈:`docs/架构设计/STM32F4-Base存储架构说明.md` -- 测试指南:`docs/测试说明/*_Test_Guide.md` +- 测试指南:`docs/测试说明/板级测试/*_Test_Guide.md` diff --git a/Drivers/BSP/SD2506/README.md b/Drivers/BSP/SD2506/README.md index d5166599..23950921 100644 --- a/Drivers/BSP/SD2506/README.md +++ b/Drivers/BSP/SD2506/README.md @@ -24,5 +24,5 @@ ## 相关文档 - 墙钟维护:`docs/子系统设计/系统墙钟时间维护说明.md` -- 测试指南:`docs/测试说明/SD2506_Test_Guide.md` +- 测试指南:`docs/测试说明/板级测试/SD2506_Test_Guide.md` - 陷阱台账:`docs/问题记录/SD2506_Trap_Records.md` diff --git a/Drivers/BSP/bsp_err.h b/Drivers/BSP/bsp_err.h index 564a4e49..7965a463 100644 --- a/Drivers/BSP/bsp_err.h +++ b/Drivers/BSP/bsp_err.h @@ -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 栈的教训在前,栈预算不欢迎「顺手加一层」。 diff --git a/MDK-ARM/README.md b/MDK-ARM/README.md index 0980c758..07886f30 100644 --- a/MDK-ARM/README.md +++ b/MDK-ARM/README.md @@ -60,6 +60,6 @@ ## 相关文档 -- 烧录/复位:`docs/测试说明/ST-LINK_CLI_复位使用说明.md` +- 烧录/复位:`docs/测试说明/测试工具/ST-LINK_CLI_复位使用说明.md` - 构建与验证:根 `AGENTS.md`「构建与验证」章 -- 测试流程:`docs/测试说明/自动化测试流程.md` +- 测试流程:`docs/测试说明/流程与规范/自动化测试流程.md` diff --git a/README.md b/README.md index ae7eceeb..3921fe47 100644 --- a/README.md +++ b/README.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/芯片手册/` | 硬件数据手册 | diff --git a/docs/CI/README.md b/docs/CI/README.md index 28e03ba2..845b9502 100644 --- a/docs/CI/README.md +++ b/docs/CI/README.md @@ -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) diff --git a/docs/CI/远程CI完整指南.md b/docs/CI/远程CI完整指南.md index e3345b75..87766c31 100644 --- a/docs/CI/远程CI完整指南.md +++ b/docs/CI/远程CI完整指南.md @@ -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` | 步骤要点 | |---|---|---| diff --git a/docs/README.md b/docs/README.md index 361e2ec4..8d92c3c0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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)。 diff --git a/docs/UI设计/RemoDispBus协议与接收设计说明.md b/docs/UI设计/RemoDispBus协议与接收设计说明.md index 3d9a8f2d..c9953bba 100644 --- a/docs/UI设计/RemoDispBus协议与接收设计说明.md +++ b/docs/UI设计/RemoDispBus协议与接收设计说明.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` | diff --git a/docs/UI设计/UI_数据供给设计说明.md b/docs/UI设计/UI_数据供给设计说明.md index 771dec4b..49949ff4 100644 --- a/docs/UI设计/UI_数据供给设计说明.md +++ b/docs/UI设计/UI_数据供给设计说明.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 钩子 | diff --git a/docs/UI设计/UI_自动化测试流程.md b/docs/UI设计/UI_自动化测试流程.md index 0e4a7b23..6945c989 100644 --- a/docs/UI设计/UI_自动化测试流程.md +++ b/docs/UI设计/UI_自动化测试流程.md @@ -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`;要区分得看行内文本,写路径判据需要时再加。 diff --git a/docs/产品需求/产品需求设计文档.md b/docs/产品需求/产品需求设计文档.md index 41452e13..0b355546 100644 --- a/docs/产品需求/产品需求设计文档.md +++ b/docs/产品需求/产品需求设计文档.md @@ -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`(仓库根) | diff --git a/docs/代码规范/pre-commit使用说明.md b/docs/代码规范/pre-commit使用说明.md index 4a166c2f..76567adc 100644 --- a/docs/代码规范/pre-commit使用说明.md +++ b/docs/代码规范/pre-commit使用说明.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。 ### 依赖清单 diff --git a/docs/任务规划/README.md b/docs/任务规划/README.md index ef8f2624..b5cee013 100644 --- a/docs/任务规划/README.md +++ b/docs/任务规划/README.md @@ -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 页面分支。上板验证可累积成一批,但保存、重启、主站读回等判据不能删除。 diff --git a/docs/任务规划/UI补齐.md b/docs/任务规划/UI补齐.md index ef02e3d6..494eff18 100644 --- a/docs/任务规划/UI补齐.md +++ b/docs/任务规划/UI补齐.md @@ -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 | --- diff --git a/docs/任务规划/数据可信.md b/docs/任务规划/数据可信.md index b99114b2..e4881783 100644 --- a/docs/任务规划/数据可信.md +++ b/docs/任务规划/数据可信.md @@ -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`** | 算法与判据正文(全周傅氏、测频、保护元件);本文只规定"这些算法的信度到什么程度" | diff --git a/docs/任务规划/登记簿.md b/docs/任务规划/登记簿.md index 642047db..a29393cf 100644 --- a/docs/任务规划/登记簿.md +++ b/docs/任务规划/登记簿.md @@ -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 全部置位才走保护判据。 未完成标准源标定就送检,保护会表现为不动作。保持该闭锁,不用非标准源标定走捷径。 diff --git a/docs/内存管理/RAM使用分析与优化方案.md b/docs/内存管理/RAM使用分析与优化方案.md index c4701da7..62afb799 100644 --- a/docs/内存管理/RAM使用分析与优化方案.md +++ b/docs/内存管理/RAM使用分析与优化方案.md @@ -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(三档表与门的细节都在那节)。 本节口径与本文的运行时水位小节、静态硬线小节互指(同文件内引用,不再另标编号,避免跨文档串号)。 **取证纪律(本节方法的可复用模板)**:凡跨树/跨构建引用数字,必须同时钉**产物路径 + diff --git a/docs/子系统设计/IEC104上行设计说明.md b/docs/子系统设计/IEC104上行设计说明.md index 9132ac49..a836f330 100644 --- a/docs/子系统设计/IEC104上行设计说明.md +++ b/docs/子系统设计/IEC104上行设计说明.md @@ -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 限制与待办(如实登记) diff --git a/docs/子系统设计/控制台单写者日志设计说明.md b/docs/子系统设计/控制台单写者日志设计说明.md index a1613cde..a8ebe388 100644 --- a/docs/子系统设计/控制台单写者日志设计说明.md +++ b/docs/子系统设计/控制台单写者日志设计说明.md @@ -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)。本评估补充一个此前 diff --git a/docs/子系统设计/故障录波设计说明.md b/docs/子系统设计/故障录波设计说明.md index 0bea8cd2..98412f85 100644 --- a/docs/子系统设计/故障录波设计说明.md +++ b/docs/子系统设计/故障录波设计说明.md @@ -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`)→ 定时模式必须**默认关闭 + 有时长上限 + 启动时打一次告警**,用完立刻回产品构建。 --- diff --git a/docs/子系统设计/看门狗设计说明.md b/docs/子系统设计/看门狗设计说明.md index 6f69b370..c49c3bd5 100644 --- a/docs/子系统设计/看门狗设计说明.md +++ b/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 失败 | diff --git a/docs/子系统设计/网络配置说明.md b/docs/子系统设计/网络配置说明.md index 4ade2d29..69f68d9f 100644 --- a/docs/子系统设计/网络配置说明.md +++ b/docs/子系统设计/网络配置说明.md @@ -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` | diff --git a/docs/子系统设计/运行与自检记录设计说明.md b/docs/子系统设计/运行与自检记录设计说明.md index c2fb0a78..4c17d8ad 100644 --- a/docs/子系统设计/运行与自检记录设计说明.md +++ b/docs/子系统设计/运行与自检记录设计说明.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` | 共享 | 自检记录内容页描述符(同上) | diff --git a/docs/子系统设计/配置文件设计说明.md b/docs/子系统设计/配置文件设计说明.md index 25ff2b68..d2831bce 100644 --- a/docs/子系统设计/配置文件设计说明.md +++ b/docs/子系统设计/配置文件设计说明.md @@ -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 端到端) diff --git a/docs/文档规范.md b/docs/文档规范.md index aa887590..60757590 100644 --- a/docs/文档规范.md +++ b/docs/文档规范.md @@ -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` 的 ``、`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` 的 ``(→ `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` 同法。 --- diff --git a/docs/架构设计/STM32F4-Base存储架构说明.md b/docs/架构设计/STM32F4-Base存储架构说明.md index 1ea3466f..672b7f59 100644 --- a/docs/架构设计/STM32F4-Base存储架构说明.md +++ b/docs/架构设计/STM32F4-Base存储架构说明.md @@ -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 干净且无 diff --git a/docs/架构设计/项目架构总览.md b/docs/架构设计/项目架构总览.md index 01935760..fffd6b32 100644 --- a/docs/架构设计/项目架构总览.md +++ b/docs/架构设计/项目架构总览.md @@ -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` | diff --git a/docs/测试说明/README.md b/docs/测试说明/README.md new file mode 100644 index 00000000..f1b93bb1 --- /dev/null +++ b/docs/测试说明/README.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`)。 diff --git a/docs/测试说明/ADC前端注入验证流程.md b/docs/测试说明/专项验证/ADC前端注入验证流程.md similarity index 99% rename from docs/测试说明/ADC前端注入验证流程.md rename to docs/测试说明/专项验证/ADC前端注入验证流程.md index d4df1a18..0c0dc97a 100644 --- a/docs/测试说明/ADC前端注入验证流程.md +++ b/docs/测试说明/专项验证/ADC前端注入验证流程.md @@ -28,7 +28,7 @@ 2026-10-27 按 `docs/硬件平台/V0.1.tel` 逐通道追线,以 UA 为例(图由 `tools/arch_diagram/gen_adc_frontend_svg.py` 生成,改图请改脚本重跑,勿手改 SVG): -![UA 通道前端:端子 → R31 → ADC7 → TPAFE AIN_7P;C44 / R32 在差分负端,不在信号通路上](../images/ADC前端电路.svg) +![UA 通道前端:端子 → R31 → ADC7 → TPAFE AIN_7P;C44 / R32 在差分负端,不在信号通路上](../../images/ADC前端电路.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): -![两把刻度尺:TPAFE5160 16 位双极性 −32768~+32767、1 码 152.59 µV、11430 码≈1.744 V;STM32 ADC1 12 位单极性 0~4095、1 码 805.66 µV、1000 码≈0.806 V](../images/ADC码值刻度.svg) +![两把刻度尺:TPAFE5160 16 位双极性 −32768~+32767、1 码 152.59 µV、11430 码≈1.744 V;STM32 ADC1 12 位单极性 0~4095、1 码 805.66 µV、1000 码≈0.806 V](../../images/ADC码值刻度.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.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.BIN`)与脚本输出(`fft` / `shape` / `dump` 三份文本 + `plot` 的图)——定量档的证据本体是 diff --git a/docs/测试说明/启动日志原子性复验流程.md b/docs/测试说明/专项验证/启动日志原子性复验流程.md similarity index 94% rename from docs/测试说明/启动日志原子性复验流程.md rename to docs/测试说明/专项验证/启动日志原子性复验流程.md index 741deb40..da67b13e 100644 --- a/docs/测试说明/启动日志原子性复验流程.md +++ b/docs/测试说明/专项验证/启动日志原子性复验流程.md @@ -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` diff --git a/docs/测试说明/存储维护与容量恢复.md b/docs/测试说明/专项验证/存储维护与容量恢复.md similarity index 97% rename from docs/测试说明/存储维护与容量恢复.md rename to docs/测试说明/专项验证/存储维护与容量恢复.md index 6380bc8c..9cb8a4e1 100644 --- a/docs/测试说明/存储维护与容量恢复.md +++ b/docs/测试说明/专项验证/存储维护与容量恢复.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) diff --git a/docs/测试说明/模拟器差距清单.md b/docs/测试说明/专项验证/模拟器差距清单.md similarity index 99% rename from docs/测试说明/模拟器差距清单.md rename to docs/测试说明/专项验证/模拟器差距清单.md index eef10882..fa8c4a0d 100644 --- a/docs/测试说明/模拟器差距清单.md +++ b/docs/测试说明/专项验证/模拟器差距清单.md @@ -5,7 +5,7 @@ > **性质**:**登记册**(living document)。新增模拟器后端差异时必须在此登记一行,不得只写在别处。 > **上游依据**:`docs/网络/Net层阻塞模型架构设计.md` §10(net 层 pending 化现状)。 > **相关**:`UI设计/LVGL模拟器部署与使用说明.md`(部署与使用)、`simulator/README.md`(目录与架构)、 -> `测试说明/测试开发标准流程.md`(模拟器回归门禁在测试分层中的位置)。 +> `docs/测试说明/流程与规范/测试开发标准流程.md`(模拟器回归门禁在测试分层中的位置)。 --- diff --git a/docs/测试说明/链路延迟测试说明.md b/docs/测试说明/专项验证/链路延迟测试说明.md similarity index 93% rename from docs/测试说明/链路延迟测试说明.md rename to docs/测试说明/专项验证/链路延迟测试说明.md index b001ccea..080a28f0 100644 --- a/docs/测试说明/链路延迟测试说明.md +++ b/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` | diff --git a/docs/测试说明/ADC输入层单元测试说明.md b/docs/测试说明/单元测试/ADC输入层单元测试说明.md similarity index 96% rename from docs/测试说明/ADC输入层单元测试说明.md rename to docs/测试说明/单元测试/ADC输入层单元测试说明.md index f3522d23..af31bad8 100644 --- a/docs/测试说明/ADC输入层单元测试说明.md +++ b/docs/测试说明/单元测试/ADC输入层单元测试说明.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 运行方式 diff --git a/docs/测试说明/主机单测覆盖率口径.md b/docs/测试说明/单元测试/主机单测覆盖率口径.md similarity index 98% rename from docs/测试说明/主机单测覆盖率口径.md rename to docs/测试说明/单元测试/主机单测覆盖率口径.md index aaaa34af..18249476 100644 --- a/docs/测试说明/主机单测覆盖率口径.md +++ b/docs/测试说明/单元测试/主机单测覆盖率口径.md @@ -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` 的触发面 diff --git a/docs/测试说明/卷锁单元测试说明.md b/docs/测试说明/单元测试/卷锁单元测试说明.md similarity index 96% rename from docs/测试说明/卷锁单元测试说明.md rename to docs/测试说明/单元测试/卷锁单元测试说明.md index 2e6dddcf..f2bca839 100644 --- a/docs/测试说明/卷锁单元测试说明.md +++ b/docs/测试说明/单元测试/卷锁单元测试说明.md @@ -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 运行方式 diff --git a/docs/测试说明/开机账本单元测试说明.md b/docs/测试说明/单元测试/开机账本单元测试说明.md similarity index 95% rename from docs/测试说明/开机账本单元测试说明.md rename to docs/测试说明/单元测试/开机账本单元测试说明.md index 1b224231..6a75b0b7 100644 --- a/docs/测试说明/开机账本单元测试说明.md +++ b/docs/测试说明/单元测试/开机账本单元测试说明.md @@ -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 观测计数) --- diff --git a/docs/测试说明/时间同步单元测试说明.md b/docs/测试说明/单元测试/时间同步单元测试说明.md similarity index 95% rename from docs/测试说明/时间同步单元测试说明.md rename to docs/测试说明/单元测试/时间同步单元测试说明.md index 20099fad..9ed165c1 100644 --- a/docs/测试说明/时间同步单元测试说明.md +++ b/docs/测试说明/单元测试/时间同步单元测试说明.md @@ -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 运行方式 diff --git a/docs/测试说明/相量层单元测试说明.md b/docs/测试说明/单元测试/相量层单元测试说明.md similarity index 93% rename from docs/测试说明/相量层单元测试说明.md rename to docs/测试说明/单元测试/相量层单元测试说明.md index c5c3bbc8..56ec62f8 100644 --- a/docs/测试说明/相量层单元测试说明.md +++ b/docs/测试说明/单元测试/相量层单元测试说明.md @@ -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 运行方式 diff --git a/docs/测试说明/看门狗单元测试说明.md b/docs/测试说明/单元测试/看门狗单元测试说明.md similarity index 95% rename from docs/测试说明/看门狗单元测试说明.md rename to docs/测试说明/单元测试/看门狗单元测试说明.md index 15eb9a01..3adf036d 100644 --- a/docs/测试说明/看门狗单元测试说明.md +++ b/docs/测试说明/单元测试/看门狗单元测试说明.md @@ -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 运行方式 diff --git a/docs/测试说明/系统时钟单元测试说明.md b/docs/测试说明/单元测试/系统时钟单元测试说明.md similarity index 97% rename from docs/测试说明/系统时钟单元测试说明.md rename to docs/测试说明/单元测试/系统时钟单元测试说明.md index 1e04a82e..0c23222a 100644 --- a/docs/测试说明/系统时钟单元测试说明.md +++ b/docs/测试说明/单元测试/系统时钟单元测试说明.md @@ -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` 台架闭环确认。 diff --git a/docs/测试说明/配置文件单元测试说明.md b/docs/测试说明/单元测试/配置文件单元测试说明.md similarity index 97% rename from docs/测试说明/配置文件单元测试说明.md rename to docs/测试说明/单元测试/配置文件单元测试说明.md index c4652d7b..506e88cb 100644 --- a/docs/测试说明/配置文件单元测试说明.md +++ b/docs/测试说明/单元测试/配置文件单元测试说明.md @@ -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 运行方式 diff --git a/docs/测试说明/CH395F_Test_Guide.md b/docs/测试说明/板级测试/CH395F_Test_Guide.md similarity index 100% rename from docs/测试说明/CH395F_Test_Guide.md rename to docs/测试说明/板级测试/CH395F_Test_Guide.md diff --git a/docs/测试说明/FTP_Test_Guide.md b/docs/测试说明/板级测试/FTP_Test_Guide.md similarity index 97% rename from docs/测试说明/FTP_Test_Guide.md rename to docs/测试说明/板级测试/FTP_Test_Guide.md index a99618bc..dc2c882b 100644 --- a/docs/测试说明/FTP_Test_Guide.md +++ b/docs/测试说明/板级测试/FTP_Test_Guide.md @@ -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 用法 diff --git a/docs/测试说明/GD5F2GQ5UE_Test_Guide.md b/docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md similarity index 99% rename from docs/测试说明/GD5F2GQ5UE_Test_Guide.md rename to docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md index 7db9f11d..1f026a6f 100644 --- a/docs/测试说明/GD5F2GQ5UE_Test_Guide.md +++ b/docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md @@ -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`。 > diff --git a/docs/测试说明/SD2506_Test_Guide.md b/docs/测试说明/板级测试/SD2506_Test_Guide.md similarity index 100% rename from docs/测试说明/SD2506_Test_Guide.md rename to docs/测试说明/板级测试/SD2506_Test_Guide.md diff --git a/docs/测试说明/实机测试实施指南.md b/docs/测试说明/板级测试/实机测试实施指南.md similarity index 96% rename from docs/测试说明/实机测试实施指南.md rename to docs/测试说明/板级测试/实机测试实施指南.md index 68357540..c0bc5c07 100644 --- a/docs/测试说明/实机测试实施指南.md +++ b/docs/测试说明/板级测试/实机测试实施指南.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 ` ——自动列 `>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/` 寄存器时序 / 模拟器差距清单的硬件专属项 / 配置变更检测与回调 / 网络重建并发 / 启动段 / 内存预算, diff --git a/docs/测试说明/测试开发标准流程.md b/docs/测试说明/流程与规范/测试开发标准流程.md similarity index 93% rename from docs/测试说明/测试开发标准流程.md rename to docs/测试说明/流程与规范/测试开发标准流程.md index 51ad98f1..6d44c784 100644 --- a/docs/测试说明/测试开发标准流程.md +++ b/docs/测试说明/流程与规范/测试开发标准流程.md @@ -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` | 配置引擎解析/契约(主机侧纯逻辑单测) | diff --git a/docs/测试说明/测试文档模板规范.md b/docs/测试说明/流程与规范/测试文档模板规范.md similarity index 99% rename from docs/测试说明/测试文档模板规范.md rename to docs/测试说明/流程与规范/测试文档模板规范.md index 6a8e5587..2445e96b 100644 --- a/docs/测试说明/测试文档模板规范.md +++ b/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 文档维护(与代码同步) diff --git a/docs/测试说明/自动化测试流程.md b/docs/测试说明/流程与规范/自动化测试流程.md similarity index 98% rename from docs/测试说明/自动化测试流程.md rename to docs/测试说明/流程与规范/自动化测试流程.md index 9daca744..f9a14d00 100644 --- a/docs/测试说明/自动化测试流程.md +++ b/docs/测试说明/流程与规范/自动化测试流程.md @@ -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 ` 重烧并看 `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`),要设门禁再给预算 | diff --git a/docs/测试说明/ST-LINK_CLI_复位使用说明.md b/docs/测试说明/测试工具/ST-LINK_CLI_复位使用说明.md similarity index 100% rename from docs/测试说明/ST-LINK_CLI_复位使用说明.md rename to docs/测试说明/测试工具/ST-LINK_CLI_复位使用说明.md diff --git a/docs/测试说明/串口助手使用指南.md b/docs/测试说明/测试工具/串口助手使用指南.md similarity index 99% rename from docs/测试说明/串口助手使用指南.md rename to docs/测试说明/测试工具/串口助手使用指南.md index 6a483395..b2827da8 100644 --- a/docs/测试说明/串口助手使用指南.md +++ b/docs/测试说明/测试工具/串口助手使用指南.md @@ -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 释放/重开陷阱。 diff --git a/docs/测试说明/串口助手设计说明.md b/docs/测试说明/测试工具/串口助手设计说明.md similarity index 99% rename from docs/测试说明/串口助手设计说明.md rename to docs/测试说明/测试工具/串口助手设计说明.md index 2713e81d..66803407 100644 --- a/docs/测试说明/串口助手设计说明.md +++ b/docs/测试说明/测试工具/串口助手设计说明.md @@ -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 候选 diff --git a/docs/测试说明/boot_log_data/20261010_prod_adc_l1_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261010_prod_adc_l1_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261010_prod_adc_l1_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261010_prod_adc_l1_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261010_prod_adc_tim6_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261010_prod_adc_tim6_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261010_prod_adc_tim6_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261010_prod_adc_tim6_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261011_prod_adc_health_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261011_prod_adc_health_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261011_prod_adc_health_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261011_prod_adc_health_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261011_prod_phasor_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261011_prod_phasor_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261011_prod_phasor_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261011_prod_phasor_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261012_B6_iec104_roundtrip_log.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B6_iec104_roundtrip_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B6_iec104_roundtrip_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B6_iec104_roundtrip_log.txt diff --git a/docs/测试说明/boot_log_data/20261012_B6_iec104_roundtrip_pre-fix_log.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B6_iec104_roundtrip_pre-fix_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B6_iec104_roundtrip_pre-fix_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B6_iec104_roundtrip_pre-fix_log.txt diff --git a/docs/测试说明/boot_log_data/20261012_B6_prod_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B6_prod_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B6_prod_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B6_prod_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261012_B6_prod_boot_log_PROTECT_MISS.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B6_prod_boot_log_PROTECT_MISS.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B6_prod_boot_log_PROTECT_MISS.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B6_prod_boot_log_PROTECT_MISS.txt diff --git a/docs/测试说明/boot_log_data/20261012_B7_iec104_persist_log.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B7_iec104_persist_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B7_iec104_persist_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B7_iec104_persist_log.txt diff --git a/docs/测试说明/boot_log_data/20261012_B7_persist_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B7_persist_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B7_persist_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B7_persist_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261012_B9_iec104_soe_post_log.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B9_iec104_soe_post_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B9_iec104_soe_post_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B9_iec104_soe_post_log.txt diff --git a/docs/测试说明/boot_log_data/20261012_B9_iec104_soe_pre_log.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B9_iec104_soe_pre_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B9_iec104_soe_pre_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B9_iec104_soe_pre_log.txt diff --git a/docs/测试说明/boot_log_data/20261012_B9_prod_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B9_prod_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B9_prod_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B9_prod_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261012_B9_soe_decode_post.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B9_soe_decode_post.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B9_soe_decode_post.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B9_soe_decode_post.txt diff --git a/docs/测试说明/boot_log_data/20261012_B9_soe_decode_pre.txt b/docs/测试说明/测试数据/boot_log_data/20261012_B9_soe_decode_pre.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261012_B9_soe_decode_pre.txt rename to docs/测试说明/测试数据/boot_log_data/20261012_B9_soe_decode_pre.txt diff --git a/docs/测试说明/boot_log_data/20261021_probe_stale_gate_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261021_probe_stale_gate_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261021_probe_stale_gate_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261021_probe_stale_gate_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261025_uinav_blindwalk_cascade.png b/docs/测试说明/测试数据/boot_log_data/20261025_uinav_blindwalk_cascade.png similarity index 100% rename from docs/测试说明/boot_log_data/20261025_uinav_blindwalk_cascade.png rename to docs/测试说明/测试数据/boot_log_data/20261025_uinav_blindwalk_cascade.png diff --git a/docs/测试说明/boot_log_data/20261025_uinav_blindwalk_pwd512.png b/docs/测试说明/测试数据/boot_log_data/20261025_uinav_blindwalk_pwd512.png similarity index 100% rename from docs/测试说明/boot_log_data/20261025_uinav_blindwalk_pwd512.png rename to docs/测试说明/测试数据/boot_log_data/20261025_uinav_blindwalk_pwd512.png diff --git a/docs/测试说明/boot_log_data/20261025_uinav_popup_clipped.png b/docs/测试说明/测试数据/boot_log_data/20261025_uinav_popup_clipped.png similarity index 100% rename from docs/测试说明/boot_log_data/20261025_uinav_popup_clipped.png rename to docs/测试说明/测试数据/boot_log_data/20261025_uinav_popup_clipped.png diff --git a/docs/测试说明/boot_log_data/20261026_bench23_flash_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261026_bench23_flash_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261026_bench23_flash_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261026_bench23_flash_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261026_bench23_recheck_verdicts.txt b/docs/测试说明/测试数据/boot_log_data/20261026_bench23_recheck_verdicts.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261026_bench23_recheck_verdicts.txt rename to docs/测试说明/测试数据/boot_log_data/20261026_bench23_recheck_verdicts.txt diff --git a/docs/测试说明/boot_log_data/20261026_bench23_reset_only_boots_r1_r4.txt b/docs/测试说明/测试数据/boot_log_data/20261026_bench23_reset_only_boots_r1_r4.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261026_bench23_reset_only_boots_r1_r4.txt rename to docs/测试说明/测试数据/boot_log_data/20261026_bench23_reset_only_boots_r1_r4.txt diff --git a/docs/测试说明/boot_log_data/20261026_prod_77779d49_boot_log.txt b/docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_boot_log.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261026_prod_77779d49_boot_log.txt rename to docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_boot_log.txt diff --git a/docs/测试说明/boot_log_data/20261026_prod_77779d49_boot_log_reset_only.txt b/docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_boot_log_reset_only.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261026_prod_77779d49_boot_log_reset_only.txt rename to docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_boot_log_reset_only.txt diff --git a/docs/测试说明/boot_log_data/20261026_prod_77779d49_iec104_setpoint_leg.txt b/docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_iec104_setpoint_leg.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261026_prod_77779d49_iec104_setpoint_leg.txt rename to docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_iec104_setpoint_leg.txt diff --git a/docs/测试说明/boot_log_data/20261026_prod_77779d49_ui_nav_trace.json b/docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_ui_nav_trace.json similarity index 100% rename from docs/测试说明/boot_log_data/20261026_prod_77779d49_ui_nav_trace.json rename to docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_ui_nav_trace.json diff --git a/docs/测试说明/boot_log_data/20261026_prod_77779d49_ui_set_badge_uncal.png b/docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_ui_set_badge_uncal.png similarity index 100% rename from docs/测试说明/boot_log_data/20261026_prod_77779d49_ui_set_badge_uncal.png rename to docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_ui_set_badge_uncal.png diff --git a/docs/测试说明/boot_log_data/20261026_prod_77779d49_ui_set_edit_enter_accepted.png b/docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_ui_set_edit_enter_accepted.png similarity index 100% rename from docs/测试说明/boot_log_data/20261026_prod_77779d49_ui_set_edit_enter_accepted.png rename to docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_ui_set_edit_enter_accepted.png diff --git a/docs/测试说明/boot_log_data/20261026_prod_77779d49_ui_set_view_readonly.png b/docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_ui_set_view_readonly.png similarity index 100% rename from docs/测试说明/boot_log_data/20261026_prod_77779d49_ui_set_view_readonly.png rename to docs/测试说明/测试数据/boot_log_data/20261026_prod_77779d49_ui_set_view_readonly.png diff --git a/docs/测试说明/boot_log_data/20261026_prod_console_interleave_evidence.txt b/docs/测试说明/测试数据/boot_log_data/20261026_prod_console_interleave_evidence.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261026_prod_console_interleave_evidence.txt rename to docs/测试说明/测试数据/boot_log_data/20261026_prod_console_interleave_evidence.txt diff --git a/docs/测试说明/boot_log_data/20261026_task24_boardnav_standby_unknown.png b/docs/测试说明/测试数据/boot_log_data/20261026_task24_boardnav_standby_unknown.png similarity index 100% rename from docs/测试说明/boot_log_data/20261026_task24_boardnav_standby_unknown.png rename to docs/测试说明/测试数据/boot_log_data/20261026_task24_boardnav_standby_unknown.png diff --git a/docs/测试说明/boot_log_data/20261026_task24_boardnav_trace.json b/docs/测试说明/测试数据/boot_log_data/20261026_task24_boardnav_trace.json similarity index 100% rename from docs/测试说明/boot_log_data/20261026_task24_boardnav_trace.json rename to docs/测试说明/测试数据/boot_log_data/20261026_task24_boardnav_trace.json diff --git a/docs/测试说明/boot_log_data/20261026_task24_boardnav_view_set.png b/docs/测试说明/测试数据/boot_log_data/20261026_task24_boardnav_view_set.png similarity index 100% rename from docs/测试说明/boot_log_data/20261026_task24_boardnav_view_set.png rename to docs/测试说明/测试数据/boot_log_data/20261026_task24_boardnav_view_set.png diff --git a/docs/测试说明/boot_log_data/20261027_bench42_reset_only_boots_r1_r4.txt b/docs/测试说明/测试数据/boot_log_data/20261027_bench42_reset_only_boots_r1_r4.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261027_bench42_reset_only_boots_r1_r4.txt rename to docs/测试说明/测试数据/boot_log_data/20261027_bench42_reset_only_boots_r1_r4.txt diff --git a/docs/测试说明/boot_log_data/20261027_bench42_ui_clock_page.png b/docs/测试说明/测试数据/boot_log_data/20261027_bench42_ui_clock_page.png similarity index 100% rename from docs/测试说明/boot_log_data/20261027_bench42_ui_clock_page.png rename to docs/测试说明/测试数据/boot_log_data/20261027_bench42_ui_clock_page.png diff --git a/docs/测试说明/boot_log_data/20261027_bench42_verdicts.txt b/docs/测试说明/测试数据/boot_log_data/20261027_bench42_verdicts.txt similarity index 100% rename from docs/测试说明/boot_log_data/20261027_bench42_verdicts.txt rename to docs/测试说明/测试数据/boot_log_data/20261027_bench42_verdicts.txt diff --git a/docs/测试说明/boot_log_data/README.md b/docs/测试说明/测试数据/boot_log_data/README.md similarity index 96% rename from docs/测试说明/boot_log_data/README.md rename to docs/测试说明/测试数据/boot_log_data/README.md index 3935bce2..35c811c2 100644 --- a/docs/测试说明/boot_log_data/README.md +++ b/docs/测试说明/测试数据/boot_log_data/README.md @@ -46,8 +46,8 @@ 落库动作由提交车道执行(本卡不碰 git): ```powershell -git add -f docs/测试说明/boot_log_data/20261012_B9_soe_pre.bin -git add -f docs/测试说明/boot_log_data/20261012_B9_soe_after_post.bin +git add -f docs/测试说明/测试数据/boot_log_data/20261012_B9_soe_pre.bin +git add -f docs/测试说明/测试数据/boot_log_data/20261012_B9_soe_after_post.bin ``` > ⚠ 同目录另有 **3 个同状态的本机 `.bin`** 目前**没有**被任何台账行引用,故本卡不代其决定,只登记防复发: @@ -80,11 +80,11 @@ git add -f docs/测试说明/boot_log_data/20261012_B9_soe_after_post.bin > f3rounds 两只是**判读证据存档**(非 `[STACK]` 水位快照):源为 serial-assistant live 日志的 > 字节偏移切片(不 clear、行边界对齐),gz 前置 ASCII 头行携带偏移窗、负载定义与 v1.1 判据 -> 结论;判据口径 = `../实机测试实施指南.md` §7.2(v1.1),工具 = `scripts/v5_log_gap_report.py`。 +> 结论;判据口径 = `../../板级测试/实机测试实施指南.md` §7.2(v1.1),工具 = `scripts/v5_log_gap_report.py`。 ## 4. 关联 -- 沉淀约定:`../测试开发标准流程.md` §7.3 -- 栈水位探针与基线:`../../内存管理/RAM使用分析与优化方案.md` §4.0.2 / §4.0.6 -- 当前诊断基线:`../../内存管理/RAM预算台账.md` -- 本流程立项:原 `../../任务规划/README.md` 的「启动日志固化流程」条目(2026-09-22 提出;2026-10-05 固化为本节流程后销项) +- 沉淀约定:`../../流程与规范/测试开发标准流程.md` §7.3 +- 栈水位探针与基线:`../../../内存管理/RAM使用分析与优化方案.md` §4.0.2 / §4.0.6 +- 当前诊断基线:`../../../内存管理/RAM预算台账.md` +- 本流程立项:原 `../../../任务规划/README.md` 的「启动日志固化流程」条目(2026-09-22 提出;2026-10-05 固化为本节流程后销项) diff --git a/docs/测试说明/boot_log_data/f3rounds_r1_7003_churn_30min.log.gz b/docs/测试说明/测试数据/boot_log_data/f3rounds_r1_7003_churn_30min.log.gz similarity index 100% rename from docs/测试说明/boot_log_data/f3rounds_r1_7003_churn_30min.log.gz rename to docs/测试说明/测试数据/boot_log_data/f3rounds_r1_7003_churn_30min.log.gz diff --git a/docs/测试说明/boot_log_data/f3rounds_r2_probe_30min.log.gz b/docs/测试说明/测试数据/boot_log_data/f3rounds_r2_probe_30min.log.gz similarity index 100% rename from docs/测试说明/boot_log_data/f3rounds_r2_probe_30min.log.gz rename to docs/测试说明/测试数据/boot_log_data/f3rounds_r2_probe_30min.log.gz diff --git a/docs/测试说明/m2_data/README.md b/docs/测试说明/测试数据/m2_data/README.md similarity index 95% rename from docs/测试说明/m2_data/README.md rename to docs/测试说明/测试数据/m2_data/README.md index 83279698..2040cbfc 100644 --- a/docs/测试说明/m2_data/README.md +++ b/docs/测试说明/测试数据/m2_data/README.md @@ -1,7 +1,7 @@ # M2 链路延迟实测数据(Phase 13,安静档) 本目录保存 M2(Phase 13:芯片 + 队列时延基线)的**原始实测产物**。判定阈值与解读见 -[`../链路延迟测试说明.md`](../链路延迟测试说明.md) §6.2;缺陷总表见 `docs/测试说明/链路延迟测试说明.md` §8。 +[`../../专项验证/链路延迟测试说明.md`](../../专项验证/链路延迟测试说明.md) §6.2;缺陷总表见 `docs/测试说明/专项验证/链路延迟测试说明.md` §8。 ## 1. 运行元数据 @@ -22,7 +22,7 @@ & '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py & '.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_runNN.json" --wait 170 # 后台作业 + --json "docs\测试说明\测试数据\m2_data\m2_quiet_runNN.json" --wait 170 # 后台作业 & '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash & '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py wait-idle ` --timeout 120 --settle-ms 10000 --max-ms 110000 @@ -115,6 +115,6 @@ frame#10:first=16.522ms batches=[1024,1024,1024,137] tail_lag=+55.7ms ## 7. 未纳入本目录的数据 -- run1~run11 为缺陷定位过程(D11~D16 见 `docs/测试说明/链路延迟测试说明.md` §6.1),其中 run10/run11 的 L7 失败、 +- run1~run11 为缺陷定位过程(D11~D16 见 `docs/测试说明/专项验证/链路延迟测试说明.md` §6.1),其中 run10/run11 的 L7 失败、 run9 的 170s 连接拒绝均已定位并修复; - 压力档(`--ftp-stress` 复现)与 `--mode remo`(生产 RemoDispBus 客户端)属 M3。 diff --git a/docs/测试说明/m2_data/m2_quiet.json b/docs/测试说明/测试数据/m2_data/m2_quiet.json similarity index 100% rename from docs/测试说明/m2_data/m2_quiet.json rename to docs/测试说明/测试数据/m2_data/m2_quiet.json diff --git a/docs/测试说明/m2_data/m2_quiet_r200.json b/docs/测试说明/测试数据/m2_data/m2_quiet_r200.json similarity index 100% rename from docs/测试说明/m2_data/m2_quiet_r200.json rename to docs/测试说明/测试数据/m2_data/m2_quiet_r200.json diff --git a/docs/测试说明/m2_data/m2_quiet_r500.json b/docs/测试说明/测试数据/m2_data/m2_quiet_r500.json similarity index 100% rename from docs/测试说明/m2_data/m2_quiet_r500.json rename to docs/测试说明/测试数据/m2_data/m2_quiet_r500.json diff --git a/docs/测试说明/m2_data/m2_quiet_run13.json b/docs/测试说明/测试数据/m2_data/m2_quiet_run13.json similarity index 100% rename from docs/测试说明/m2_data/m2_quiet_run13.json rename to docs/测试说明/测试数据/m2_data/m2_quiet_run13.json diff --git a/docs/测试说明/m2_data/m2_quiet_run14.json b/docs/测试说明/测试数据/m2_data/m2_quiet_run14.json similarity index 100% rename from docs/测试说明/m2_data/m2_quiet_run14.json rename to docs/测试说明/测试数据/m2_data/m2_quiet_run14.json diff --git a/docs/测试说明/m2_data/m2_serial_excerpt_run13.txt b/docs/测试说明/测试数据/m2_data/m2_serial_excerpt_run13.txt similarity index 100% rename from docs/测试说明/m2_data/m2_serial_excerpt_run13.txt rename to docs/测试说明/测试数据/m2_data/m2_serial_excerpt_run13.txt diff --git a/docs/测试说明/m2_data/m2_serial_excerpt_run15.txt b/docs/测试说明/测试数据/m2_data/m2_serial_excerpt_run15.txt similarity index 100% rename from docs/测试说明/m2_data/m2_serial_excerpt_run15.txt rename to docs/测试说明/测试数据/m2_data/m2_serial_excerpt_run15.txt diff --git a/docs/测试说明/m3_data/m3_dev_quiet.json b/docs/测试说明/测试数据/m3_data/m3_dev_quiet.json similarity index 100% rename from docs/测试说明/m3_data/m3_dev_quiet.json rename to docs/测试说明/测试数据/m3_data/m3_dev_quiet.json diff --git a/docs/测试说明/m3_data/m3_dev_quiet_fixed.json b/docs/测试说明/测试数据/m3_data/m3_dev_quiet_fixed.json similarity index 100% rename from docs/测试说明/m3_data/m3_dev_quiet_fixed.json rename to docs/测试说明/测试数据/m3_data/m3_dev_quiet_fixed.json diff --git a/docs/测试说明/m3_data/m3_dev_quiet_r200.json b/docs/测试说明/测试数据/m3_data/m3_dev_quiet_r200.json similarity index 100% rename from docs/测试说明/m3_data/m3_dev_quiet_r200.json rename to docs/测试说明/测试数据/m3_data/m3_dev_quiet_r200.json diff --git a/docs/测试说明/m3_data/m3_dev_stress.json b/docs/测试说明/测试数据/m3_data/m3_dev_stress.json similarity index 100% rename from docs/测试说明/m3_data/m3_dev_stress.json rename to docs/测试说明/测试数据/m3_data/m3_dev_stress.json diff --git a/docs/测试说明/m3_data/m3_dev_stress_fixed.json b/docs/测试说明/测试数据/m3_data/m3_dev_stress_fixed.json similarity index 100% rename from docs/测试说明/m3_data/m3_dev_stress_fixed.json rename to docs/测试说明/测试数据/m3_data/m3_dev_stress_fixed.json diff --git a/docs/测试说明/m3_data/m3_dev_stress_r200.json b/docs/测试说明/测试数据/m3_data/m3_dev_stress_r200.json similarity index 100% rename from docs/测试说明/m3_data/m3_dev_stress_r200.json rename to docs/测试说明/测试数据/m3_data/m3_dev_stress_r200.json diff --git a/docs/测试说明/m3_data/m3_pending_quiet.json b/docs/测试说明/测试数据/m3_data/m3_pending_quiet.json similarity index 100% rename from docs/测试说明/m3_data/m3_pending_quiet.json rename to docs/测试说明/测试数据/m3_data/m3_pending_quiet.json diff --git a/docs/测试说明/m3_data/m3_pending_stress.json b/docs/测试说明/测试数据/m3_data/m3_pending_stress.json similarity index 100% rename from docs/测试说明/m3_data/m3_pending_stress.json rename to docs/测试说明/测试数据/m3_data/m3_pending_stress.json diff --git a/docs/测试说明/m3_data/m3_sim_quiet.json b/docs/测试说明/测试数据/m3_data/m3_sim_quiet.json similarity index 100% rename from docs/测试说明/m3_data/m3_sim_quiet.json rename to docs/测试说明/测试数据/m3_data/m3_sim_quiet.json diff --git a/docs/测试说明/m3_data/m3_tail_ackfast.json b/docs/测试说明/测试数据/m3_data/m3_tail_ackfast.json similarity index 100% rename from docs/测试说明/m3_data/m3_tail_ackfast.json rename to docs/测试说明/测试数据/m3_data/m3_tail_ackfast.json diff --git a/docs/测试说明/m3_data/m3_tail_ackprobe.json b/docs/测试说明/测试数据/m3_data/m3_tail_ackprobe.json similarity index 100% rename from docs/测试说明/m3_data/m3_tail_ackprobe.json rename to docs/测试说明/测试数据/m3_data/m3_tail_ackprobe.json diff --git a/docs/环境与部署/并行任务工作树方案.md b/docs/环境与部署/并行任务工作树方案.md index 66c3beb0..ba81f508 100644 --- a/docs/环境与部署/并行任务工作树方案.md +++ b/docs/环境与部署/并行任务工作树方案.md @@ -226,7 +226,7 @@ D:/Code/DTU Code/ `done` 前置检查:**陈旧锁自动接管释放**(不再硬失败),仅当锁仍被有效占用时才拒绝回收。 > ⚠ 台架相关的既有陷阱(`--require-selftest-pass` 的陈旧台账、回读校验会复位目标) -> 不因引入工作树而改变,仍按 `docs/测试说明/自动化测试流程.md` 执行。 +> 不因引入工作树而改变,仍按 `docs/测试说明/流程与规范/自动化测试流程.md` 执行。 ### 7.2 构建 @@ -436,7 +436,7 @@ docs\内存管理\RAM使用分析与优化方案.md:585 [路径引用] docs/内 | 主题 | 去处 | |---|---| | 提交门禁钩子逐项详解 | `docs/代码规范/pre-commit使用说明.md` | -| 自动化测试与台架流程 | `docs/测试说明/自动化测试流程.md` | +| 自动化测试与台架流程 | `docs/测试说明/流程与规范/自动化测试流程.md` | | 文档写作规范(编码/链接/登记) | `docs/文档规范.md` | | 工具路径环境变量(换机) | `docs/环境与部署/本地工具路径环境变量方案.md` | | 待办与排序登记簿 | `docs/任务规划/README.md` | diff --git a/docs/环境与部署/项目部署环境要求.md b/docs/环境与部署/项目部署环境要求.md index affbffa5..fb81d96e 100644 --- a/docs/环境与部署/项目部署环境要求.md +++ b/docs/环境与部署/项目部署环境要求.md @@ -129,7 +129,7 @@ Graphviz / Cppcheck 的安装位置差异一律用 `DTU_*` 环境变量表达( > ⚠ 本节涵盖**两类都要 MSVC 的 PC 侧构建**:① LVGL 模拟器(C++,产物 `lvgl_sim.exe`); > ② 主机侧单元测试(C,批量离线编译**真实生产源码**,见 §2.10 与 -> `docs/测试说明/看门狗单元测试说明.md`)。两者共用同一套 VS 安装,**无需装两次**。 +> `docs/测试说明/单元测试/看门狗单元测试说明.md`)。两者共用同一套 VS 安装,**无需装两次**。 | 项 | 要求 | 说明 | |---|---|---| @@ -192,7 +192,7 @@ python tools/font_gen/extract_cn.py # 任意 python3: | 一键测试 | `.dsh/skills/serial-boot-test/scripts/run_boot_test.py`(即 `@test`,`& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py`) | 开串口 + 清日志 → 烧录 → wait-idle(静默 8s/超时 30s)→ 提取 → 标记校验;默认端口取 `.serialtest/config.json` / 115200,退出码 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法错误 | > 采集 = 端口常开 + daemon 全量日志(`.dsh/skills/serial-assistant/scripts/state/serial.log`),无采集窗口/first-byte/EOF 重试仪式。 -> 命令契约与陷阱见 `docs/测试说明/串口助手设计说明.md`、`docs/测试说明/自动化测试流程.md`。 +> 命令契约与陷阱见 `docs/测试说明/测试工具/串口助手设计说明.md`、`docs/测试说明/流程与规范/自动化测试流程.md`。 ### 2.7 代码审查钩子(pre-commit) @@ -415,7 +415,7 @@ pre-commit run --all-files # 提交期 47 根(manual 三根另跑:- ### 2.11 CI runner 环境(Gitea Actions,2026-10-01 起) CI 跑 **静态门禁 + 主机侧纯逻辑单测**(**不含板端测试套件 / 主机侧回归 / 人工目检**——需真机 + ST-LINK,只在本地)。 -workflow 见 `.gitea/workflows/ci.yml`;覆盖边界与判定细节见 [`../测试说明/测试开发标准流程.md`](../测试说明/测试开发标准流程.md) §9。 +workflow 见 `.gitea/workflows/ci.yml`;覆盖边界与判定细节见 [`../测试说明/流程与规范/测试开发标准流程.md`](../测试说明/流程与规范/测试开发标准流程.md) §9。 | 项 | 要求 | 说明 | |---|---|---| @@ -643,10 +643,10 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级 | 网口配置 / 生效链路 | `docs/子系统设计/网络配置说明.md` | | 远程显示协议 | `docs/UI设计/RemoDispBus协议与接收设计说明.md` | | LVGL 模拟器部署 | `docs/UI设计/LVGL模拟器部署与使用说明.md`、`simulator/README.md` | -| 串口调试 / 自动化测试 | `docs/测试说明/串口助手使用指南.md`、`docs/测试说明/串口助手设计说明.md`、`docs/测试说明/自动化测试流程.md` | -| **测试分层 / 主机侧纯逻辑单测** | `docs/测试说明/测试开发标准流程.md`(分层与门禁)· `docs/测试说明/看门狗单元测试说明.md`(主机侧纯逻辑单测范式:MSVC 离线编译 + 平台桩) | -| **CI(Gitea Actions)** | `docs/CI/README.md`(**远程 CI 唯一入口**:服务端 / Runner 部署与保活 / workflow / 排障,**仅本机一台 runner,日常开发不必读**)· `docs/测试说明/测试开发标准流程.md` §9(覆盖边界) | +| 串口调试 / 自动化测试 | `docs/测试说明/测试工具/串口助手使用指南.md`、`docs/测试说明/测试工具/串口助手设计说明.md`、`docs/测试说明/流程与规范/自动化测试流程.md` | +| **测试分层 / 主机侧纯逻辑单测** | `docs/测试说明/流程与规范/测试开发标准流程.md`(分层与门禁)· `docs/测试说明/单元测试/看门狗单元测试说明.md`(主机侧纯逻辑单测范式:MSVC 离线编译 + 平台桩) | +| **CI(Gitea Actions)** | `docs/CI/README.md`(**远程 CI 唯一入口**:服务端 / Runner 部署与保活 / workflow / 排障,**仅本机一台 runner,日常开发不必读**)· `docs/测试说明/流程与规范/测试开发标准流程.md` §9(覆盖边界) | | pre-commit / cppcheck | `docs/代码规范/pre-commit使用说明.md`、`docs/代码规范/cppcheck使用说明.md` | | 引用关系图(文件引用) | `docs/架构设计/引用关系图说明.md`(生成工具 `tools/refgraph`;渲染依赖 Graphviz,§2.8) | -| 各模块测试指南 | `docs/测试说明/CH395F_Test_Guide.md`、`GD5F2GQ5UE_Test_Guide.md`、`SD2506_Test_Guide.md`、`FTP_Test_Guide.md` | +| 各模块测试指南 | `docs/测试说明/板级测试/CH395F_Test_Guide.md`、`GD5F2GQ5UE_Test_Guide.md`、`SD2506_Test_Guide.md`、`FTP_Test_Guide.md` | | 已知硬件陷阱 | `docs/问题记录/CH395F_Trap_Records.md` 等 | diff --git a/docs/硬件平台/ADC通道映射说明.md b/docs/硬件平台/ADC通道映射说明.md index a1f48abe..580c3c74 100644 --- a/docs/硬件平台/ADC通道映射说明.md +++ b/docs/硬件平台/ADC通道映射说明.md @@ -195,7 +195,7 @@ STM32(U17)为 LQFP144 脚号。 ### 8.1 2026-10-27 实测记录(首次执行,六项判据全 PASS) -**注入点在端子侧**(`U5.x` 连接器焊盘,见 `docs/测试说明/ADC前端注入验证流程.md` §3), +**注入点在端子侧**(`U5.x` 连接器焊盘,见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §3), 未碰 LQFP 引脚——有 1k 串阻护着,且 ③ 段已定 1:1,端子侧斜率即引脚侧斜率。 完整步骤、现场记录表与逐项判据见该文档 §5/§6,此处只留结论。 diff --git a/docs/算法/继电保护功能复现规划.md b/docs/算法/继电保护功能复现规划.md index 953700e5..a8472c52 100644 --- a/docs/算法/继电保护功能复现规划.md +++ b/docs/算法/继电保护功能复现规划.md @@ -238,15 +238,15 @@ | 功能名 | 关键参数 | 完成判据 | 状态 | | --- | --- | --- | --- | -| 周期 CONVST 重触发 | 1000 Hz(与保护节拍同源) | 示波器见 U3 `BUSY` 连续脉冲;`tpafe5160_frame_seq()` 持续递增 | ✅ 2026-10-10:**TIM3 更新事件(1 kHz)硬件触发**(ISR 内 `tpafe5160_start_conv_irq()`;方案 A,零引脚/零驱动改动。⚠ 节拍源**不能**是 TIM6/TIM7——F4 上 ADC1 收不到它们的 TRGO,见 `docs/子系统设计/ADC采样节拍设计说明.md` §3.2);台架 `@test` PASS——`seq` 每 10 s 精确 +10000 = 1000.0 Hz、`frst_err=0`(早期证据 `boot_log_data/20261010_prod_adc_tim6_boot_log.txt`,节拍源当时为 TIM6) | +| 周期 CONVST 重触发 | 1000 Hz(与保护节拍同源) | 示波器见 U3 `BUSY` 连续脉冲;`tpafe5160_frame_seq()` 持续递增 | ✅ 2026-10-10:**TIM3 更新事件(1 kHz)硬件触发**(ISR 内 `tpafe5160_start_conv_irq()`;方案 A,零引脚/零驱动改动。⚠ 节拍源**不能**是 TIM6/TIM7——F4 上 ADC1 收不到它们的 TRGO,见 `docs/子系统设计/ADC采样节拍设计说明.md` §3.2);台架 `@test` PASS——`seq` 每 10 s 精确 +10000 = 1000.0 Hz、`frst_err=0`(早期证据 `docs/测试说明/测试数据/boot_log_data/20261010_prod_adc_tim6_boot_log.txt`,节拍源当时为 TIM6) | | TPAFE 快照消费 | 8 通道 / 帧 | `adc_task` 每拍调 `tpafe5160_snapshot()`,返回 1/0/-1 有处理 | ✅ B1 已实现并 `@test` 闭环(`adc_task.c`;台架 `idle=0`、`frst_err=0`) | | STM32 ADC1 启动与扫描 | 9 通道、144 cycles、**TIM3 TRGO 硬件触发 + DMA** | 全库出现 `HAL_ADC_Start_DMA`;9 通道码值随注入变化 | ✅ 2026-10-10(v2.0):`App/algo/adc_input.c` 的 `stm32_take()`——ADC1 由 TIM3 更新事件经 TRGO 触发一轮 9 通道,`HAL_ADC_Start_DMA(&hadc1, buf, 18)` + DMA2_Stream4 循环模式把码值自动搬进**乒乓双缓冲**,任务侧只消费刚完成的半区(**零忙等**,实测单拍 `adcp` 122 µs → **8 µs**);台架 `@test` PASS——`adc1_seq` 每拍 +1、`adc1_err=0`、`adc1_hw=0`。⚠ 「9 通道码值随注入变化」已由 2026-10-27 台架已知电压注入直接证实(六项判据全 PASS,实测记录 `docs/硬件平台/ADC通道映射说明.md` §8.1);两点标定与端子/子板变比确认仍待做 | | 通道语义映射 | 见 `docs/硬件平台/ADC通道映射说明.md`(**按语义取数,不写死下标**) | `UA→buf[6]`、`UN→buf[5]`、`IA→buf[2]`;STM32 侧 `UB→ADC_CHANNEL_14` | ✅ 2026-10-10:`App/algo/adc_input.c` 的 `k_adc_map[]` 语义表(`UA/UN/IA`→TPAFE `buf[6]/[5]/[2]`,`UB/UC/IB/IC/IN/TEMP`→ADC1 `CH14/3/6/1/2/5`)+ `adc_input_raw()` 按语义取数;开机**映射自检**(`adc_input_init()` 校验 STM32 映射通道必落在扫描序列内 → 挡住"映射到不扫描的通道"静默错)通过(`ADC input layer init: OK`)。台架首帧日志 8 路 + 温度全部读出:`UA=11429 UN=11454 IA=11452`(与 TIM3 轮次一致)、`UB=1018 UC=1044 IB=943 IC=1069 IN=1052 T=850`(互异、非饱和;**两次开机读数不同** → 确为实时转换而非常量) | | 通道标定(一次系数 + 零漂) | 每通道 `k`、`b`;系数定点 `2^10` | 注入标准源,读数误差 ≤ 目标精度 | ⬜ | -| 采样有效性校验 | FRSTDATA 跳变、帧序号单调、丢帧计数 | 芯片静默/丢帧被检出并置告警 | ✅ 2026-10-11:新增 `App/algo/adc_health.c/h`(纯逻辑判定层:静默 100 ms 门限 / 丢帧边沿 / 序号倒退锁存 / FRSTDATA·HAL 错误·STM32 停摆计数增量)+ `adc_task.c` 告警编排(严重事件与故障上升沿 `DBG_ERROR` + 每类每次开机一次 `SYSLOG_SELFTEST`,恢复 `DBG_INFO`;gap 不告警只计数,心跳增 `tgap`);主机单测 `test/host/adc_health/` **31 用例全绿**(`adc-health-unit-test` 钩子);台架 `@test` PASS 零 `[ERR]`(健康不误报,`boot_log_data/20261011_prod_adc_health_boot_log.txt`)。⚠ 抬栈:判定链 `adc_health_report`→`syslog_post` 回显尾使 adcTask 静态最坏链 832→**1080 B** → 栈 512→**640 words**(余 1480 B / 57%) | +| 采样有效性校验 | FRSTDATA 跳变、帧序号单调、丢帧计数 | 芯片静默/丢帧被检出并置告警 | ✅ 2026-10-11:新增 `App/algo/adc_health.c/h`(纯逻辑判定层:静默 100 ms 门限 / 丢帧边沿 / 序号倒退锁存 / FRSTDATA·HAL 错误·STM32 停摆计数增量)+ `adc_task.c` 告警编排(严重事件与故障上升沿 `DBG_ERROR` + 每类每次开机一次 `SYSLOG_SELFTEST`,恢复 `DBG_INFO`;gap 不告警只计数,心跳增 `tgap`);主机单测 `test/host/adc_health/` **31 用例全绿**(`adc-health-unit-test` 钩子);台架 `@test` PASS 零 `[ERR]`(健康不误报,`docs/测试说明/测试数据/boot_log_data/20261011_prod_adc_health_boot_log.txt`)。⚠ 抬栈:判定链 `adc_health_report`→`syslog_post` 回显尾使 adcTask 静态最坏链 832→**1080 B** → 栈 512→**640 words**(余 1480 B / 57%) | | 等周波采样(软件测频 + 调频闭环) | 20 点/周波;测频范围建议 **45~55 Hz**(参考 40.5~60.5) | 频率偏移 ±2 Hz 时幅值误差 ≤ 1% | ⬜ | | 零序通道接入(外部专用 / 自产切换) | 外部 `UN`/`IN`;自产 `3I0 = Ia+Ib+Ic`(V0.2 起) | 零序通道可切换来源,值正确 | ⬜ | -| 二次谐波/五次谐波提取入口 | k=2(涌流)、k=5(选线) | 相量层可产出对应谐波相量 | ✅ 2026-10-11:`phasor.c` 实例表 `C04-IA-F2`(k=2)/ `C05-IA-F5`(k=5)随每拍重算产出,台架心跳日志 `phasor(hb) C04/C05` 行可见(`boot_log_data/20261011_prod_phasor_boot_log.txt`);谐波**抑制/提取正确性**已由主机单测覆盖(`test/host/phasor/`) | +| 二次谐波/五次谐波提取入口 | k=2(涌流)、k=5(选线) | 相量层可产出对应谐波相量 | ✅ 2026-10-11:`phasor.c` 实例表 `C04-IA-F2`(k=2)/ `C05-IA-F5`(k=5)随每拍重算产出,台架心跳日志 `phasor(hb) C04/C05` 行可见(`docs/测试说明/测试数据/boot_log_data/20261011_prod_phasor_boot_log.txt`);谐波**抑制/提取正确性**已由主机单测覆盖(`test/host/phasor/`) | > ⚠️ **「双转换器无共同采样触发」约束**:「通道语义映射」中 `UA/UN/IA` 在 TPAFE、`UB/UC/IB/IC/IN` 在 STM32 ADC。V0.1 上 语义取数与有效性只做**逐通道独立监视**,不得假设同族量同刻(`UA` 与 `UB` 无共同采样触发)。 @@ -255,7 +255,7 @@ | 功能名 | 关键参数 | 完成判据 | 状态 | | --- | --- | --- | --- | | 全周傅氏系数表 | `sin(2πk/N)·(√2/N)`、`cos(2πk/N)·(√2/N)`,N=20 | 系数表与 `docs/算法/傅氏算法详解.md` §2.3 一致 | ✅ 2026-10-11:`phasor.c` 离线系数表**预乘 √2/N**;主机单测逐项复核(`test/host/phasor/` 系数表用例) | -| 基波相量实例 | **5 个实例**(参考项目 4 个,见下方注):`C01-IA-F1` / `C02-UA-F1` / `C03-UN-F1` / `C04-IA-F2` / `C05-IA-F5` | 每实例输出 `{fRe, fIm, fAm, fAmSQ}` | ✅ 2026-10-11:`k_inst[]` 数据驱动 5 实例;台架开机即产出 `phasor(first)` 5 行(`boot_log_data/20261011_prod_phasor_boot_log.txt`) | +| 基波相量实例 | **5 个实例**(参考项目 4 个,见下方注):`C01-IA-F1` / `C02-UA-F1` / `C03-UN-F1` / `C04-IA-F2` / `C05-IA-F5` | 每实例输出 `{fRe, fIm, fAm, fAmSQ}` | ✅ 2026-10-11:`k_inst[]` 数据驱动 5 实例;台架开机即产出 `phasor(first)` 5 行(`docs/测试说明/测试数据/boot_log_data/20261011_prod_phasor_boot_log.txt`) | | 相量有效值输出 | `fAmSQ = √(fRe²+fIm²)` 直接为**有效值**(系数已折算) | 标准源读数 = 设定有效值 | ✅ 2026-10-11(链路级):`fAmSQ` 口径实现 + 单测合成正弦幅值误差 ≤1%;**"标准源读数"判据在无信号源台架不可达**(同 §7.1),待「通道标定(一次系数 + 零漂)」标定后复核 | | 相位输出 | `φ = atan2(fIm, fRe)` | 相位误差 ≤ 目标值 | ✅ 2026-10-11(链路级):`fRe/fIm` 常驻双区、每拍产出,φ 由消费侧 `atan2f` 现算(不常驻结构体,见 `docs/算法/采集与算法层设计说明.md` §6);单测覆盖相位;**目标值待产品定义 + 标准源复核** | | 线/负序/零序合成 | 线电压 `Uab=Ua−Ub` 等;负序 `3U2`/`3I2`;零序 `3U0`/`3I0` | 合成相量可复用于保护元件(**V0.1 仅同转换器内可合成**,见 §1.6) | ⬜ **V0.1 不适用**:跨转换器合成被「双转换器无共同采样触发」禁止;零序走**外部专用通道** `UN`/`IN`(§6.4),无需自产 → 随 V0.2 启用 | @@ -265,9 +265,9 @@ > **双轨有效值**:保护要"基波有效值 + 相位"(抗衰减直流、抗谐波误动);计量/遥测要"真有效值"(谐波方和根)。两者**不可混用**——这是参考系统 `CN_ANA_VEC_SQRT=FALSE` 与遥测谐波轨并存的根本原因。 -> **「基波相量实例」实例数 4 → 5 的来历**:参考项目(`APP/CLS100_Dsp/InstCalCell.c`)为 **4 个实例**——C01 基波 I/U、C02 零序基波、C03 二次谐波、C04 五次谐波。本项目按 V0.1 **有效通道**(`UA`/`UN`/`IA`,见 §1.6:`UB/UC/IB/IC/IN` 无中点偏置 → 削顶不可用)展开:C01 的"I/U"拆为两行(`C01-IA-F1` 电流 / `C02-UA-F1` 电压),其余顺延为 `C03-UN-F1` 零序、`C04-IA-F2` 二次、`C05-IA-F5` 五次。实现见 `App/algo/phasor.c` 的 `k_inst[]`;判据按 **5** 个实例断言(见 `docs/测试说明/相量层单元测试说明.md` §2.6)。 +> **「基波相量实例」实例数 4 → 5 的来历**:参考项目(`APP/CLS100_Dsp/InstCalCell.c`)为 **4 个实例**——C01 基波 I/U、C02 零序基波、C03 二次谐波、C04 五次谐波。本项目按 V0.1 **有效通道**(`UA`/`UN`/`IA`,见 §1.6:`UB/UC/IB/IC/IN` 无中点偏置 → 削顶不可用)展开:C01 的"I/U"拆为两行(`C01-IA-F1` 电流 / `C02-UA-F1` 电压),其余顺延为 `C03-UN-F1` 零序、`C04-IA-F2` 二次、`C05-IA-F5` 五次。实现见 `App/algo/phasor.c` 的 `k_inst[]`;判据按 **5** 个实例断言(见 `docs/测试说明/单元测试/相量层单元测试说明.md` §2.6)。 -> **本表状态列口径**(2026-10-11 更新):「全周傅氏系数表」~「相位输出」/「每 1 ms 滑动窗刷新」/「双区指针原子交换」已**实现 + 主机单测(57 用例)+ 台架 `@test` 闭环**——闭环命令 `run_boot_test.py --required "...;phasor(first);phasor(hb)" --require-order "App init OK>phasor(first)>phasor(hb)"`,证据 `boot_log_data/20261011_prod_phasor_boot_log.txt`(`fw build` 身份戳匹配、回读一致、锚点 ×1、零 `[ERR]`)。⚠ **幅值/相位精度判据(标准源)在无信号源台架上不可达**(同 §7.1 无示波器口径),且「通道标定(一次系数 + 零漂)」标定未实现 → 现读数为**原始码值**,只证明链路通;精度复核排在标定之后。「线/负序/零序合成」随 V0.2(双转换器无共同采样触发),「遥测谐波轨(可选)」可选项未做。 +> **本表状态列口径**(2026-10-11 更新):「全周傅氏系数表」~「相位输出」/「每 1 ms 滑动窗刷新」/「双区指针原子交换」已**实现 + 主机单测(57 用例)+ 台架 `@test` 闭环**——闭环命令 `run_boot_test.py --required "...;phasor(first);phasor(hb)" --require-order "App init OK>phasor(first)>phasor(hb)"`,证据 `docs/测试说明/测试数据/boot_log_data/20261011_prod_phasor_boot_log.txt`(`fw build` 身份戳匹配、回读一致、锚点 ×1、零 `[ERR]`)。⚠ **幅值/相位精度判据(标准源)在无信号源台架上不可达**(同 §7.1 无示波器口径),且「通道标定(一次系数 + 零漂)」标定未实现 → 现读数为**原始码值**,只证明链路通;精度复核排在标定之后。「线/负序/零序合成」随 V0.2(双转换器无共同采样触发),「遥测谐波轨(可选)」可选项未做。 ### 3.3 保护判据元件 diff --git a/docs/算法/采样有效性校验设计说明.md b/docs/算法/采样有效性校验设计说明.md index 5db1a989..4fba4417 100644 --- a/docs/算法/采样有效性校验设计说明.md +++ b/docs/算法/采样有效性校验设计说明.md @@ -396,7 +396,7 @@ if (((serious | rise) & ~s_health_logged) != 0u) { /* 位图当去重键 */ `[ADC_TASK] health:` 行出现 **0 次**(判定层确实全程失明);`snap` 相对 `req` 缺的正是 bit6 = `TASK_WD_ADC`(`0x1F7 − 0x1B7 = 0x40`,实证 adcTask 当时真的阻塞,而不是"还在跑但没报"); `reset cause:` 仅 1 次——300 ms 停摆被看门狗的 800 ms 容忍吸收,**闭锁不靠复位**。 -证据文件 `docs/测试说明/boot_log_data/20261021_probe_stale_gate_boot_log.txt`。 +证据文件 `docs/测试说明/测试数据/boot_log_data/20261021_probe_stale_gate_boot_log.txt`。 --- @@ -509,7 +509,7 @@ stateDiagram-v2 ### 11.2 台架证据 -`docs/测试说明/boot_log_data/20261011_prod_adc_health_boot_log.txt`:两条心跳行 +`docs/测试说明/测试数据/boot_log_data/20261011_prod_adc_health_boot_log.txt`:两条心跳行 (`adc1_err=0 adc1_hw=0 adc1_gap=23 → 25`、`tgap=1 → 2`、`frames` 每 10 s +10000; 该日志出自**换版前固件**,其中的 `adc1_gap` 是次数口径) 加上全程零 `[ERR]` —— 即「健康不误报」+「gap 常态被正确压住」。 diff --git a/docs/算法/采集与算法层设计说明.md b/docs/算法/采集与算法层设计说明.md index 1e41d09e..8a190d15 100644 --- a/docs/算法/采集与算法层设计说明.md +++ b/docs/算法/采集与算法层设计说明.md @@ -12,7 +12,7 @@ > `docs/硬件平台/ADC通道映射说明.md`(**语义映射唯一权威口径**) > `docs/子系统设计/ADC采样节拍设计说明.md`(TIM3 1 kHz 同源节拍、ADC1+DMA 乒乓缓冲、`adcTask` 唤醒) > `docs/算法/傅氏算法详解.md` §2.3(有效值口径怎么来的) -> `docs/测试说明/相量层单元测试说明.md`、`docs/测试说明/ADC输入层单元测试说明.md`(主机单测细则) +> `docs/测试说明/单元测试/相量层单元测试说明.md`、`docs/测试说明/单元测试/ADC输入层单元测试说明.md`(主机单测细则) ## 目录 @@ -486,8 +486,8 @@ adcTask 静态最坏链与余量的**台账在** `docs/内存管理/RAM使用分 | 模块 | 套件钉死的东西 | 细则 | |---|---|---| -| `phasor` / `sample_ring` | 系数表逐项复核、幅值与相位口径、谐波抑制与提取、频偏、采样环时序、双区交换 | `docs/测试说明/相量层单元测试说明.md` | -| `adc_input` | 逐 Rank 注入互异码值钉死映射、HAL 启动失败与"本拍无新帧"分支、乒乓半区推导、gap / stall 分开计数 | `docs/测试说明/ADC输入层单元测试说明.md` | +| `phasor` / `sample_ring` | 系数表逐项复核、幅值与相位口径、谐波抑制与提取、频偏、采样环时序、双区交换 | `docs/测试说明/单元测试/相量层单元测试说明.md` | +| `adc_input` | 逐 Rank 注入互异码值钉死映射、HAL 启动失败与"本拍无新帧"分支、乒乓半区推导、gap / stall 分开计数 | `docs/测试说明/单元测试/ADC输入层单元测试说明.md` | | `adc_health` | 100 ms 静默门限两侧、丢帧边沿、序号倒退锁存、错误增量、tick 回绕、`NULL` 守卫、`init` 幂等 | `test/host/adc_health/` | | `prot_set` | 范围校验、all-or-nothing 装载、封存-自检-闭锁、Q10 往返、元数据表自检、blob 往返与损坏拒绝、换代拒绝、`uint64_t` bad_mask | `test/host/prot_set/` | | `prot_elm` | 滞回与定时限、欠量方向、投退、闭锁联动、时基回绕、位图聚合、测频接线与"必不启动值" | `test/host/prot_elm/` | @@ -524,5 +524,5 @@ adcTask 静态最坏链与余量的**台账在** `docs/内存管理/RAM使用分 - 通道映射权威口径:`docs/硬件平台/ADC通道映射说明.md` - 采样节拍与 DMA 搬运:`docs/子系统设计/ADC采样节拍设计说明.md` - 傅氏算法与有效值口径:`docs/算法/傅氏算法详解.md` §2.3 -- 主机单测细则:`docs/测试说明/相量层单元测试说明.md`、`docs/测试说明/ADC输入层单元测试说明.md` +- 主机单测细则:`docs/测试说明/单元测试/相量层单元测试说明.md`、`docs/测试说明/单元测试/ADC输入层单元测试说明.md` - RAM 与栈台账:`docs/内存管理/RAM使用分析与优化方案.md` §2.3 diff --git a/docs/网络/BSD_Socket_API_函数调用关系.md b/docs/网络/BSD_Socket_API_函数调用关系.md index 9e5f8ea7..367c6e2d 100644 --- a/docs/网络/BSD_Socket_API_函数调用关系.md +++ b/docs/网络/BSD_Socket_API_函数调用关系.md @@ -449,6 +449,6 @@ sequenceDiagram - `docs/网络/网络自愈架构设计.md` —— **监听生命周期权威设计**(边沿→电平、单一所有者重建 = `net_reconcile_tick` 形态③④、`net_listener.c` / `net_events.c` 模块化边界 §11) - `docs/问题记录/CH395F_Trap_Records.md` —— TRAP-NET-01~23 机制细节(本文引用处) - `docs/网络/Net层阻塞模型架构设计.md` —— 阻塞等待模型的现状架构设计(pending 请求模型 / 五路完成语义) -- `docs/测试说明/链路延迟测试说明.md` —— 芯片 / 队列 / 挂起 recv 等分段时延基线与自愈路径的台架证据 +- `docs/测试说明/专项验证/链路延迟测试说明.md` —— 芯片 / 队列 / 挂起 recv 等分段时延基线与自愈路径的台架证据 - `docs/子系统设计/网络配置说明.md` §4 —— 代次号与网络重建时序 -- `docs/测试说明/CH395F_Test_Guide.md` —— 单连接模型测试规则(TC-NET-6xx) +- `docs/测试说明/板级测试/CH395F_Test_Guide.md` —— 单连接模型测试规则(TC-NET-6xx) diff --git a/docs/网络/Net层阻塞模型架构设计.md b/docs/网络/Net层阻塞模型架构设计.md index 64beb464..016c1a50 100644 --- a/docs/网络/Net层阻塞模型架构设计.md +++ b/docs/网络/Net层阻塞模型架构设计.md @@ -9,7 +9,7 @@ > `docs/网络/BSD_Socket_API_使用指南.md`(应用视角 API 语义)、 > `docs/网络/BSD_Socket_API_函数调用关系.md`(调用链与执行域)、 > `docs/网络/网络自愈架构设计.md`(周期对账与监听生命周期——与本模型的分工见 §2.4;模块化边界见该文档 §11)、 -> `docs/测试说明/链路延迟测试说明.md`(延迟基线与故障对照)、 +> `docs/测试说明/专项验证/链路延迟测试说明.md`(延迟基线与故障对照)、 > 本文件 §10(ACCEPT 挂起化不实施的判据) ## 目录 @@ -614,7 +614,7 @@ net_pending_capture_owner() ← 捕获执行者 | 指标 | 值 | 来源 / 条件 | |---|---|---| | 队列响应性(挂起连接下) | **92.5 ms** | `test/host/e02_probe.py`:挂起对时客户端 + FTP banner 探测 | -| M3 静默档帧周期 | med 58.9 / p95 69.9 / max 72.1 ms | `docs/测试说明/链路延迟测试说明.md` §6.3(零尖峰) | +| M3 静默档帧周期 | med 58.9 / p95 69.9 / max 72.1 ms | `docs/测试说明/专项验证/链路延迟测试说明.md` §6.3(零尖峰) | | M3 压力档帧周期 | med 60.1 / p95 66.4 / max 69.3 ms | 同上(零尖峰) | | netTask 栈峰值 | **1116 B / 3840 B(余 70%)**,FTP 传输期峰 **1164 B**;静态最坏链 ≈1.9 KB | `docs/内存管理/RAM使用分析与优化方案.md` §2.3 | | 挂起表静态 RAM | recv `s_net_pending[]` **192 B** + send `s_net_send[]` **224 B**(RW_IRAM1) | §4.1 / §4.5 | diff --git a/docs/网络/网络自愈架构设计.md b/docs/网络/网络自愈架构设计.md index 75ec40a0..4a379b91 100644 --- a/docs/网络/网络自愈架构设计.md +++ b/docs/网络/网络自愈架构设计.md @@ -460,7 +460,7 @@ CLOSED → 由形态④ 接手。关键在两条快路径的判据(`net_pendin 僵尸 30~90s(E13)——不是应用可加速的路径。 - 回归锚点:`TC-NETSOCK-240efg / 321 全组 / 460ef`(登记式、netTask 零占用、 client fd 旧形态保留);台架判据 = V5 复跑(e02_probe + FTP ≥30min)零 stall, - 见 `docs/测试说明/实机测试实施指南.md` §4。 + 见 `docs/测试说明/板级测试/实机测试实施指南.md` §4。 ### 4.7 KeepAlive(服务器侧) diff --git a/docs/门禁说明/README.md b/docs/门禁说明/README.md index 884f2e85..c43cf11b 100644 --- a/docs/门禁说明/README.md +++ b/docs/门禁说明/README.md @@ -77,7 +77,7 @@ | [`setview-check.md`](setview-check.md) | `setview-check` | 定值查看行表与 `prot_set` 枚举序 / `g_prot_set_meta` 上下限是否同一份口径 | `tools/setview_check/**`、`ui_w_setview.*` | 已写 | | (专篇待补,档位与限度正文在 [`../UI设计/UI_自动化测试流程.md`](../UI设计/UI_自动化测试流程.md) §7.3) | `uinav-selftest` | 板端 UI 导航器认屏快检(黄金参考帧分类;完整闭环档=合入前/上板前手工跑,快检不互替) | `scripts/board_ui_nav.py`、`simulator/tests/ref/*.bin` | 指针 | | [`host-unit-tests.md`](host-unit-tests.md) | 22 个 `*-unit-test` | 主机侧单测(同一机制 22 个实例):逻辑层在无硬件的 PC 上编译并跑断言 | 各自被测模块与其测试目录 | 已写 | -| 详解在 [`../测试说明/主机单测覆盖率口径.md`](../测试说明/主机单测覆盖率口径.md)(口径 / 分母 / 基线 / 盲区都在那篇,本目录不重复) | `test-coverage` | **覆盖率总闸**:跑全部 44 套主机单测 + 已覆盖行只增不减的回退台账 | `App/`、`Drivers/BSP/`、`test/host/`、脚本与基线 | 已写(在 `docs/测试说明/`;`stages: [manual]`) | +| 详解在 [`../测试说明/单元测试/主机单测覆盖率口径.md`](../测试说明/单元测试/主机单测覆盖率口径.md)(口径 / 分母 / 基线 / 盲区都在那篇,本目录不重复) | `test-coverage` | **覆盖率总闸**:跑全部 44 套主机单测 + 已覆盖行只增不减的回退台账 | `App/`、`Drivers/BSP/`、`test/host/`、脚本与基线 | 已写(在 `docs/测试说明/`;`stages: [manual]`) | | [`trailing-whitespace.md`](trailing-whitespace.md) | `trailing-whitespace` | 行尾空白(改写型;CubeMX/Keil 生成文件豁免) | 全部 | 已写 | | [`end-of-file-fixer.md`](end-of-file-fixer.md) | `end-of-file-fixer` | 文件末尾必须恰好一个换行(改写型;同豁免) | 全部 | 已写 | | [`check-added-large-files.md`](check-added-large-files.md) | `check-added-large-files` | 别把大文件(日志/镜像/二进制)误提进仓库 | 全部 | 已写 | diff --git a/docs/门禁说明/bsp-err.md b/docs/门禁说明/bsp-err.md index 170e0fa5..33aa0a27 100644 --- a/docs/门禁说明/bsp-err.md +++ b/docs/门禁说明/bsp-err.md @@ -37,7 +37,7 @@ - **它上线当天就照出真窟窿**:`consume-result` 落地即暴露 37 条存量丢弃,其中一处是 `bbt_rebuild` 重新打开 ECC 的那两行返回值全丢——SPI 一抖 ECC 就保持关闭,而 ECC 关闭时 ECC 检查恒读"无错",整条链再没有任何信号。修法与运维判据见 - `docs/测试说明/存储维护与容量恢复.md` §4.3。 + `docs/测试说明/专项验证/存储维护与容量恢复.md` §4.3。 - **没有工具会替我们做这件事**,两条实测负结果(本门禁存在的正当性全在这两条上): ① `__attribute__((warn_unused_result))` 在 ARMCC v5 上**完全不生效**——属性挂上、调用点 裸调不接返回值,构建仍 0 错 0 警告(在 `rs485_transmit` 上做过实验); diff --git a/docs/门禁说明/host-unit-tests.md b/docs/门禁说明/host-unit-tests.md index 622f45ae..dae4386b 100644 --- a/docs/门禁说明/host-unit-tests.md +++ b/docs/门禁说明/host-unit-tests.md @@ -123,7 +123,7 @@ 几个坑正是这类,见 `docs/问题记录/*_Trap_Records.md`)。 6. 断言写的是"作者当时想到的分支":**行 / 函数覆盖有度量了**(`test-coverage` 总闸出 Cobertura 并守基线台账),但**分支覆盖仍无**——按用户裁定 2026-10-23 记为**已接受缺口**, - 口径与理由见 `docs/测试说明/主机单测覆盖率口径.md` §2.1,不是待办。 + 口径与理由见 `docs/测试说明/单元测试/主机单测覆盖率口径.md` §2.1,不是待办。 ## 7. 豁免与基线 diff --git a/docs/门禁说明/test-suite-switch.md b/docs/门禁说明/test-suite-switch.md index 6ee8ae0c..c9e9f415 100644 --- a/docs/门禁说明/test-suite-switch.md +++ b/docs/门禁说明/test-suite-switch.md @@ -49,7 +49,7 @@ 跑,不适合作为常规手段。 3. 它不判断"产品构建是否真的没有测试代码"(`test/board/*.c` 可能仍在工程里,只是被宏关掉)。 4. `ENABLE_DESTRUCTIVE_TESTS` 的开/关**不由本门判定**(那是破坏性代价,属 Ask-first 事项, - 见 `docs/测试说明/存储维护与容量恢复.md`)。 + 见 `docs/测试说明/专项验证/存储维护与容量恢复.md`)。 - **判定实现**:先剥掉块注释与行注释再匹配 `#define`,所以注释掉的开关不会误判;同文件派生出的 `TEST_SUITE_SELECTED` / `TEST_SUITE_NAME` 由白名单排除(它们是开关的推导结果,不是可选项)。 diff --git a/docs/问题记录/ADC_Trap_Records.md b/docs/问题记录/ADC_Trap_Records.md index 49b5b495..70e8e9a4 100644 --- a/docs/问题记录/ADC_Trap_Records.md +++ b/docs/问题记录/ADC_Trap_Records.md @@ -142,4 +142,4 @@ DMA 从序列中途开始搬运时,整个缓冲一起旋转,拷贝照样"恒 `docs/子系统设计/ADC采样节拍设计说明.md` §4.5(设计铁律第 8 条)。 - 通道映射与引脚对应:`docs/硬件平台/ADC通道映射说明.md`。 - 前端拓扑(③ 段变比 = 1:1,非分压):`docs/硬件平台/V0.0_网表详细分析报告.md` §4.7。 -- 零点/线性/映射的现场验证步骤与判据:`docs/测试说明/ADC前端注入验证流程.md`。 +- 零点/线性/映射的现场验证步骤与判据:`docs/测试说明/专项验证/ADC前端注入验证流程.md`。 diff --git a/docs/问题记录/CH395F_Trap_Records.md b/docs/问题记录/CH395F_Trap_Records.md index 31b43fcd..db1322e0 100644 --- a/docs/问题记录/CH395F_Trap_Records.md +++ b/docs/问题记录/CH395F_Trap_Records.md @@ -132,7 +132,7 @@ CH395F 以太网驱动与 NET 层的实证陷阱:现象、定案根因、修 2. **幽灵态甄别**:补 accept 前回读对端端口(`GET_REMOT_IPP`),**= 上一条连接端口(`last_peer_port`)→ 幽灵,不 accept**; 3. 对账②同步加幽灵甄别;`last_peer_port` 登记点:`handle_disconnect_event` / `handle_timeout_event` / `net_relisten_try`(清零 remote_port 前转登)/ `net_close_locked`(跨 memset 保留——幽灵属芯片 Socket 级,与 fd 复用无关)。 - **定案二:closed-with-data accept(425 真根因=accept 竞态自毁缓冲)**:`FUN_PARA` bit3 `SOCKET_CLOSE=1`(§5.52 ②)下产生 DISCONNECT 后芯片**不关 Socket、不清缓冲**,RX 缓冲里 STOR 载荷一个不少(探针实证 `recv_len=1027 re-read st=0x05/0x00`);那个 DISCONNECT 是**客户端正常 FIN**(ftplib `storbinary` 发完即关,局域网小文件 ~5ms)。旧 `net_accept_locked` 把 CLOSED 一律当"无连接" → `net_relisten_try`(close+open **清空芯片 RX 缓冲**)→ 数据被**我方亲手销毁** → 425。**修复**:CLOSED + auto_relisten + **芯片 RX 有数据**(`GET_RECV_LEN_SN`>0)→ 接受这条"已关但可读"连接(日志 `closed-with-data accept (drain pending)`),应用快路径排空,排空后 EOF 自然触发 relisten——对齐 §5.52 ② 契约。 -- **定案三:LIST 吞包 = 背靠背小段写毒化芯片 TX**:决定性对照——同一目录,LIST #1(行间天然间隔)通过;LIST #4/#7(每行一次 `net_send` ~60B 背靠背小段)必挂。芯片对同一连接的**背靠背多段小写入**会毒化 TX(芯片报 SEND_OK 但对端全部丢弃,无 RST 无 DISCONNECT);RETR 1KB 满块连发不受影响。**修复**:`send_list`/`send_nlst` 整份目录**一次性批量发送**(static 1536B 缓冲;注意 `lftpd_inet_write` 成功返回**字节数**非 0)。 **2026-10-22 增补(同一处缓冲埋的第二颗雷)**:批量发送把"装满就 `break` + 回 −1"留在了路径上,`cmd_list` 据此回 **550**——目录一旦超过 1536 B,客户端拿到的是**静默截断**的清单**外加一个错误码**,而清单看起来完全像"目录里就这些"。实测台架根目录 30 条目:修复前 1512 B / 24 条目 / 完成回包 550,修复后 1880 B / 30 条目 / 226,**6 个文件凭空消失**。改成**满块续发**(装满一块整块发出、清空再装):既保住"只发大块"这条实测结论(定案三的本体),又不让清单完整性由一个缓冲区上限决定;单行真装不下时**明确失败**而不是少发条目。同一函数还有个已知偏差:`cmd_list`/`cmd_nlst` 忽略命令参数、恒列 `client->directory`(会话 CWD)——主流客户端都是 `CWD` + 裸 `LIST`,暂未修,登记在案。 **回归**:`test/host/ftp_list_fill_test.py`(自造 26 个 8.3 短名文件把清单撑过一块,判"全列出 + 完成回包 226",跑完自动删干净;用法见 `../测试说明/FTP_Test_Guide.md` §4.5)——设备目录清空后,只有这种自己造规模的脚本才拦得住这颗雷。 +- **定案三:LIST 吞包 = 背靠背小段写毒化芯片 TX**:决定性对照——同一目录,LIST #1(行间天然间隔)通过;LIST #4/#7(每行一次 `net_send` ~60B 背靠背小段)必挂。芯片对同一连接的**背靠背多段小写入**会毒化 TX(芯片报 SEND_OK 但对端全部丢弃,无 RST 无 DISCONNECT);RETR 1KB 满块连发不受影响。**修复**:`send_list`/`send_nlst` 整份目录**一次性批量发送**(static 1536B 缓冲;注意 `lftpd_inet_write` 成功返回**字节数**非 0)。 **2026-10-22 增补(同一处缓冲埋的第二颗雷)**:批量发送把"装满就 `break` + 回 −1"留在了路径上,`cmd_list` 据此回 **550**——目录一旦超过 1536 B,客户端拿到的是**静默截断**的清单**外加一个错误码**,而清单看起来完全像"目录里就这些"。实测台架根目录 30 条目:修复前 1512 B / 24 条目 / 完成回包 550,修复后 1880 B / 30 条目 / 226,**6 个文件凭空消失**。改成**满块续发**(装满一块整块发出、清空再装):既保住"只发大块"这条实测结论(定案三的本体),又不让清单完整性由一个缓冲区上限决定;单行真装不下时**明确失败**而不是少发条目。同一函数还有个已知偏差:`cmd_list`/`cmd_nlst` 忽略命令参数、恒列 `client->directory`(会话 CWD)——主流客户端都是 `CWD` + 裸 `LIST`,暂未修,登记在案。 **回归**:`test/host/ftp_list_fill_test.py`(自造 26 个 8.3 短名文件把清单撑过一块,判"全列出 + 完成回包 226",跑完自动删干净;用法见 `../测试说明/板级测试/FTP_Test_Guide.md` §4.5)——设备目录清空后,只有这种自己造规模的脚本才拦得住这颗雷。 - **与 TRAP-NET-17 的关系**:周期对账对常驻监听器有效;FTP 数据通道是"活 1 秒就死"的短命监听器,对账②无幽灵甄别时既救不全又帮凶。本条把"看状态补 accept"内联进 accept 热路径(短去抖、无冷却)+ 端口甄别,对账②保留为兜底网。 - **教训(总纲)**:**CH395F 的"成功"(中断位/状态码)只代表芯片本地动作完成,不代表对端收到;判定必须回到对端可见证据(主机侧收发)+ 手册语义(FUN_PARA §5.52、状态码 §5.22)**。 - **对应文件**:`net_events.c`(`net_lost_connect_probe` / `net_reconcile_tick`②;原在 `net_socket.c`,2026-10-14 抽出)、`net_socket.c`(closed-with-data accept)、`net_types.h`(`last_peer_port`)、`lftpd.c`(批量发送);台架 `test/board/ch395f_reuse_bench.{c,h}` + `test/host/ch395f_reuse_host.py`(主分支存档)。 @@ -260,7 +260,7 @@ CH395F 以太网驱动与 NET 层的实证陷阱:现象、定案根因、修 - **现象**:`GET_DHCP_STATUS` 已置 0x00 后立即 `GET_IP_INF` 读到的仍是旧静态配置,而芯片实际已按新租约收发——三方数据矛盾构成假阳性。 - **根因(定案)**:DHCP 状态位仅代表协商完成;IP/MASK/GW 寄存器提交与状态置位**异步**,数百毫秒级窗口(实测 ~1s 内翻转)。 - **修复**:① 连续 3 次读 `GET_IP_INF`(间隔 300ms,上限 8s)一致且非零才采信;② PC 端把收到的宣告 IP 与租约比对兜底。 -- **对应**:`test/board/ch395f_test_task.c: phase4_run()`;`docs/测试说明/CH395F_Test_Guide.md` 阶段 4 风险表 #4。 +- **对应**:`test/board/ch395f_test_task.c: phase4_run()`;`docs/测试说明/板级测试/CH395F_Test_Guide.md` 阶段 4 风险表 #4。 --- @@ -296,7 +296,7 @@ CH395F 以太网驱动与 NET 层的实证陷阱:现象、定案根因、修 ## 主机侧测试工具过期 - **`test/host/ftp_abort_probe.py` 已修**:原用匿名登录,FTP 鉴权落地后匿名被 530 拒 → TRAP-NET-18 两条腿**假 0/5**(第 1 轮 `PASV failed`,且半认证会话占死 FTP 唯一会话,后续轮全变 `ConnectionRefused`)。改 `admin/admin` 后 RST 5/5、FIN 5/5。**教训:跑既有回归腿前先确认凭据仍有效,否则会把工具过期读成固件回归。** -- **同族未修**:`test/host/ftp_up_dl_test.py`、`ftp_speed_test.py`、`ftp_test.py` 仍用匿名登录 → 对当前固件必挂登录步;`docs/测试说明/FTP_Test_Guide.md` 推荐的这几个入口因此已失效(现行可用入口是 `test/host/ftp_regression.py`,默认 `admin/admin`)。 +- **同族未修**:`test/host/ftp_up_dl_test.py`、`ftp_speed_test.py`、`ftp_test.py` 仍用匿名登录 → 对当前固件必挂登录步;`docs/测试说明/板级测试/FTP_Test_Guide.md` 推荐的这几个入口因此已失效(现行可用入口是 `test/host/ftp_regression.py`,默认 `admin/admin`)。 ## 文档侧待修清单 diff --git a/scripts/README.md b/scripts/README.md index 82b2122b..82d7d64a 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -41,10 +41,10 @@ | 脚本 / 文件 | 作用 | |---|---| -| `ci_local.py` | **本地跑与 CI 等价的门禁**(静态门禁 pre-commit 47 根 + **manual 段**(`cppcheck` / `test-cppcheck` / `test-coverage` 三根逐根 `--hook-stage manual`,默认跑)+ 提交信息门禁 + **体积门禁** + 主机侧纯逻辑单测):自动选用装了 pre-commit 的解释器;无 `.map` 时自适应跳过 `mem-numbers` / `mem-budget`(⚠ 那是 SKIP 不是通过,缺口由体积门禁兜住);退出码 0/1/2 与 CI 对齐。CI 定义见 `../.gitea/workflows/ci.yml`,覆盖边界见 `docs/测试说明/测试开发标准流程.md` §9 | +| `ci_local.py` | **本地跑与 CI 等价的门禁**(静态门禁 pre-commit 47 根 + **manual 段**(`cppcheck` / `test-cppcheck` / `test-coverage` 三根逐根 `--hook-stage manual`,默认跑)+ 提交信息门禁 + **体积门禁** + 主机侧纯逻辑单测):自动选用装了 pre-commit 的解释器;无 `.map` 时自适应跳过 `mem-numbers` / `mem-budget`(⚠ 那是 SKIP 不是通过,缺口由体积门禁兜住);退出码 0/1/2 与 CI 对齐。CI 定义见 `../.gitea/workflows/ci.yml`,覆盖边界见 `docs/测试说明/流程与规范/测试开发标准流程.md` §9 | | `check_size_gate.py` | **体积门禁的强制路径**:`.map` 只在本地有,钩子无它时自适应 SKIP,于是"没测=通过"。本脚本用**已提交的同码凭证** `scripts/size_attestation.json` 把这条判据变成无需 Keil 也能跑:`--stamp` 只在"`.map` 存在、比全部受管源码新、且未超 92%"时才盖章(已挂在 `ram_baseline.py --update` 里,无新增人工步骤);`--local` 供 ci_local 的体积门禁步;`--ci` 供 runner(同码性 + 按凭证数字复核红线,主干 push 拦红、其余事件 `--warn-only`);`--show` 排障。**口径与边界的唯一正文在本脚本模块 docstring** | | `size_attestation.json` | (被 `check_size_gate.py` 读写)体积同码凭证:受管源码指纹(`git ls-files` 范围内逐文件 sha256 聚合)+ 测量数字与占比 + `.map` 出处。改固件源码后不重测 → 指纹对不上 → 体积门禁与 CI 同时拦红 | -| `check_test_coverage.py` | 主机单测**覆盖率**(2026-10-23):mscoverage 动态插桩跑 `test/host/**` 全部 44 套,统计自研生产源码行/函数覆盖(并集)+ 与 `test_coverage_baseline.json` 比回退;`--module/--update-baseline/--md/--json/--list`;挂在 `test-coverage` 钩子上(`stages: [manual]`,**`git commit` 不跑**),入口 = 远端 CI「手动阶段门禁」步 / `scripts/ci_local.py` 的 manual 段(`--coverage` 旗标保留只为兼容旧命令;口径见 `docs/测试说明/主机单测覆盖率口径.md`) | +| `check_test_coverage.py` | 主机单测**覆盖率**(2026-10-23):mscoverage 动态插桩跑 `test/host/**` 全部 44 套,统计自研生产源码行/函数覆盖(并集)+ 与 `test_coverage_baseline.json` 比回退;`--module/--update-baseline/--md/--json/--list`;挂在 `test-coverage` 钩子上(`stages: [manual]`,**`git commit` 不跑**),入口 = 远端 CI「手动阶段门禁」步 / `scripts/ci_local.py` 的 manual 段(`--coverage` 旗标保留只为兼容旧命令;口径见 `docs/测试说明/单元测试/主机单测覆盖率口径.md`) | | `ci_gitlint_range.ps1` | CI 侧**提交信息门禁**:逐条校验本次 push/PR 引入的提交(`--all-files` 跑不到 `commit-msg` stage,故必须单独守) | | `ci_find_python.ps1` | CI 侧 Python 探测(候选顺序须与 `ci_local.py` 同序同步,否则 CI 与本地判定会分叉) | | `ci_runner_bootstrap.ps1` | **本机 runner 运维脚本**(体检 `-Status` / 干跑 `-DryRun` / 部署 `-SetEnv -StartNow`):装"等 Gitea 就绪 + 崩溃自拉起"的看门狗 + 开机计划任务 + 机器级 `DTU_*` | diff --git a/scripts/archive/id_gate/id_aliases.json b/scripts/archive/id_gate/id_aliases.json index 99356045..c00fcbcc 100644 --- a/scripts/archive/id_gate/id_aliases.json +++ b/scripts/archive/id_gate/id_aliases.json @@ -174,7 +174,7 @@ { "to": null, "status": "void", - "note": "从未存在的陷阱号被 docs/测试说明/CH395F_Test_Guide.md 引用(§1.2 / §7.2:删除或改指实际条目)" + "note": "从未存在的陷阱号被 docs/测试说明/板级测试/CH395F_Test_Guide.md 引用(§1.2 / §7.2:删除或改指实际条目)" }, { "to": "TRAP-NET-19", @@ -2853,7 +2853,7 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", "Drivers/BSP/GD5F2GQ5UE/nand_ftl.c", @@ -2867,7 +2867,7 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", "Drivers/BSP/GD5F2GQ5UE/nand_ftl.c", @@ -2881,7 +2881,7 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", "Drivers/BSP/GD5F2GQ5UE/nand_ftl.c", @@ -2895,7 +2895,7 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", "Drivers/BSP/GD5F2GQ5UE/nand_ftl.c", @@ -2909,7 +2909,7 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", "Drivers/BSP/GD5F2GQ5UE/nand_ftl.c", @@ -2923,7 +2923,7 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", "Drivers/BSP/GD5F2GQ5UE/nand_ftl.c", @@ -2937,7 +2937,7 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", "Drivers/BSP/GD5F2GQ5UE/nand_ftl.c", @@ -2950,7 +2950,7 @@ "status": "renamed", "note": "同一属主的中文形「见陷阱 01」→ 与空格形合并成同一个号(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md" + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md" ] }, "陷阱 1": { @@ -3296,7 +3296,7 @@ "S-2": { "to": null, "status": "void", - "note": "本号两义,均已死:① 登记簿 S-2(启动日志固化流程,2026-09-22 提出、2026-10-05 固化后销项)→ docs/测试说明/boot_log_data/README.md;② 报告 S-2(跨模块裸 `extern`,2026-10-22 已闭环)→ 契约见 App/task/task_handles.h、gd5f_spi1_notify_*、net_msg_queue_adopt" + "note": "本号两义,均已死:① 登记簿 S-2(启动日志固化流程,2026-09-22 提出、2026-10-05 固化后销项)→ docs/测试说明/测试数据/boot_log_data/README.md;② 报告 S-2(跨模块裸 `extern`,2026-10-22 已闭环)→ 契约见 App/task/task_handles.h、gd5f_spi1_notify_*、net_msg_queue_adopt" }, "N-2": { "to": null, diff --git a/scripts/archive/id_gate/id_registry.json b/scripts/archive/id_gate/id_registry.json index ad9b91c7..3d19c8de 100644 --- a/scripts/archive/id_gate/id_registry.json +++ b/scripts/archive/id_gate/id_registry.json @@ -389,10 +389,10 @@ "owner_docs_glob": [ "docs/测试说明/*_Test_Guide.md", "docs/测试说明/*单元测试说明.md", - "docs/测试说明/实机测试实施指南.md", - "docs/测试说明/链路延迟测试说明.md", - "docs/测试说明/自动化测试流程.md", - "docs/测试说明/存储维护与容量恢复.md" + "docs/测试说明/板级测试/实机测试实施指南.md", + "docs/测试说明/专项验证/链路延迟测试说明.md", + "docs/测试说明/流程与规范/自动化测试流程.md", + "docs/测试说明/专项验证/存储维护与容量恢复.md" ], "scope": "global", "frozen": true, @@ -612,7 +612,7 @@ "title": "台架日志代次(§4.2 目标形态,数字不变仅改字面)", "pattern": "\\bGEN-[0-9]{1,3}\\b", "owner_docs": [ - "docs/测试说明/串口助手设计说明.md" + "docs/测试说明/测试工具/串口助手设计说明.md" ], "scope": "global", "frozen": false, @@ -626,7 +626,7 @@ "title": "台架轮次(§4.2 目标形态,日期制)", "pattern": "\\bRUN-[0-9]{8}-[0-9]{1,2}\\b", "owner_docs": [ - "docs/测试说明/实机测试实施指南.md" + "docs/测试说明/板级测试/实机测试实施指南.md" ], "scope": "global", "frozen": false, @@ -795,7 +795,7 @@ "title": "模拟器差距(§4.2;§7.1 收编 H-x / L-x / 差距 N-x)", "pattern": "\\bGAP-[0-9]{1,3}\\b", "owner_docs": [ - "docs/测试说明/模拟器差距清单.md" + "docs/测试说明/专项验证/模拟器差距清单.md" ], "scope": "doc-scoped", "frozen": false, @@ -813,7 +813,7 @@ "title": "实机验证场景(§4.2;§7.1 收编实机预检 A1~A8、看门狗 V2/V4/V5)", "pattern": "\\bSC-[0-9]{1,3}\\b", "owner_docs": [ - "docs/测试说明/实机测试实施指南.md" + "docs/测试说明/板级测试/实机测试实施指南.md" ], "scope": "doc-scoped", "frozen": false, @@ -878,7 +878,7 @@ "title": "链路延迟分段 LAT-(§4.2 文档内编号;存量 L1~L11)", "pattern": "\\bLAT-[0-9]{1,2}\\b", "owner_docs": [ - "docs/测试说明/链路延迟测试说明.md" + "docs/测试说明/专项验证/链路延迟测试说明.md" ], "scope": "doc-scoped", "frozen": false, @@ -1178,7 +1178,7 @@ "title": "模拟器差距清单 H-1~H-7(§7.1 → GAP-01~07)", "pattern": "\\bH-[0-9]\\b", "owner_docs": [ - "docs/测试说明/模拟器差距清单.md" + "docs/测试说明/专项验证/模拟器差距清单.md" ], "scope": "doc-scoped", "frozen": true, @@ -1195,7 +1195,7 @@ "title": "模拟器差距清单 L-1~L-4(§7.1 → GAP-08~11)", "pattern": "\\bL-[0-9]\\b", "owner_docs": [ - "docs/测试说明/模拟器差距清单.md" + "docs/测试说明/专项验证/模拟器差距清单.md" ], "scope": "doc-scoped", "frozen": true, @@ -1212,7 +1212,7 @@ "title": "模拟器差距清单 N-1~N-6(§7.1 → GAP-12~17;与登记簿 N-x 同名不同义)", "pattern": "\\bN-[0-9]\\b", "owner_docs": [ - "docs/测试说明/模拟器差距清单.md" + "docs/测试说明/专项验证/模拟器差距清单.md" ], "scope": "doc-scoped", "frozen": true, @@ -1292,7 +1292,7 @@ "pattern": "\\bV[2-9]\\b", "owner_docs": [ "docs/子系统设计/看门狗设计说明.md", - "docs/测试说明/实机测试实施指南.md" + "docs/测试说明/板级测试/实机测试实施指南.md" ], "scope": "doc-scoped", "frozen": true, @@ -1335,7 +1335,7 @@ "title": "测试分层五档 T0/T0.5/T1/T2/T3(§4.2 目标形态;现存写 L0~L3)", "pattern": "\\bT[0-3](?:\\.5)?\\b", "owner_docs": [ - "docs/测试说明/测试开发标准流程.md" + "docs/测试说明/流程与规范/测试开发标准流程.md" ], "scope": "global", "frozen": false, @@ -1351,7 +1351,7 @@ "title": "门禁档位 G0~G3(§4.2,与测试分层两套不合并)", "pattern": "\\bG[0-3](?:\\.5)?\\b", "owner_docs": [ - "docs/测试说明/测试开发标准流程.md" + "docs/测试说明/流程与规范/测试开发标准流程.md" ], "scope": "global", "frozen": true, @@ -1365,7 +1365,7 @@ "title": "测试分层 / 算法层现存裸形 L0~L3(§4.2 目标 → T0~T3;§1.2 记四义)", "pattern": "\\bL[0-3](?:\\.5)?\\b", "owner_docs": [ - "docs/测试说明/测试开发标准流程.md", + "docs/测试说明/流程与规范/测试开发标准流程.md", "App/algo/README.md" ], "scope": "global", @@ -2155,7 +2155,7 @@ ] }, "owner_docs_exclude": [ - "docs/测试说明/测试文档模板规范.md" + "docs/测试说明/流程与规范/测试文档模板规范.md" ], "designator_rule": "硬件语料位号识别:docs/硬件平台/ 与 docs/芯片手册/ 里匹配 ^[RCDJXUT][0-9]{1,3}$(无连字符)的字面量判为**位号**,不产生任何编号结论;不含 B(V0.0 网表报告的 B1 是真专项条目),带连字符的 D-7/N-18/TC-206 不受影响。机制在 check_ids.py 的 add() 里落地(统计键 designator_skipped)。**本目录仍未纳入扫描语料**:纳入前必须先把位号从可判定比例的 refs_total 里减掉,否则约 4200 处位号会把比例分母灌水、掩盖真实变化。 【批 9 扩展】同一规则再覆盖**引脚名/总线名/网名/区间**:^[A-Z]{2,3}[0-9]{1,2}(-[0-9]{1,2})?(如 PB12-15、PG0-15、PF13-15、DB0-15、OS0-2、KEY1-3、AIN1),同样不进 refs_total。带连字符的一字母形态(C-10 / A-9 / N-18 / D-7)与 TC-206 / TC1003 一律不受影响,仍照旧判。器件料号(FOC-817SC-F 被切成 FOC-817)**不做形状规则**:[A-Z]{3}-\\d{3} 与真家族 DEF-* 撞形,代价远大于收益,故留在台账 reason 里记账。", "excluded_paths_note": [ diff --git a/scripts/archive/id_gate/编号治理历史.md b/scripts/archive/id_gate/编号治理历史.md index f3af6f6d..1a15ccc6 100644 --- a/scripts/archive/id_gate/编号治理历史.md +++ b/scripts/archive/id_gate/编号治理历史.md @@ -168,7 +168,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语 2. **本文自述形态化**:把本文里 4 处「字母 T 紧跟数字」与 2 处 DRV 段孤儿号的**字面量写法**改成形态描述(lesson 不丢),使这四个族的门禁命中数真正归零,而不是停在「只有规范自己在引用」。 3. **登记机器面还空着的那一面**:`scripts/archive/id_gate/id_registry.json` 给 `L-PROT`/`FEAT` 补 `retired` 字段;给 `T-TEST` 补 `cursor_note` 写明——它的 pattern 最高只到数字 3,**即使 `frozen: true` 校验 5 也碰不到任何新写法**(探针实测写 4 不响),所以该族停发今天只有 `docs/编号规范.md` §3.3 禁令 + 评审两道兜底,**别把「存量已清零」读成「机器已关闭」**。 -> ⚠ 本轮执行期间另有一道并行改动落地:`docs/测试说明/boot_log_data/README.md`(登记簿旧号「启动日志固化流程」)与 `docs/测试说明/m2_data/README.md`(审计发现 E 族一处死号)已由该道改为语义短语——**本笔不重复改这两处、也不替它收口**;复测两处死号引用均为 0。 +> ⚠ 本轮执行期间另有一道并行改动落地:`docs/测试说明/测试数据/boot_log_data/README.md`(登记簿旧号「启动日志固化流程」)与 `docs/测试说明/测试数据/m2_data/README.md`(审计发现 E 族一处死号)已由该道改为语义短语——**本笔不重复改这两处、也不替它收口**;复测两处死号引用均为 0。 §8.1 的 7,828 是当日更早时点值;本轮 14:1x 复测 **791 文件 / 7,931 字面量 / 不可判定 982(上限 1,166,余量 184)/ 可判定 87.61%**——增量全部来自别道在飞的新代码与新文档,本笔净效果是**只减不增**。 ### 9.1 三批计划(按「值不值得动门禁」排序) @@ -243,7 +243,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语 上一笔曾特意标 ✅ 保留,理由是该行被 `App/task/adc_task.c` 的 v3.3 修订行按卡号当口径出处引用; 引用侧改成语义短语后该理由不再成立 → **例外撤销**。判据与实测记录的属主 = `docs/硬件平台/ADC通道映射说明.md` §8.1(六项判据全 PASS、斜率 6544.2 码/V、偏差 −0.14 %), - 执行侧 = `docs/测试说明/ADC前端注入验证流程.md`(含两项残留口径与残差表)。 + 执行侧 = `docs/测试说明/专项验证/ADC前端注入验证流程.md`(含两项残留口径与残差表)。 2. **整族清退**:「卡」+ 数字 1~11 那 11 行早在 2026-10-25 就删完了,代码注释里剩下的这种形态今天 **查无此行**——按 `docs/编号规范.md` §4.1.1 末句,正确动作是**删号留事实**(换成语义短语),不是回去补一个定义。 @@ -333,7 +333,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语 1. **peer 的 JSON 键不改(本族清退到 schema 边界为止)**:`test/host/latency_peer.py` 的 `l5_recv` / `l5_send` / `l3_drain` / `l7_crc` / `seg_l6` / `seg_l7_first_byte` / `seg_l7_total` / - `frames_l7` 与内部字典键 `l3`/`l6`/`l7`(共 48 token)是 `docs/测试说明/m2_data/*.json` 五份 + `frames_l7` 与内部字典键 `l3`/`l6`/`l7`(共 48 token)是 `docs/测试说明/测试数据/m2_data/*.json` 五份 **冻结实测证据**的 schema。改名要么让代码与归档数据漂移,要么得回头改证据文件(等于篡改 测量产物)——两条都不接受。这是**有记录的刻意例外**,不是漏网。 2. **`REQ2FIRST` / `FULLFRAME` 不并入 `ECHO_RT` / `FRAME_RT`**:它们是「整帧往返」段内两个不同 @@ -362,7 +362,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语 | 2026-10-27 | **批次四:`L-PROT` / `FEAT` 发号口关闭(`docs/编号规范.md` §4.1 七行→五行)+ 本文自述形态化 + 登记 `T-TEST` 机器面空白** | 用户指令「语义标识已定为默认形态,看看还有哪些编号族仍被引用、各自还剩多少,把能清的族清掉一批」。按门禁 `Checker` 实测三口径重打 §9 存量表:**真编号活引用只剩 `TC-*`(保留、水位 497/81 未涨)、`TRAP-*`、`CODE-RULE-*`、`MENU-STATE-*` 四族**,批次一/二涉及的 `N-*`/`TM-*`/`T-TEST`/`L-PROT`/`FEAT` 活引用均已归零。本笔:① `docs/编号规范.md` §4.1 把 `L-`、`F--` 从『允许继续发号』整行移出并在『已停发』栏各写一行(含探针证据:新形态号 → 校验 3 错误级);② 本文 6 处形态自述改「字母+数字」描述,使四个族门禁命中归零、lesson 不丢;③ registry 给 `L-PROT`/`FEAT` 补 `retired`、给 `T-TEST` 补 cursor_note(pattern 上限即 3 → 冻结游标是空操作,停发今天只有规范效力);④ 分类登记 `docs/编号规范.md` §4.4 误判面(版本记号 / 活表代号 / 状态组合 / 位号)与 `docs/编号规范.md` §4.3 冻结波次号两类**不清**的理由。未改门禁判定逻辑、未动冻结历史与原始串口日志、未新增任何号。 | | 2026-10-27 | **批次一 `F-*` 收口:网络设计 12 个条目号转「条目名」语义短语,§7 表加「条目名」列为权威对照** | 用户指令「把网络设计里的 `F-*` 条目号换成语义短语,别改坏硬件资料的 T1/T2/T3 位号和 Mermaid 节点名」。走 `scripts/rename_ids.py`(映射 `scripts/rename_maps/batch7-f-net-semantic.json`,`--no-alias` 后手工写别名),10 处定点改写=属主文档正文 9 处(含 1 处孤儿号删号留事实)+ `test/host/net_socket/net_socket_test.c` 注释 1 处;孤儿号(F 前缀 + 模块码段 + 数字序号的三段形态;§7 从无定义行)删号留事实、不补定义;13 个旧号标 `retired-to-phrase`。刻意不动:§7 编号列(历史对照)、`BSD_Socket_API_使用指南.md` 变更记录行、`docs/硬件平台/` 位号、Mermaid 节点名。`scripts/archive/id_gate/id_registry.json` FEAT `cursor_note` 改记停发口径(三模块各有最高号 → 不冻结游标的理由写在里面)。零代码语义变更。 | | 2026-10-27 | **停发机械化落地:34 个 `TC-HOST-*` 子族游标冻结,`docs/编号规范.md` §8 校验 5 开始咬新配的 TC 号** | 上一笔把缺口登记为「停发今天只有规范效力」并写明机械化怎么做;本笔照它落地、把话兑现:`scripts/archive/id_gate/id_registry.json` 37 个 TC 类族全部 `frozen: true`,34 个子族的 `cursor` 冻结在裁定日存量最高号(字符串形态——整型比较静默不生效;5 个低于存量的已抬:`TC-PROTELEM-013→015`、`TC-SYSLOG-108→137`、`TC-ADCHEALTH-011→023`、`TC-ADCCAL-017→023`、`TC-I104SRV-041→053`),理由记在顶层 `tc_freeze_2026_10_27`。探针(Checker `_check_frozen`):在 `TC-PROTSET-` 段存量最高号之上再加一号 → 命中 1 条校验 5,写存量最高号本身 → 零误伤;`check_ids.py --only 5` = 0 处;plain 与 `--strict` 的错误级 findings 与本笔前逐条相同(**12 条 `TC-TIMESYNC-0xx` 悬空引用属另一道在飞的 time_sync 改动,不在本笔写域,也没替它改**);台账 0 条、可判定 87.67%、不可判定 979 / 上限 1,166,不动 §8.1。**没有把主族 `TC` 说成已冻结**:它 `cursor` 仍为 `null`,`docs/编号规范.md` §4.1 框内第三条与 §9.1 末段把这块空白及其兜底(校验 3 + 冻结水位 564/474/79 只减不增 + 评审)写明,并规定「给这些模块补号即使在文档里补了定义行也算违令」。§9.1 末段由「效力边界」改写为「机器口径已落地」,当日实测留作历史不抹。零代码、零编号增删。 | -| 2026-10-27 | **停发口径收口:`TC-*` 从『允许继续发号』表整行移出,并登记「机器面还没冻结」这个缺口** | 裁定上一笔已入档,但效力写在了会被扫表读过的地方:`TC-*` 仍占着「允许继续发号」表第一行、用途列还写着「要进 C 断言标签」,那句"注意它已停发"只是表前的脚注;而那张表连表头行都在早先瘦身时丢了(GFM 里表格不能紧跟段落,整张塌成正文)。本笔:① 移出该行、补回表头与空行,『允许继续发号』写成**恰好 7 行**;② 表下加防误读框,把「不做了」的两条误读各钉一次——「维持原状所以还能发」与「停发所以顺手清掉/复用号」,并写明唯一重启入口 = 先裁定再回本节改表;③ 实测登记效力边界:registry 37 个 TC 类族仍有 35 个 `frozen: false` 带活游标,`docs/编号规范.md` §8 第 5 项碰不到它们(且 `cursor` 为空时该校验直接跳过),所以停发今天只有规范效力,机械化单独开卡走 §7.3;④ `docs/编号规范.md` §5.1 补「不在 7 行内第 ① 步就走不通」、§9.1 两条硬口径扩成三条(新增「停发 ≠ 待清」)并补效力边界段、§9.2 计数 8 → 7。同步:`AGENTS.md` 索引行、`docs/测试说明/测试文档模板规范.md` §6.3、`docs/门禁说明/host-unit-tests.md` §7 号段行(那里原文写着「新增用例要带号」,是最直接的误读源头)。零代码、零编号增删。 | +| 2026-10-27 | **停发口径收口:`TC-*` 从『允许继续发号』表整行移出,并登记「机器面还没冻结」这个缺口** | 裁定上一笔已入档,但效力写在了会被扫表读过的地方:`TC-*` 仍占着「允许继续发号」表第一行、用途列还写着「要进 C 断言标签」,那句"注意它已停发"只是表前的脚注;而那张表连表头行都在早先瘦身时丢了(GFM 里表格不能紧跟段落,整张塌成正文)。本笔:① 移出该行、补回表头与空行,『允许继续发号』写成**恰好 7 行**;② 表下加防误读框,把「不做了」的两条误读各钉一次——「维持原状所以还能发」与「停发所以顺手清掉/复用号」,并写明唯一重启入口 = 先裁定再回本节改表;③ 实测登记效力边界:registry 37 个 TC 类族仍有 35 个 `frozen: false` 带活游标,`docs/编号规范.md` §8 第 5 项碰不到它们(且 `cursor` 为空时该校验直接跳过),所以停发今天只有规范效力,机械化单独开卡走 §7.3;④ `docs/编号规范.md` §5.1 补「不在 7 行内第 ① 步就走不通」、§9.1 两条硬口径扩成三条(新增「停发 ≠ 待清」)并补效力边界段、§9.2 计数 8 → 7。同步:`AGENTS.md` 索引行、`docs/测试说明/流程与规范/测试文档模板规范.md` §6.3、`docs/门禁说明/host-unit-tests.md` §7 号段行(那里原文写着「新增用例要带号」,是最直接的误读源头)。零代码、零编号增删。 | | 2026-10-27 | **批次三裁定「不做」:`TC-*` 保留现状但即日停发** | 用户原话「批次三,不坐」(即不做)。裁定写进 §9.1 批次三(含理由与两条硬口径)、`docs/编号规范.md` §4.1『已停发』栏加一行、§9 结果表同步。停发的硬口径:游标冻结、现存号只减不增、**新用例一律用语义化测试函数名 + 文档表格行名,不再配 `TC-` 号**;真要清则先让追溯器同时认新旧两种形态、核对通过后单独开卡,不许先改文档再改代码(会造悬空号)。留着的判据依据:`TC-*` 是 `docs/编号规范.md` §4.1 那条判据(有脚本按字面量匹配)唯一真满足的族,字母号的痛在「人读」侧,解法是不再造给人读的号,而不是拆掉机器面的把手。 | | 2026-10-27 | **语义标识定为唯一默认形态;编号收窄为「机器按字面量匹配」的例外,并首次给出现量清点与三批计划** | 用户原话:「不要用字母加数字的编号,简直太难以理解了,语义标识是最好的」。本笔:① 标题下的一句话从「允许用号的族只有 8 个」改成「语义标识是唯一默认、编号是例外」,并把 `docs/编号规范.md` §4.1 拆成『允许继续发号』8 族与『已停发、存量待清』4 族(`N-*` / `TM-*` / 台架阶段裸形 / `F-*`)——原表自称穷举,实际漏登记了这三类在用族,属真缺陷。② 新增 §9 存量清点(用门禁自身接口实测:26 族仍有引用、565 个字面量、1,108 个引用站点)与三批计划:批次一 62 站点不碰门禁即可清、批次二保护功能号 184 站点转功能名、批次三 `TC-*` 561 站点需先换追溯机制(等用户裁定)。③ §8.1 基线按 2026-10-27 复测重打:784 文件 / 7,828 字面量、护栏 2 实跑 1,161 / 上限 1,166。 | | 2026-10-26 | **编号治理收口:清死号 → 停发活号 → 本文重写为短版(用户三次裁定)** | 全仓字母+数字编号 10,956 → 8,230 处。① **清死号**:属主登记处已删或从未启用的号一律就地删号留事实、禁补号(文本实删约 1,557 处)。② **停发活号**:登记簿 `N-x`/`S-x`/`T-x`、专项(A 前缀 + 数字)、已删报告的 UI 簇(字母 U 紧跟一位数字,区间两端即该簇首尾两枚)共 20 个号转成语义短语(约 418 处)——登记簿表首格就是短语,旧号进 `scripts/archive/id_gate/id_aliases.json` 标 `retired-to-phrase`;已销项的死号**故意不进别名表**,让门禁继续咬残留引用。③ **本文瘦身**:619 行 → 229 行,删掉八原则长表、迁移映射表、模块码表与门禁细节(那些各有事实源:registry / 别名表 / `docs/门禁说明/id-check.md`),改成「先问三句再决定要不要发号」+ `docs/编号规范.md` §4.1 允许用号的族**穷举 = 8 个**。④ **门禁配套**:`check_ids.py` 加变更记录行豁免与第二根护栏 `undecidable_total_ceiling`(比值会被清号动作稀释,绝对数不会),债务台账还清到 0 条 → `--strict` 实为全量拦截,比例基线重打为 86.0%。**本表按用户 2026-10-26 的明确指示只保留最近一条**,更早沿革看 `git log` 与 `docs/门禁说明/id-check.md` §7.5(含其后的方案 B 一节);这是**本文档的例外**,不改变 `docs/编号规范.md` §5.5对其他文档「冻结历史不回改」的约束。 | diff --git a/scripts/check_test_coverage.py b/scripts/check_test_coverage.py index 73173786..4607fc88 100644 --- a/scripts/check_test_coverage.py +++ b/scripts/check_test_coverage.py @@ -24,7 +24,7 @@ r""" - **Windows 原生侧没有 gcc / clang / gcov / lcov / gcovr**(全盘扫 0 处)→ gcov 那条最主流的路在 Windows 侧走不通。**但 WSL2 Ubuntu 里有 gcc/gcov 15.2.0**,实测 16 套单测在 gcc 下全部编过、 gcov -b -c 还给出分支覆盖——不用它当默认是因为**换编译器=换分母**(sha256.c:gcc 105 行 vs - MSVC 114 行),详见 docs/测试说明/主机单测覆盖率口径.md §2.1 的决策记录。 + MSVC 114 行),详见 docs/测试说明/单元测试/主机单测覆盖率口径.md §2.1 的决策记录。 - **MSVC 14.51(VS 2026/18)已不认 /coverage**:cl 只报 warning D9002「忽略未知选项」, 然后**照常编译成功** → 拿它做覆盖率等于静默出假数据,绝不可用(/fsanitize=coverage 同)。 - Team Tools\Dynamic Code Coverage Tools\CodeCoverage.exe(17.0)还在但已 deprecated, @@ -34,7 +34,7 @@ r""" MSVC 原生 exe + PDB,且**子进程退出码原样透传**(实测子进程 return 3 → collect 也返回 3)。 - 结论:编译期插桩这条路在本机是断的,走**加载期动态插桩**(mscoverage collect)。 -口径(一句话版,完整版见 docs/测试说明/主机单测覆盖率口径.md): +口径(一句话版,完整版见 docs/测试说明/单元测试/主机单测覆盖率口径.md): 行覆盖 = 至少执行过一次的可执行行 / 被插桩的可执行行; 函数覆盖 = 至少有一行命中的函数 / 被插桩的函数; 统计面 = 自研生产源码(App/**、Drivers/BSP/** 的 .c/.h),**不含**测试单元自身、 @@ -73,7 +73,7 @@ r""" - **PDB 里的源路径大小写会漂**(盘符、VS 根),比对前先按仓库实际拼写归一,否则同一文件 在基线里裂成两份。 -设计依据:docs/测试说明/主机单测覆盖率口径.md +设计依据:docs/测试说明/单元测试/主机单测覆盖率口径.md 创建日期:2026-10-23 """ @@ -440,7 +440,7 @@ def write_baseline(path, modules, files, totals, tested_sources, untested): payload = { "schema": BASELINE_SCHEMA, "generated_by": "scripts/check_test_coverage.py --update-baseline", - "note": "主机单测覆盖率基线。口径与工具链限制见 docs/测试说明/主机单测覆盖率口径.md。" + "note": "主机单测覆盖率基线。口径与工具链限制见 docs/测试说明/单元测试/主机单测覆盖率口径.md。" "门禁判据:files[].lines_covered 与 funcs_covered 只增不减,下降即拦提交。", "totals": totals, "modules": modules, @@ -523,7 +523,7 @@ def diff_baseline(baseline, modules, files, totals, full_run): # -------------------------------------------------------------------------- def print_report(modules, files, totals, untested, generated, notes, regress, verbose): - print("=== 主机单测覆盖率(口径:docs/测试说明/主机单测覆盖率口径.md)===") + print("=== 主机单测覆盖率(口径:docs/测试说明/单元测试/主机单测覆盖率口径.md)===") print("") print("--- 各套单测(插桩运行)---") for name in sorted(modules): @@ -584,7 +584,7 @@ def write_markdown(path, modules, files, totals, untested, notes, regress): "# 主机单测覆盖率报告", "", "> 由 " + code("scripts/check_test_coverage.py") + " 生成;口径、工具链限制与盲区见 " - + code("docs/测试说明/主机单测覆盖率口径.md") + "。本报告是一次性快照,重跑即覆盖。", + + code("docs/测试说明/单元测试/主机单测覆盖率口径.md") + "。本报告是一次性快照,重跑即覆盖。", "", "## 总计", "", @@ -689,7 +689,7 @@ def run(args): # 中间产物根:**跟着工作树走**,与主机单测同一个家(task-10)。旧写法是 # tempfile.gettempdir()/dtu_test_cov —— 全机一个名字,多棵工作树并行跑覆盖率就 - # 互相覆盖 exe/PDB/cov 文件(docs/测试说明/主机单测覆盖率口径.md 里"并行期每人 + # 互相覆盖 exe/PDB/cov 文件(docs/测试说明/单元测试/主机单测覆盖率口径.md 里"并行期每人 # 只跑 --module 自己模块"那条规避,就是为了绕开它;分家之后不再需要)。 # 复用 harness 的同一套判据(含 DTU_HOST_BUILD 覆盖),避免两处口径漂移。 _host_build_root = getattr(harness, "host_build_root", None) diff --git a/scripts/check_test_suite.py b/scripts/check_test_suite.py index efaf1b4a..43a1e983 100644 --- a/scripts/check_test_suite.py +++ b/scripts/check_test_suite.py @@ -37,7 +37,7 @@ & '.venv\\Scripts\\python.exe' scripts/check_test_suite.py --allow-test-build & '.venv\\Scripts\\python.exe' scripts/check_test_suite.py --file <路径> -设计依据:docs/任务规划/登记簿.md;docs/测试说明/测试开发标准流程.md §3.1 +设计依据:docs/任务规划/登记簿.md;docs/测试说明/流程与规范/测试开发标准流程.md §3.1 创建日期:2026-10-01 """ diff --git a/scripts/check_test_traceability.py b/scripts/check_test_traceability.py index 07382429..e7afc3b2 100644 --- a/scripts/check_test_traceability.py +++ b/scripts/check_test_traceability.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """check_test_traceability.py - 用例追溯校验(默认仅告警,不阻断提交)。 -背景(docs/测试说明/实机测试实施指南.md §8.2;原复审项 S4,已闭环): +背景(docs/测试说明/板级测试/实机测试实施指南.md §8.2;原复审项 S4,已闭环): 文档声称 91 个 TC、代码有 222 个 TEST_CHECK(断言点数 > 用例数正常), 但**双向是否一一对应无人校验**——某个 TC 可能"文档写了、代码没实现", 或"代码实现了、文档没登记"。纯靠人肉比对。 @@ -12,7 +12,8 @@ ① 代码侧:`test/board/*.c`(含 `*_test_task.c` 与 `net_latency_test.c`) 里出现的 `TC--`(注释、DBG_INFO 串皆计入); - ② 文档侧:`docs/测试说明/*_Test_Guide.md` 里出现的 `TC--`。 + ② 文档侧:`docs/测试说明/**/*_Test_Guide.md` 里出现的 `TC--` + (2026-10-30 测试说明目录分层后改**递归**匹配,板级指南现居 `板级测试/`)。 [DOC-ONLY] 文档有、代码无 -> 未实现(或代码未标注) [CODE-ONLY] 代码有、文档无 -> 未登记(或文档漏写) @@ -41,7 +42,7 @@ & '.venv\\Scripts\\python.exe' scripts/check_test_traceability.py --strict & '.venv\\Scripts\\python.exe' scripts/check_test_traceability.py --verbose -设计依据:docs/测试说明/实机测试实施指南.md §8.2(S4 用例追溯,原复审项已闭环) +设计依据:docs/测试说明/板级测试/实机测试实施指南.md §8.2(S4 用例追溯,原复审项已闭环) 创建日期:2026-10-03 """ @@ -189,11 +190,14 @@ def main(): host_dir = REPO_ROOT / "test" / "host" code_files = sorted(code_dir.glob("*.c")) if code_dir.is_dir() else [] - doc_files = sorted(doc_dir.glob("*_Test_Guide.md")) if doc_dir.is_dir() else [] + # 2026-10-30:docs/测试说明 按用途分了子目录(板级测试/ 单元测试/ …,见 + # docs/测试说明/README.md),文档侧一律**递归**找,否则分层等于静默放行—— + # 这里若还是 glob 单层,doc_files 会变成空表并直接 return 2(门禁瞎掉)。 + doc_files = sorted(doc_dir.rglob("*_Test_Guide.md")) if doc_dir.is_dir() else [] if not args.board_only: # 主机侧单测一侧:7 篇「单元测试说明.md」+ test/host 下的测试代码(*.c / *_test.py / # run_unit_test.py)——TC 编号在两侧都是**追溯链的锚点**,缺一侧就是断链。 - doc_files += sorted(doc_dir.glob("*单元测试说明.md")) + doc_files += sorted(doc_dir.rglob("*单元测试说明.md")) if host_dir.is_dir(): code_files += sorted(host_dir.rglob("*.c")) code_files += sorted(host_dir.rglob("*.py")) @@ -202,7 +206,7 @@ def main(): print(f"[ERR] 未找到代码侧文件:{code_dir}/*.c", file=sys.stderr) return 2 if not doc_files: - print(f"[ERR] 未找到文档侧文件:{doc_dir}/*_Test_Guide.md", file=sys.stderr) + print(f"[ERR] 未找到文档侧文件:{doc_dir}/**/*_Test_Guide.md", file=sys.stderr) return 2 code_ids, code_counts, code_intents = collect(code_files, "code", want_intent=True) diff --git a/scripts/ci_local.py b/scripts/ci_local.py index ce605e7e..d6ff9020 100644 --- a/scripts/ci_local.py +++ b/scripts/ci_local.py @@ -19,7 +19,7 @@ **fail-closed**:没有体积同码凭证、或代码与测量不同码即红——不再"没跑=通过"。 CI 侧的「体积门禁」步跑的是同一条实现(那条无需 Keil,见 .gitea/workflows/ci.yml)。 主机侧纯逻辑单测(host-unit) = `test/host/**/run_unit_test.py` - 覆盖率口径与盲区 → docs/测试说明/主机单测覆盖率口径.md + 覆盖率口径与盲区 → docs/测试说明/单元测试/主机单测覆盖率口径.md (旧旗标 `--coverage` 的独立一步已并入 manual 段:跑的是**同一根** pre-commit 钩子 test-coverage,与 CI 逐字同口径,不再重复跑一遍插桩) @@ -56,7 +56,7 @@ & '.venv\\Scripts\\python.exe' scripts/ci_local.py --keep-going # 失败也继续跑完 & '.venv\\Scripts\\python.exe' scripts/ci_local.py --commits 20 # 提交信息校验条数 -设计依据:`.gitea/workflows/ci.yml`;docs/测试说明/测试开发标准流程.md §9 +设计依据:`.gitea/workflows/ci.yml`;docs/测试说明/流程与规范/测试开发标准流程.md §9 创建日期:2026-10-01 """ @@ -553,7 +553,7 @@ def run_manual_stage(): print("[SUMMARY] manual: {} -- rc={} {}".format(hook, rc, verdict[-90:])) if hook == "test-coverage" and rc == 2: print(" (rc 2 = 环境错误:多半没装 VS 的「代码覆盖率工具」组件,或需设") - print(" DTU_MS_COVERAGE。口径与排障 → docs/测试说明/主机单测覆盖率口径.md)") + print(" DTU_MS_COVERAGE。口径与排障 → docs/测试说明/单元测试/主机单测覆盖率口径.md)") elif hook == "test-coverage" and rc == 1: print(" (rc 1 = 有单测失败,或已覆盖行/函数相对基线回退;确认无误后") print(" 跑 scripts/check_test_coverage.py --update-baseline 重登基线)") @@ -700,7 +700,7 @@ def run_host_unit_tests(args): print("[FAIL] {}(退出码 {})".format(rel, rc)) if rc == 2: print(" (退出码 2 = 环境错误:多半是本机未装 MSVC,见 " - "docs/测试说明/测试开发标准流程.md §4.2)") + "docs/测试说明/流程与规范/测试开发标准流程.md §4.2)") rc_all = 1 if not args.keep_going: break diff --git a/scripts/rename_maps/batch-lprot-semantic.json b/scripts/rename_maps/batch-lprot-semantic.json index e4d0eca1..c600aa78 100644 --- a/scripts/rename_maps/batch-lprot-semantic.json +++ b/scripts/rename_maps/batch-lprot-semantic.json @@ -6,8 +6,8 @@ "new": "周期 CONVST 重触发", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -30,8 +30,8 @@ "new": "TPAFE 快照消费", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -54,8 +54,8 @@ "new": "STM32 ADC1 启动与扫描", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -78,8 +78,8 @@ "new": "通道语义映射", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -102,8 +102,8 @@ "new": "通道标定(一次系数 + 零漂)", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -126,8 +126,8 @@ "new": "采样有效性校验", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -150,8 +150,8 @@ "new": "等周波采样(软件测频 + 调频闭环)", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -174,8 +174,8 @@ "new": "二次谐波/五次谐波提取入口", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -198,8 +198,8 @@ "new": "全周傅氏系数表", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -222,8 +222,8 @@ "new": "基波相量实例", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -246,8 +246,8 @@ "new": "相量有效值输出", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -270,8 +270,8 @@ "new": "相位输出", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -294,8 +294,8 @@ "new": "线/负序/零序合成", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -318,8 +318,8 @@ "new": "每 1 ms 滑动窗刷新", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -342,8 +342,8 @@ "new": "双区指针原子交换", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -366,8 +366,8 @@ "new": "三段式相间过流", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -390,8 +390,8 @@ "new": "三段式零序过流", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -414,8 +414,8 @@ "new": "过频 / 低频", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -438,8 +438,8 @@ "new": "跳闸出口(KO)", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -462,8 +462,8 @@ "new": "出口自检", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -486,8 +486,8 @@ "new": "SOE 记录", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -510,8 +510,8 @@ "new": "动作记录", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -534,8 +534,8 @@ "new": "定值校验和", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", @@ -558,8 +558,8 @@ "new": "自检失败闭锁", "files": [ "docs/算法/继电保护功能复现规划.md", - "docs/测试说明/boot_log_data/README.md", - "docs/测试说明/相量层单元测试说明.md", + "docs/测试说明/测试数据/boot_log_data/README.md", + "docs/测试说明/单元测试/相量层单元测试说明.md", "docs/硬件平台/ADC通道映射说明.md", "App/algo/*.c", "App/algo/*.h", diff --git a/scripts/rename_maps/batch3-trap.json b/scripts/rename_maps/batch3-trap.json index 35d37ed3..2b5488ff 100644 --- a/scripts/rename_maps/batch3-trap.json +++ b/scripts/rename_maps/batch3-trap.json @@ -12,7 +12,7 @@ "files": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", "docs/问题记录/项目审查与优化建议报告.md", - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", "Drivers/BSP/GD5F2GQ5UE/nand_ftl.c", @@ -26,7 +26,7 @@ "old": "陷阱 (?P\\d{2})\\b", "new": "TRAP-GD5F-{n:02d}", "files": [ - "docs/测试说明/GD5F2GQ5UE_Test_Guide.md" + "docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md" ], "note": "同一属主的中文形「见陷阱 01」→ 与空格形合并成同一个号" }, diff --git a/scripts/rename_maps/batch8-s-review-dead.json b/scripts/rename_maps/batch8-s-review-dead.json index d4f75087..be950be0 100644 --- a/scripts/rename_maps/batch8-s-review-dead.json +++ b/scripts/rename_maps/batch8-s-review-dead.json @@ -3,12 +3,12 @@ "batch": "批次四(2026-10-27 实测清点):复审残号 S-REVIEW + 两条无主死号的残留引用收口(删号留事实)", "applied_by": "scripts/rename_ids.py --no-alias", "record": "docs/编号规范.md §4.1.1(复审残号 S1~S14 / E-xx → 写条目本身)、§4.5、§7.3", - "note": "只清「号当标识用」的标注与待办用法;别名表**故意不写**:这些裸形(S1/S4/S5/S7/S9/S11)在 .c/.h 注释、.pre-commit-config.yaml 与在飞的 docs/测试说明/自动化测试流程.md 里还有活引用,写进别名表等于把那些残留一起洗成「已解析」(§4.1.1:部分死号故意不进别名表,好让门禁继续咬残留引用)。刻意不碰:① 属主登记处 docs/任务规划/测试与架构专项.md(§2.1 S12 定义行 + 首行指针;删行销项属 Ask-first);② 变更记录行与「原复审项 S4,已闭环」这类显式历史标注;③ 任何 .c/.h(改注释也要重跑 @build,本批零代码);④ 工作区里别人在飞的脏文件;⑤ 实机测试实施指南.md:5「(S7、A1~A4)」——A1~A4 与本文 A 表(前置检查 A2~A6)同形、语义待属主确认,按 §7.3 第 3 条不猜。", + "note": "只清「号当标识用」的标注与待办用法;别名表**故意不写**:这些裸形(S1/S4/S5/S7/S9/S11)在 .c/.h 注释、.pre-commit-config.yaml 与在飞的 docs/测试说明/流程与规范/自动化测试流程.md 里还有活引用,写进别名表等于把那些残留一起洗成「已解析」(§4.1.1:部分死号故意不进别名表,好让门禁继续咬残留引用)。刻意不碰:① 属主登记处 docs/任务规划/测试与架构专项.md(§2.1 S12 定义行 + 首行指针;删行销项属 Ask-first);② 变更记录行与「原复审项 S4,已闭环」这类显式历史标注;③ 任何 .c/.h(改注释也要重跑 @build,本批零代码);④ 工作区里别人在飞的脏文件;⑤ 实机测试实施指南.md:5「(S7、A1~A4)」——A1~A4 与本文 A 表(前置检查 A2~A6)同形、语义待属主确认,按 §7.3 第 3 条不猜。", "batches": [ { "family": "S-REVIEW", "files": [ - "docs/测试说明/链路延迟测试说明.md" + "docs/测试说明/专项验证/链路延迟测试说明.md" ], "old": "基线行为;可选优化 (?PS7)(poll 前置 \\+ while 排空),低优先", "new": "基线行为;可选优化(poll 前置 + while 排空),低优先", @@ -17,7 +17,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/链路延迟测试说明.md" + "docs/测试说明/专项验证/链路延迟测试说明.md" ], "old": "其余待办 (?PS9)(按键后立即取帧", "new": "其余待办(按键后立即取帧", @@ -26,7 +26,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/链路延迟测试说明.md" + "docs/测试说明/专项验证/链路延迟测试说明.md" ], "old": "^4\\. \\*\\*(?PS1)\\*\\* 超时参数分档", "new": "4. 超时参数分档", @@ -35,7 +35,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/链路延迟测试说明.md" + "docs/测试说明/专项验证/链路延迟测试说明.md" ], "old": "^6\\. \\*\\*(?PS4)\\*\\* 发送块配额与 MSS", "new": "6. 发送块配额与 MSS", @@ -44,7 +44,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/链路延迟测试说明.md" + "docs/测试说明/专项验证/链路延迟测试说明.md" ], "old": "^7\\. \\*\\*(?PS5)\\*\\* 去掉一次 3200B 拷贝", "new": "7. 去掉一次 3200B 拷贝", @@ -53,7 +53,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/链路延迟测试说明.md" + "docs/测试说明/专项验证/链路延迟测试说明.md" ], "old": "^8\\. \\*\\*(?PS7)\\*\\* uiTask:", "new": "8. uiTask:", @@ -62,7 +62,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/实机测试实施指南.md" + "docs/测试说明/板级测试/实机测试实施指南.md" ], "old": "堆低水位告警实测(P1-B / (?PS11))", "new": "堆低水位告警实测(P1-B)", @@ -71,7 +71,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/实机测试实施指南.md" + "docs/测试说明/板级测试/实机测试实施指南.md" ], "old": "GD5F 错误通道回归(P2-A / (?PS9))", "new": "GD5F 错误通道回归(P2-A)", @@ -80,7 +80,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/实机测试实施指南.md" + "docs/测试说明/板级测试/实机测试实施指南.md" ], "old": "工程卫生(P3 / (?PS5) \\+ S4 \\+ 待核实项)", "new": "工程卫生(P3 + 待核实项)", @@ -89,7 +89,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/实机测试实施指南.md" + "docs/测试说明/板级测试/实机测试实施指南.md" ], "old": "含新增 (?PS5) `test-cppcheck`", "new": "含新增 `test-cppcheck`", @@ -107,7 +107,7 @@ { "family": "S-REVIEW", "files": [ - "docs/测试说明/存储维护与容量恢复.md" + "docs/测试说明/专项验证/存储维护与容量恢复.md" ], "old": "自检台账清零,重建 (?PS7) 审计基线", "new": "自检台账清零,重建联合判定审计基线", @@ -116,7 +116,7 @@ { "family": "S-LDG", "files": [ - "docs/测试说明/boot_log_data/README.md" + "docs/测试说明/测试数据/boot_log_data/README.md" ], "old": "本流程立项:原 `../../任务规划/README\\.md` (?PS-2)(2026-09-22 提出", "new": "本流程立项:原 `../../任务规划/README.md` 的「启动日志固化流程」条目(2026-09-22 提出", @@ -125,7 +125,7 @@ { "family": "E-AUD", "files": [ - "docs/测试说明/m2_data/README.md" + "docs/测试说明/测试数据/m2_data/README.md" ], "old": "(`--ftp-stress`,(?PE-02) 复现)", "new": "(`--ftp-stress` 复现)", diff --git a/scripts/rename_ref.py b/scripts/rename_ref.py index 572b0b96..ce012e67 100644 --- a/scripts/rename_ref.py +++ b/scripts/rename_ref.py @@ -39,6 +39,14 @@ import subprocess import sys import urllib.parse +# 控制台编码兜底(同 check_ids.py / check_doc_links.py / check_test_traceability.py): +# 裸跑环境的代码页常是 936(GBK),而本脚本收尾提示里有 `ℹ` → print 抛 UnicodeEncodeError。 +# 偏偏那时 **文件已经 git mv + 引用改写落盘**,于是脚本带 traceback 退出 1: +# 退出码与真实结果相反(2026-10-30 一次挪 28 个路径实测,28 次全是「做完了却报 1」)。 +for _stream in (sys.stdout, sys.stderr): + if hasattr(_stream, "reconfigure"): + _stream.reconfigure(encoding="utf-8", errors="replace") + REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent # 不扫描的路径片段(第三方 / 生成物 / 本地状态) diff --git a/scripts/stack_tolerance.tsv b/scripts/stack_tolerance.tsv index dbb1195f..abd26955 100644 --- a/scripts/stack_tolerance.tsv +++ b/scripts/stack_tolerance.tsv @@ -2,7 +2,7 @@ # docs/内存管理/RAM使用分析与优化方案.md §4.0.6 第③条;用法:scripts/stack_gate.py。 # # 容差是**推导值不是拍的**:tol(task) = 向上取整到 16 B 格的 max(128 B, 2 x 同镜像实测最大摆动)。 -# 实测来源(台架原始日志在 docs/测试说明/boot_log_data/): +# 实测来源(台架原始日志在 docs/测试说明/测试数据/boot_log_data/): # 2026-10-26 task-30(同一份 1d4b6a17 像、4 圈仅复位):uiTask 4116~4188 = 72 B、adcTask 80 B # 2026-10-27 task-42(HEAD 像、4 圈仅复位):全部任务零摆动 # -> 最大同镜像摆动 80 B => tol = max(128, 160) = **160 B**,全任务统一。 diff --git a/scripts/test_coverage_baseline.json b/scripts/test_coverage_baseline.json index 580621ca..2e5d16e4 100644 --- a/scripts/test_coverage_baseline.json +++ b/scripts/test_coverage_baseline.json @@ -780,7 +780,7 @@ "ok": true } }, - "note": "主机单测覆盖率基线。口径与工具链限制见 docs/测试说明/主机单测覆盖率口径.md。门禁判据:files[].lines_covered 与 funcs_covered 只增不减,下降即拦提交。", + "note": "主机单测覆盖率基线。口径与工具链限制见 docs/测试说明/单元测试/主机单测覆盖率口径.md。门禁判据:files[].lines_covered 与 funcs_covered 只增不减,下降即拦提交。", "schema": 1, "tested_sources": [ "App/algo/adc_cal.c", diff --git a/scripts/v5_log_gap_report.py b/scripts/v5_log_gap_report.py index a630d1bd..b6ccffc1 100644 --- a/scripts/v5_log_gap_report.py +++ b/scripts/v5_log_gap_report.py @@ -7,7 +7,7 @@ - 「无源 vs 真停滞」判别:docs/子系统设计/控制台单写者日志设计说明.md 文末附录 (日志静默观察项与单写者化的合并评估,2026-10-25)——静默段贴边(前一行 / 结束后一窗)命中 「丢弃账 / 故障账」留痕行 = 真停滞嫌疑;零命中 = 无源(系统安静,正常形态)。 -- 开机良性豁免:docs/测试说明/实机测试实施指南.md §9 第 8 条——开机屏障期 +- 开机良性豁免:docs/测试说明/板级测试/实机测试实施指南.md §9 第 8 条——开机屏障期 (reset cause / armed / netTask: started 等锚点后一窗)偶见的单抽样 MISS start 属固有交错;且自 v1.1 起 MISS start 整体降级为**诊断行**(复合缺席边沿,不代表 停喂,v2-on-ui 看门狗 v1.5 按位分账语义)——违规判定只看 task stall 行与 @@ -39,7 +39,7 @@ v1.1(2026-10-25,道F task-22 / 大窗判读 F1):违规口径 = stall>0 MISS 计违规,经 2026-10-25 台架 70min 窗逐窗归因属收紧过头,予以纠正)。stall 行 语义随看门狗 v1.5 按位分账变化(行文本不变):每行 = 同一任务 800ms 单串,见 docs/子系统设计/看门狗设计说明.md §5.3/§6.1;使用文档 -docs/测试说明/实机测试实施指南.md §7.2。 +docs/测试说明/板级测试/实机测试实施指南.md §7.2。 """ import argparse diff --git a/simulator/README.md b/simulator/README.md index 066906ba..be53fbd2 100644 --- a/simulator/README.md +++ b/simulator/README.md @@ -117,7 +117,7 @@ LVGL 场景(同一份 ui_menu.c) | 业务任务 | netTask / ftpTask / timeSyncTask 等 | 无(仅编译纯软件部分的配置文件引擎 net_cfg/cfg_file,可离线验证配置加载/保存) | | 时钟 | `lv_tick_inc` 由 ui_task 手动喂(10ms 周期) | SDL 驱动内部 `lv_tick_set_cb(SDL_GetTicks)`,**不可再手动喂** | | UI 数据来源 | `App/app/ui_data_feed.c` 每轮从 phasor / prot_set / 104 点表…装配并发布三帧 | `main.c` 一次性发布**固定帧**(定值不手抄数字,取链进来的 `App/algo/prot_set.c` 出厂默认);口径 `docs/UI设计/UI_数据供给设计说明.md` §9.2 | -| 定值写路径(保存) | `ui_data_feed_tick()` 里 `ui_data_param_drain()` 落定 → 置脏 → defaultTask 写 `/prot_set.bin` | `sim_param_pump()` 用**同一份** `g_prot_set_meta` 上下限预检后落值到 RAM,**到此为止**:模拟器无 NAND,"重启值保持 / 主站 C_RD 读到同值"只能上板验(差距登记 `docs/测试说明/模拟器差距清单.md`) | +| 定值写路径(保存) | `ui_data_feed_tick()` 里 `ui_data_param_drain()` 落定 → 置脏 → defaultTask 写 `/prot_set.bin` | `sim_param_pump()` 用**同一份** `g_prot_set_meta` 上下限预检后落值到 RAM,**到此为止**:模拟器无 NAND,"重启值保持 / 主站 C_RD 读到同值"只能上板验(差距登记 `docs/测试说明/专项验证/模拟器差距清单.md`) | ### 2.4 关键设计决策 @@ -295,5 +295,5 @@ UI 改动的自动化门禁脚本(完整流程见 `docs/UI设计/UI_自动化 > **模拟器跑过 ≠ 真机跑过**:本目录与真机的**全部已知差异**(网络 pending 机制缺失、代次号恒 0、 > 日志/配置的 mtime 粒度与堆后端差异、IWDG/NAND/RTC 等硬件不可建模)统一登记在 -> [`../docs/测试说明/模拟器差距清单.md`](../docs/测试说明/模拟器差距清单.md)—— -> 改动触及 `sim/` 任何后端时,**必须同步在那里登记一行**;改动前先看 `docs/测试说明/模拟器差距清单.md` §3 判断是否必须回真机。 +> [`../docs/测试说明/专项验证/模拟器差距清单.md`](../docs/测试说明/专项验证/模拟器差距清单.md)—— +> 改动触及 `sim/` 任何后端时,**必须同步在那里登记一行**;改动前先看 `docs/测试说明/专项验证/模拟器差距清单.md` §3 判断是否必须回真机。 diff --git a/simulator/main.c b/simulator/main.c index b7af39dc..b870d878 100644 --- a/simulator/main.c +++ b/simulator/main.c @@ -1053,7 +1053,7 @@ static void sim_publish_data_frames(void) { /* 运行报告四数:模拟器**没有** boot_stats(依赖 SD2506 I2C 与 RCC_CSR,模拟器不编译 * 该模块)也没有 104 协议栈 → 填确定值假数据,只为像素黄金可复现;真机走 * App/app/ui_data_feed.c 的 boot_stats_get()/iec104_serv_get_stats() 真源。 - * 差异已登记 docs/测试说明/模拟器差距清单.md(2026-10-28 UI 补齐「运行报告」) */ + * 差异已登记 docs/测试说明/专项验证/模拟器差距清单.md(2026-10-28 UI 补齐「运行报告」) */ info.boot_ready = 1u; info.boot_count = 7u; info.boot_seq_state = 2u; /* 延续(自 RTC 电池周期起) */ @@ -1104,7 +1104,7 @@ static int sim_param_check(uint8_t a_id, int32_t a_q10) { * 限定条件:BSP 侧已整批预检通过 * 函数说明:真机在这里之后还有 defaultTask 扫脏写 /prot_set.bin 一段——模拟器没有 * NAND,跨复位保持这条只能在台架验(差距已登记在案,别把模拟器跑绿 - * 当成"保存能落盘"的证据 → docs/测试说明/模拟器差距清单.md) + * 当成"保存能落盘"的证据 → docs/测试说明/专项验证/模拟器差距清单.md) */ static int sim_param_apply(uint8_t a_id, int32_t a_q10) { if (a_id >= (uint8_t)PS_ID_COUNT) { diff --git a/simulator/sim/sim_syslog.c b/simulator/sim/sim_syslog.c index 4790b2dd..fabbda56 100644 --- a/simulator/sim/sim_syslog.c +++ b/simulator/sim/sim_syslog.c @@ -240,7 +240,7 @@ int syslog_request_clear(syslog_id_t id) { /* 成功才留痕(失败那次什么都没改),且跳过 oper.log 自己——理由见上面表头。 * 本端 syslog_post_quiet 等价于直写,所以这条操作记录在函数返回前就已落盘, * 与 MCU 端"下一轮 drain 才落"时序不同(两端差异已登记在 - * docs/测试说明/模拟器差距清单.md,task-4 那次也写在那里)。 */ + * docs/测试说明/专项验证/模拟器差距清单.md,task-4 那次也写在那里)。 */ if ((rc == 0) && ((uint32_t)id != (uint32_t)SYSLOG_OPER)) { syslog_post_quiet(SYSLOG_OPER, s_clear_rec[id]); } diff --git a/test/README.md b/test/README.md index 5a73aa9c..6a13bd37 100644 --- a/test/README.md +++ b/test/README.md @@ -56,7 +56,7 @@ ## 相关文档 -- `docs/测试说明/测试开发标准流程.md` — 测试验证分层与门禁决策表 -- `docs/测试说明/自动化测试流程.md` — `@test` 细节与失败模式 -- 各模块测试指南:`docs/测试说明/*_Test_Guide.md` -- `docs/测试说明/链路延迟测试说明.md` +- `docs/测试说明/流程与规范/测试开发标准流程.md` — 测试验证分层与门禁决策表 +- `docs/测试说明/流程与规范/自动化测试流程.md` — `@test` 细节与失败模式 +- 各模块测试指南:`docs/测试说明/板级测试/*_Test_Guide.md` +- `docs/测试说明/专项验证/链路延迟测试说明.md` diff --git a/test/board/README.md b/test/board/README.md index 223d186e..5b90d3ff 100644 --- a/test/board/README.md +++ b/test/board/README.md @@ -40,6 +40,6 @@ ## 相关文档 -- 测试指南:`docs/测试说明/CH395F_Test_Guide.md`、`GD5F2GQ5UE_Test_Guide.md`、`SD2506_Test_Guide.md`、`FTP_Test_Guide.md` +- 测试指南:`docs/测试说明/板级测试/CH395F_Test_Guide.md`、`GD5F2GQ5UE_Test_Guide.md`、`SD2506_Test_Guide.md`、`FTP_Test_Guide.md` - 套件配置:`AGENTS.md`「测试与验证」章 -- 容量恢复:`docs/测试说明/存储维护与容量恢复.md` +- 容量恢复:`docs/测试说明/专项验证/存储维护与容量恢复.md` diff --git a/test/board/ch395f_test.h b/test/board/ch395f_test.h index ef79bc22..c4fc233e 100644 --- a/test/board/ch395f_test.h +++ b/test/board/ch395f_test.h @@ -26,7 +26,7 @@ * Phase 12 | 硬件层 | 独立运行:SPI 字节命令 / DMA 时延基线(SPI_CMD/SPI_DMA,无需 PC) * Phase 13 | NET 层 | testTask:芯片 + 队列时延(CHUNK_WAIT~FRAME_RT/LOGTAX,需 PC peer,独立运行) * Phase 14 | NET 层 | testTask:生产路径时延(PROD_CYCLE~UI_LOOP + 模拟器 A/B,需 PC peer)〔M3 规划〕 - * 时延分段定义/判定基线/执行流程:docs/测试说明/链路延迟测试说明.md + * 时延分段定义/判定基线/执行流程:docs/测试说明/专项验证/链路延迟测试说明.md */ #ifndef CH395F_TEST_H @@ -42,7 +42,7 @@ extern "C" { /* * 阶段使能开关(取消注释即启用对应阶段) * - * 构建模式互斥(详见 docs/测试说明/CH395F_Test_Guide.md「构建模式与执行顺序」): + * 构建模式互斥(详见 docs/测试说明/板级测试/CH395F_Test_Guide.md「构建模式与执行顺序」): * 硬件层模式(阶段 1~5):netTask 入口自挂起(创建但不运行),testTask 独占 CH395F * NET 层模式 (阶段 6~11):完整网络栈,netTask 轮询 + testTask 监听循环 * @@ -66,10 +66,10 @@ extern "C" { * 连接无效,E11 实证);勿与 Phase 6/9/10/13 混选(recv 互抢数据)。 * ⚠ 说明写在**上一行**而不是挂在 #define 行尾:见本节末尾的"开关行注释规范" */ #define ENABLE_PHASE11_TESTS /* [网] KeepAlive 超时断开(判据见 CH395F_Test_Guide) */ -/* ---- 链路时延基线(M1;分段/阈值见 docs/测试说明/链路延迟测试说明.md)---- */ +/* ---- 链路时延基线(M1;分段/阈值见 docs/测试说明/专项验证/链路延迟测试说明.md)---- */ //#define ENABLE_PHASE12_TESTS /* [硬] SPI 字节命令 / DMA 时延基线(SPI_CMD/SPI_DMA,无需 PC)—— M1 已完成,基线见说明文档 §6.1 */ -//#define ENABLE_PHASE15_TESTS /* [硬] 自愈驱动原语:状态回读一致性/cmd_done/sock_reset 状态机跑通/链路缓存(无需 PC)——TC 详见 docs/测试说明/CH395F_Test_Guide.md 阶段 15;台架 21/21 PASS */ -/* ---- 链路时延(M2/M3;分段/阈值见 docs/测试说明/链路延迟测试说明.md)---- */ +//#define ENABLE_PHASE15_TESTS /* [硬] 自愈驱动原语:状态回读一致性/cmd_done/sock_reset 状态机跑通/链路缓存(无需 PC)——TC 详见 docs/测试说明/板级测试/CH395F_Test_Guide.md 阶段 15;台架 21/21 PASS */ +/* ---- 链路时延(M2/M3;分段/阈值见 docs/测试说明/专项验证/链路延迟测试说明.md)---- */ //#define ENABLE_PHASE13_TESTS /* [网] 芯片 + 队列时延(CHUNK_WAIT~FRAME_RT/LOGTAX,需 PC peer)—— M2 已完成,基线见说明文档 §6.2 */ /* [网] 生产路径时延(PROD_CYCLE~UI_LOOP + 模拟器 Δ)—— M3,需 peer --mode remo(:7003); * 与 Phase 11 共存安全:peer 缺席时有 LAT_P14_TIMEOUT_MS 整体超时,自动 done, diff --git a/test/board/ch395f_test_task.c b/test/board/ch395f_test_task.c index 3e58e763..7448de12 100644 --- a/test/board/ch395f_test_task.c +++ b/test/board/ch395f_test_task.c @@ -90,7 +90,7 @@ static void phase1_run(void) { * 通过:函数返回 CH395F_ERR_SUCCESS(0x00)= SPI 回显取反匹配。 * 失败:返回 CH395F_STATUS_NOT_DETECTED(0xFF)= SPI 通信异常或芯片未响应。 * - * 用例号:TC-NET-101(docs/测试说明/CH395F_Test_Guide.md §2 阶段 1「SPI 命令路径 + * 用例号:TC-NET-101(docs/测试说明/板级测试/CH395F_Test_Guide.md §2 阶段 1「SPI 命令路径 * 完整性」——该条目的各步就是本函数按序执行的九个测试项,项号见各项标注)。 */ { @@ -187,7 +187,7 @@ static void phase1_run(void) { * 失败:第二次读非 0x0000(测试期间出现新事件)。 * * 用例号:本项即原 TC-NET-102(全局中断状态一致性)。该条目在 2026-08-22 - * 文档重构时被删、而 docs/测试说明/CH395F_Test_Guide.md 附录 B 的 + * 文档重构时被删、而 docs/测试说明/板级测试/CH395F_Test_Guide.md 附录 B 的 * 汇总行遗留至今,故在此把号挂回实现体。 */ { diff --git a/test/board/gd5f_test.h b/test/board/gd5f_test.h index 3aa717a6..20f6d994 100644 --- a/test/board/gd5f_test.h +++ b/test/board/gd5f_test.h @@ -2,7 +2,7 @@ * 模块名称:GD5F2GQ5UE Driver Test Suite * 模块功能:GD5F2GQ5UE SPI NAND Flash 驱动测试入口,按阶段组织测试用例, * 覆盖 gd5f2gq5ue.c 全部公开/私有函数,并延伸到 FTL(nand_ftl)与 - * FatFS diskio。详见 docs/测试说明/GD5F2GQ5UE_Test_Guide.md。 + * FatFS diskio。详见 docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md。 * 适用平台:STM32F4 系列(GD5F2GQ5UE SPI NAND) * 作者:王建锋 * 创建日期:2026-08-26 diff --git a/test/board/net_latency_test.c b/test/board/net_latency_test.c index 6aa38c78..9a76bd19 100644 --- a/test/board/net_latency_test.c +++ b/test/board/net_latency_test.c @@ -3,7 +3,7 @@ * 模块功能:DWT CYCCNT 微秒时基 + 采样统计(min/med/p95/max/尖峰)+ [LAT] * 机器可读报告与 verdict;Phase 12(M1):SPI 字节命令 / DMA 时延 * 基线(SPI_CMD/SPI_DMA,硬件层模式,无需 PC)。分段定义与判定基线见 - * docs/测试说明/链路延迟测试说明.md。 + * docs/测试说明/专项验证/链路延迟测试说明.md。 * 适用平台:STM32F4 系列(CH395F) * 作者:王建锋 * 创建日期:2026-09-22 diff --git a/test/board/net_latency_test.h b/test/board/net_latency_test.h index b32413cb..bd68f1ae 100644 --- a/test/board/net_latency_test.h +++ b/test/board/net_latency_test.h @@ -5,7 +5,7 @@ * Phase 12(硬件层,M1):SPI 字节命令 / DMA 时延基线(SPI_CMD/SPI_DMA,无需 PC); * Phase 13/14(NET 层,M2/M3 规划):芯片发送握手 / 队列往返 / * 生产路径时延。分段定义、判定基线与执行流程见 - * docs/测试说明/链路延迟测试说明.md。 + * docs/测试说明/专项验证/链路延迟测试说明.md。 * 适用平台:STM32F4 系列(CH395F) * 作者:王建锋 * 创建日期:2026-09-22 diff --git a/test/board/net_test_task.c b/test/board/net_test_task.c index 04a15111..f173beae 100644 --- a/test/board/net_test_task.c +++ b/test/board/net_test_task.c @@ -494,7 +494,7 @@ static int32_t phase8_verify(uint8_t *buf, uint32_t size, uint32_t offset) { #endif /* 用例号:TC-NET-801(SEND 方向)与 TC-NET-802(RECV 方向)——两向由 - * PHASE8_DIRECTION 编译期切换,定义见 docs/测试说明/CH395F_Test_Guide.md + * PHASE8_DIRECTION 编译期切换,定义见 docs/测试说明/板级测试/CH395F_Test_Guide.md * 阶段 8(本函数体从未改过名,只是一直没挂上号,2026-10-21 核对补注)。 */ static void phase8_run(int32_t sockfd) { #if PHASE8_DIRECTION == PHASE8_DIR_RECV @@ -610,7 +610,7 @@ static void phase8_run(int32_t sockfd) { * 通过:select 检测到数据并成功回显。 * 失败:select 未检测到数据或回显失败。 * 用例号:TC-NET-901(单 Socket 就绪检测)与 TC-NET-902(超时返回 0), - * 定义见 docs/测试说明/CH395F_Test_Guide.md 阶段 9——本测试一直在, + * 定义见 docs/测试说明/板级测试/CH395F_Test_Guide.md 阶段 9——本测试一直在, * 只是从未挂上这两个号(2026-10-21 核对补注)。 * =================================================================== */ @@ -811,7 +811,7 @@ static void phase10_run(int32_t sockfd) { * 通过:从连接建立到 recv 返回 0 的间隔落在 10s~120s 有界窗 * (芯片定时语义与手册公式 75s 不符,实测判死 18~31s—— * 见《网络自愈架构设计》§5.2 E11 与 phase11_run 内判据注释)。 - * 用例号:TC-NET-1101(docs/测试说明/CH395F_Test_Guide.md 阶段 11 KeepAlive 触发断开)。 + * 用例号:TC-NET-1101(docs/测试说明/板级测试/CH395F_Test_Guide.md 阶段 11 KeepAlive 触发断开)。 * =================================================================== */ #ifdef ENABLE_PHASE11_TESTS diff --git a/test/board/sd2506_test_task.c b/test/board/sd2506_test_task.c index 6af8347a..adcf93b8 100644 --- a/test/board/sd2506_test_task.c +++ b/test/board/sd2506_test_task.c @@ -229,7 +229,7 @@ void sd2506_test_run(void) * 不再出现"Phase 2 显示的是含 Phase 1 的累计值"这种易误读输出; * 2) 末尾输出套件级 `=== RTC Tests: N/M PASSED (failed=0) ===` 汇总行—— * 它是 run_all_suites.py --require-suite-summary 的判定标记 - * (见 test_common.h / docs/测试说明/测试开发标准流程.md §3.2)。 */ + * (见 test_common.h / docs/测试说明/流程与规范/测试开发标准流程.md §3.2)。 */ uint16_t suite_total = 0U; uint16_t suite_passed = 0U; uint16_t suite_failed = 0U; diff --git a/test/board/test_common.h b/test/board/test_common.h index 0fde9eb7..26b01da6 100644 --- a/test/board/test_common.h +++ b/test/board/test_common.h @@ -6,7 +6,7 @@ * * 设计取舍:**统计变量仍按套件独立**(各套件持有自己的 `g_xxx_stats`), * 公共宏只提供"内核",由各套件用一行宏把它绑定到自己的统计变量。 - * 理由见 docs/测试说明/测试开发标准流程.md §3.2: + * 理由见 docs/测试说明/流程与规范/测试开发标准流程.md §3.2: * - 统计变量独立 = 防跨套件串数(历史约定,不能破); * - 内核共用 = 报告行格式/字段一处维护,改一次即全生效。 * diff --git a/test/board/test_config.h b/test/board/test_config.h index 59c2be1c..fb50672e 100644 --- a/test/board/test_config.h +++ b/test/board/test_config.h @@ -26,7 +26,7 @@ extern "C" { * ⚠️ 默认必须是**产品构建**(全部注释)——pre-commit 钩子 `test-suite-switch` 会拦截 * 未显式放行的测试构建(`--allow-test-build` / `ALLOW_TEST_BUILD=1`)。 * 跑套件回归时取消注释所需套件;跑完务必改回、或直接用 `test/run_all_suites.py` - * (自动改宏 + 结束后无条件还原)。详见 docs/测试说明/测试开发标准流程.md §3.1/§3.6。 */ + * (自动改宏 + 结束后无条件还原)。详见 docs/测试说明/流程与规范/测试开发标准流程.md §3.1/§3.6。 */ //#define TEST_SUITE_CH395F //#define TEST_SUITE_STORAGE //#define TEST_SUITE_GD5F @@ -54,7 +54,7 @@ extern "C" { * 创建"的旧疑点不成立(实测 RTC 套件正常执行;RTC 已计入下方析取,故 RTC 构建下本 * 标记亦置位、testTask 正常保留)。 * 4 个套件(含 RTC)在此补齐:若将来再引入"测试构建下 defaultTask 空闲"等分支而复用 - * 本标记,可避免重演"漏 RTC"的隐患。详见 docs/测试说明/实机测试实施指南.md §8.3。 */ + * 本标记,可避免重演"漏 RTC"的隐患。详见 docs/测试说明/板级测试/实机测试实施指南.md §8.3。 */ #if defined(TEST_SUITE_CH395F) || defined(TEST_SUITE_STORAGE) || defined(TEST_SUITE_GD5F) || defined(TEST_SUITE_RTC) #define TEST_SUITE_SELECTED #endif diff --git a/test/host/README.md b/test/host/README.md index f86bdc6c..0c660bb8 100644 --- a/test/host/README.md +++ b/test/host/README.md @@ -70,10 +70,10 @@ | `nand_port/nand_port_test.c` | 测试单元本体(`#include` 生产源码 + RAM 假芯片;内联一份"只看页首 64 B"的**旧算法对照**,证明断言能咬人) | | `nand_port/stub/` | 桩头文件(`gd5f2gq5ue.h` 芯片几何与 SPI 原语声明 / `dbg_log.h` 日志宏计数) | -> 详见 `docs/测试说明/看门狗单元测试说明.md`、`docs/测试说明/系统时钟单元测试说明.md`、 -> `docs/测试说明/配置文件单元测试说明.md`、`docs/测试说明/ADC输入层单元测试说明.md`、 -> `docs/测试说明/相量层单元测试说明.md`、`docs/测试说明/卷锁单元测试说明.md`、 -> `docs/测试说明/时间同步单元测试说明.md`; +> 详见 `docs/测试说明/单元测试/看门狗单元测试说明.md`、`docs/测试说明/单元测试/系统时钟单元测试说明.md`、 +> `docs/测试说明/单元测试/配置文件单元测试说明.md`、`docs/测试说明/单元测试/ADC输入层单元测试说明.md`、 +> `docs/测试说明/单元测试/相量层单元测试说明.md`、`docs/测试说明/单元测试/卷锁单元测试说明.md`、 +> `docs/测试说明/单元测试/时间同步单元测试说明.md`; > harness 用法见 [`common/README.md`](common/README.md)。 > 已挂 pre-commit 钩子(各模块同名 `*-unit-test`,共 **22** 个;逐个说明见 > `docs/代码规范/pre-commit使用说明.md` §2 与 AGENTS.md 门禁条)。 @@ -149,13 +149,13 @@ ## 相关文档 -- `docs/测试说明/自动化测试流程.md` — `@test` 细节与失败模式 -- `docs/测试说明/测试开发标准流程.md` — 测试分层与门禁 -- `docs/测试说明/看门狗单元测试说明.md` — 主机侧单测(用例 / 平台层 / 扩展方法) -- `docs/测试说明/系统时钟单元测试说明.md` — 系统时钟换算单测(用例 / 桩 / Zeller 缺陷记录) -- `docs/测试说明/配置文件单元测试说明.md` — 配置引擎单测(内存 FS 桩 / 抓出的 P0) -- `docs/测试说明/ADC输入层单元测试说明.md` — ADC 输入层单测(逐 Rank 钉死映射) -- `docs/测试说明/相量层单元测试说明.md` — 相量层单测(傅氏系数 / 双区交换) -- `docs/测试说明/卷锁单元测试说明.md` — 卷锁单测(fail-open 不变量) -- `docs/测试说明/时间同步单元测试说明.md` — 时间同步单测(探针窗口心跳缺口逻辑贡献者) -- `docs/测试说明/CH395F_Test_Guide.md`、`FTP_Test_Guide.md` +- `docs/测试说明/流程与规范/自动化测试流程.md` — `@test` 细节与失败模式 +- `docs/测试说明/流程与规范/测试开发标准流程.md` — 测试分层与门禁 +- `docs/测试说明/单元测试/看门狗单元测试说明.md` — 主机侧单测(用例 / 平台层 / 扩展方法) +- `docs/测试说明/单元测试/系统时钟单元测试说明.md` — 系统时钟换算单测(用例 / 桩 / Zeller 缺陷记录) +- `docs/测试说明/单元测试/配置文件单元测试说明.md` — 配置引擎单测(内存 FS 桩 / 抓出的 P0) +- `docs/测试说明/单元测试/ADC输入层单元测试说明.md` — ADC 输入层单测(逐 Rank 钉死映射) +- `docs/测试说明/单元测试/相量层单元测试说明.md` — 相量层单测(傅氏系数 / 双区交换) +- `docs/测试说明/单元测试/卷锁单元测试说明.md` — 卷锁单测(fail-open 不变量) +- `docs/测试说明/单元测试/时间同步单元测试说明.md` — 时间同步单测(探针窗口心跳缺口逻辑贡献者) +- `docs/测试说明/板级测试/CH395F_Test_Guide.md`、`FTP_Test_Guide.md` diff --git a/test/host/adc_health/run_unit_test.py b/test/host/adc_health/run_unit_test.py index 266cb9fe..382a543c 100644 --- a/test/host/adc_health/run_unit_test.py +++ b/test/host/adc_health/run_unit_test.py @@ -26,7 +26,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 设计依据:docs/算法/继电保护功能复现规划.md §3.1(采样有效性校验); - docs/测试说明/测试开发标准流程.md §4.2(主机侧纯逻辑单测)。 + docs/测试说明/流程与规范/测试开发标准流程.md §4.2(主机侧纯逻辑单测)。 创建日期:2026-10-11 """ import os diff --git a/test/host/cfg_file/cfg_file_test.c b/test/host/cfg_file/cfg_file_test.c index 34dcc88f..a47e7c7c 100644 --- a/test/host/cfg_file/cfg_file_test.c +++ b/test/host/cfg_file/cfg_file_test.c @@ -14,7 +14,7 @@ * 这些在真机上极难复现(需掉电/坏块)。 * 3. 不占 MCU 的 RAM。 * - * 覆盖点(对应 docs/测试说明/配置文件单元测试说明.md 的 TC-CFG-xxx): + * 覆盖点(对应 docs/测试说明/单元测试/配置文件单元测试说明.md 的 TC-CFG-xxx): * —— 值类型编解码(s_encode / s_decode 经公开 load/save 间接验证 + 直接白盒)—— * TC-CONFIG-001 UINT 1/2/4 字节小端往返(含 0 / 最大值) * TC-CONFIG-002 UINT 非法:空 / 非数字 / 带后缀 / 超范围 diff --git a/test/host/cfg_file/run_unit_test.py b/test/host/cfg_file/run_unit_test.py index edcdd707..3ecf98e2 100644 --- a/test/host/cfg_file/run_unit_test.py +++ b/test/host/cfg_file/run_unit_test.py @@ -22,7 +22,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 -设计依据:docs/测试说明/配置文件单元测试说明.md(S1-b,原复审项已闭环); +设计依据:docs/测试说明/单元测试/配置文件单元测试说明.md(S1-b,原复审项已闭环); 创建日期:2026-10-02 """ import os diff --git a/test/host/cfg_file_store_mcu/run_unit_test.py b/test/host/cfg_file_store_mcu/run_unit_test.py index 7cbb9fcb..804d2cf3 100644 --- a/test/host/cfg_file_store_mcu/run_unit_test.py +++ b/test/host/cfg_file_store_mcu/run_unit_test.py @@ -36,7 +36,7 @@ r"""配置存储后端(cfg_file_store_mcu)的主机侧纯逻辑单元测试 设计依据:docs/子系统设计/配置文件设计说明.md §6.2(mtime 令牌)、 docs/架构设计/STM32F4-Base存储架构说明.md §10.1 第 10/11 条、 -docs/测试说明/主机单测覆盖率口径.md §9 P2 第 2 项 +docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P2 第 2 项 创建日期:2026-10-24 """ import os diff --git a/test/host/common/README.md b/test/host/common/README.md index 80dd97b2..98ec6824 100644 --- a/test/host/common/README.md +++ b/test/host/common/README.md @@ -72,7 +72,7 @@ raise SystemExit(run_host_unit_test(TestBuild(name="...", src="...", ...))) ## 环境要求 -同主机侧纯逻辑单测通用要求(见 [`../../../docs/测试说明/测试开发标准流程.md`](../../../docs/测试说明/测试开发标准流程.md) §4.2): +同主机侧纯逻辑单测通用要求(见 [`../../../docs/测试说明/流程与规范/测试开发标准流程.md`](../../../docs/测试说明/流程与规范/测试开发标准流程.md) §4.2): MSVC `cl.exe`(装了 VS 即有)+ Windows SDK + 纯标准库 Python;**不调 `vcvars64.bat`** (内部 `reg.exe` 受限),直接拼环境变量调 `cl.exe`。 @@ -104,7 +104,7 @@ MSVC `cl.exe`(装了 VS 即有)+ Windows SDK + 纯标准库 Python;**不 - `DTU_HOST_BUILD=<目录>`:改产物根(CI/容器要固定路径时用)。覆盖率侧同源—— `scripts/check_test_coverage.py` 复用同一个函数,不再用自己那套固定名 - (旧 `%TEMP%\dtu_test_cov` 的共享名,正是 docs/测试说明/主机单测覆盖率口径.md 里 + (旧 `%TEMP%\dtu_test_cov` 的共享名,正是 docs/测试说明/单元测试/主机单测覆盖率口径.md 里 "并行期每人只跑 `--module` 自己模块"那条规避的由来;分家之后该规避不再必要)。 - `DTU_HOST_BUILD_KEEP=1`:保留本次独占目录不删(要单步调试那个 exe 时用,会打印路径)。 diff --git a/test/host/common/unit_test_harness.py b/test/host/common/unit_test_harness.py index 80ff91bc..1f8de21f 100644 --- a/test/host/common/unit_test_harness.py +++ b/test/host/common/unit_test_harness.py @@ -36,7 +36,7 @@ summary_marker="=== Task Watchdog Tests:", ))) -设计依据:docs/测试说明/测试开发标准流程.md §4.2 +设计依据:docs/测试说明/流程与规范/测试开发标准流程.md §4.2 创建日期:2026-10-01 """ @@ -141,9 +141,9 @@ class TestBuild: # 套件**就会互相覆盖,而最坏的不是编不过:A 树编译完,B 树把同名 exe 又盖一遍, # A 树随后执行的是 **B 树编出来的二进制**——两棵树的 summary_marker 一模一样, # harness 分辨不出来,于是拿着别人的运行结果给自己下结论(比红更难查)。 -# 覆盖率侧同源:%TEMP%\dtu_test_cov 也是固定共享名(docs/测试说明/主机单测覆盖率 -# 口径.md 里"并行期每人只跑 --module 自己模块"就是为绕开它写的规避;本处修好后 -# 那条规避不再必要)。 +# 覆盖率侧同源:%TEMP%\dtu_test_cov 也是固定共享名(口径文档 +# docs/测试说明/单元测试/主机单测覆盖率口径.md:其中"并行期每人只跑 --module 自己模块" +# 就是为绕开它写的规避;本处修好后那条规避不再必要)。 # # 口径:**按工作树分家**。产物根 = %TEMP%\dtu_host\<仓库根路径哈希>\,跨树天然不撞, # 同一棵树内仍复用同一份目录(33 套的编译缓存没必要白白重编)。**不用锁**——锁会把 diff --git a/test/host/console_log/console_log_test.c b/test/host/console_log/console_log_test.c index 80d72b6b..51c31498 100644 --- a/test/host/console_log/console_log_test.c +++ b/test/host/console_log/console_log_test.c @@ -1282,9 +1282,10 @@ static void tc_check_then_act(void) * 这是本套唯一能把"两个生产者并发时,写进 DR 的字节流里不得出现另一条行的字节" * 做成必然失败断言的把手:修复后是**非阻塞**设计,永远不会调 vTaskDelay,所以既有的 * con_delay_hook 在这条路径上根本不会被触发(拿它当注入点会静默地什么都测不到)。 - * 台架一手证据:docs/测试说明/boot_log_data/20261026_prod_console_interleave_evidence.txt + * 台架一手证据:docs/测试说明/测试数据/boot_log_data/20261026_prod_console_interleave_evidence.txt * —— PROT 行内多出 [ 2 0 三字节,紧接其后的 NAND_FTL 行恰好缺这三个字节的行首。 */ -/* 台架 16:37 那次被插字的原文行(boot_log_data/20261026_prod_console_interleave_evidence.txt +/* 台架 16:37 那次被插字的原文行(证据文件同上: + * docs/测试说明/测试数据/boot_log_data/ 那份 interleave 证据的 * OCCURRENCE 1 去掉三个外来字节之后的样子)。M 族拿它当"真实行长与真实前缀"的样本, * 免得用例自己造一个不像现场的理想行。 */ static const char s_prot_line[] = diff --git a/test/host/console_log/run_unit_test.py b/test/host/console_log/run_unit_test.py index 483c5503..b0bbe72f 100644 --- a/test/host/console_log/run_unit_test.py +++ b/test/host/console_log/run_unit_test.py @@ -38,7 +38,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 -设计依据:docs/子系统设计/控制台单写者日志设计说明.md、docs/测试说明/主机单测覆盖率口径.md §9「P2 落地」清单第 3 条 +设计依据:docs/子系统设计/控制台单写者日志设计说明.md、docs/测试说明/单元测试/主机单测覆盖率口径.md §9「P2 落地」清单第 3 条 创建日期:2026-10-24 """ import os diff --git a/test/host/ftp_cfg/run_unit_test.py b/test/host/ftp_cfg/run_unit_test.py index 21dbc6a1..150743cd 100644 --- a/test/host/ftp_cfg/run_unit_test.py +++ b/test/host/ftp_cfg/run_unit_test.py @@ -22,7 +22,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 -设计依据:docs/子系统设计/网络配置说明.md §3.4、docs/测试说明/主机单测覆盖率口径.md §9 P1 +设计依据:docs/子系统设计/网络配置说明.md §3.4、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P1 创建日期:2026-10-23 """ import os diff --git a/test/host/iec104_serv/run_unit_test.py b/test/host/iec104_serv/run_unit_test.py index d92cf2c4..09a98be0 100644 --- a/test/host/iec104_serv/run_unit_test.py +++ b/test/host/iec104_serv/run_unit_test.py @@ -28,7 +28,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 设计依据:docs/子系统设计/*104* 设计文档、AGENTS.md 模块约定(单连接 socket 断开语义、 -错误码经任务通知值回传)、docs/测试说明/主机单测覆盖率口径.md §9 +错误码经任务通知值回传)、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 创建日期:2026-10-23 """ import os diff --git a/test/host/latency_peer.py b/test/host/latency_peer.py index 136bfeb3..876d54b6 100644 --- a/test/host/latency_peer.py +++ b/test/host/latency_peer.py @@ -3,7 +3,7 @@ Server-driven protocol: the MCU (testTask, port 8080) sends one operation byte; the peer executes the corresponding traffic pattern. See -docs/测试说明/链路延迟测试说明.md §4.5 for the full protocol spec. +docs/测试说明/专项验证/链路延迟测试说明.md §4.5 for the full protocol spec. Ops (MCU -> peer): 0x01 QUEUE_RT recv flood : peer sends 50 x 100B (5ms apart) diff --git a/test/host/lftpd/run_unit_test.py b/test/host/lftpd/run_unit_test.py index 1c1c90dc..356ba363 100644 --- a/test/host/lftpd/run_unit_test.py +++ b/test/host/lftpd/run_unit_test.py @@ -29,8 +29,8 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 -设计依据:docs/测试说明/FTP_Test_Guide.md、docs/子系统设计/网络配置说明.md §3.4、 -docs/测试说明/主机单测覆盖率口径.md §9 +设计依据:docs/测试说明/板级测试/FTP_Test_Guide.md、docs/子系统设计/网络配置说明.md §3.4、 +docs/测试说明/单元测试/主机单测覆盖率口径.md §9 创建日期:2026-10-23 """ import os diff --git a/test/host/lftpd_inet/run_unit_test.py b/test/host/lftpd_inet/run_unit_test.py index 49a3f234..fc0015e3 100644 --- a/test/host/lftpd_inet/run_unit_test.py +++ b/test/host/lftpd_inet/run_unit_test.py @@ -25,8 +25,8 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 -设计依据:docs/子系统设计/网络配置说明.md §3.4、docs/测试说明/FTP_Test_Guide.md、 -docs/测试说明/主机单测覆盖率口径.md §9 +设计依据:docs/子系统设计/网络配置说明.md §3.4、docs/测试说明/板级测试/FTP_Test_Guide.md、 +docs/测试说明/单元测试/主机单测覆盖率口径.md §9 创建日期:2026-10-23 """ import os diff --git a/test/host/lftpd_io/run_unit_test.py b/test/host/lftpd_io/run_unit_test.py index a2606e2b..945e92ce 100644 --- a/test/host/lftpd_io/run_unit_test.py +++ b/test/host/lftpd_io/run_unit_test.py @@ -26,7 +26,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 -设计依据:docs/内存管理/RAM使用分析与优化方案.md §4.2.1、docs/测试说明/主机单测覆盖率口径.md §9 P1 +设计依据:docs/内存管理/RAM使用分析与优化方案.md §4.2.1、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P1 创建日期:2026-10-23 """ import os diff --git a/test/host/net_cfg/run_unit_test.py b/test/host/net_cfg/run_unit_test.py index 845859b8..f6806ac6 100644 --- a/test/host/net_cfg/run_unit_test.py +++ b/test/host/net_cfg/run_unit_test.py @@ -28,7 +28,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 -设计依据:docs/子系统设计/网络配置说明.md、docs/测试说明/主机单测覆盖率口径.md §9 P1 +设计依据:docs/子系统设计/网络配置说明.md、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P1 创建日期:2026-10-23 """ import os diff --git a/test/host/net_events/run_unit_test.py b/test/host/net_events/run_unit_test.py index b71bfc3d..d764636b 100644 --- a/test/host/net_events/run_unit_test.py +++ b/test/host/net_events/run_unit_test.py @@ -31,7 +31,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 设计依据:docs/网络/网络自愈架构设计.md §4.10、docs/网络/Net层阻塞模型架构设计.md、 -docs/测试说明/主机单测覆盖率口径.md §9 +docs/测试说明/单元测试/主机单测覆盖率口径.md §9 创建日期:2026-10-23 """ import os diff --git a/test/host/net_listener/run_unit_test.py b/test/host/net_listener/run_unit_test.py index a1d04c2a..0139566c 100644 --- a/test/host/net_listener/run_unit_test.py +++ b/test/host/net_listener/run_unit_test.py @@ -31,7 +31,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 -设计依据:docs/网络/网络自愈架构设计.md §4.10、docs/测试说明/主机单测覆盖率口径.md §9(假 CH395F 实施规格) +设计依据:docs/网络/网络自愈架构设计.md §4.10、docs/测试说明/单元测试/主机单测覆盖率口径.md §9(假 CH395F 实施规格) 创建日期:2026-10-23 """ import os diff --git a/test/host/net_pending/run_unit_test.py b/test/host/net_pending/run_unit_test.py index 09045967..91aa6fbb 100644 --- a/test/host/net_pending/run_unit_test.py +++ b/test/host/net_pending/run_unit_test.py @@ -30,7 +30,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 设计依据:AGENTS.md 模块约定(错误码经任务通知值回传)、 -docs/网络/Net层阻塞模型架构设计.md、docs/测试说明/主机单测覆盖率口径.md §9 +docs/网络/Net层阻塞模型架构设计.md、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 创建日期:2026-10-23 """ import os diff --git a/test/host/net_select/run_unit_test.py b/test/host/net_select/run_unit_test.py index bdd28506..d9db671c 100644 --- a/test/host/net_select/run_unit_test.py +++ b/test/host/net_select/run_unit_test.py @@ -25,7 +25,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 -设计依据:docs/网络/Net层阻塞模型架构设计.md、docs/测试说明/主机单测覆盖率口径.md §9 P1 +设计依据:docs/网络/Net层阻塞模型架构设计.md、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P1 创建日期:2026-10-23 """ import os diff --git a/test/host/net_socket/run_unit_test.py b/test/host/net_socket/run_unit_test.py index eaf83d8b..d1f9691e 100644 --- a/test/host/net_socket/run_unit_test.py +++ b/test/host/net_socket/run_unit_test.py @@ -49,7 +49,7 @@ 退出码:0=PASS / 1=测试失败(含常量闸不过)/ 2=环境错误。 -设计依据:docs/网络/网络自愈架构设计.md §4.10、docs/测试说明/主机单测覆盖率口径.md §9 +设计依据:docs/网络/网络自愈架构设计.md §4.10、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 创建日期:2026-10-24 """ import os diff --git a/test/host/phasor/run_unit_test.py b/test/host/phasor/run_unit_test.py index f4918474..b3aaae64 100644 --- a/test/host/phasor/run_unit_test.py +++ b/test/host/phasor/run_unit_test.py @@ -28,7 +28,7 @@ 设计依据:docs/算法/继电保护功能复现规划.md §3.2(全周傅氏系数表 等); docs/算法/傅氏算法详解.md §2.3(系数口径); - docs/测试说明/测试开发标准流程.md §4.2(主机侧纯逻辑单测)。 + docs/测试说明/流程与规范/测试开发标准流程.md §4.2(主机侧纯逻辑单测)。 创建日期:2026-10-10 """ import os diff --git a/test/host/prot_set_store/run_unit_test.py b/test/host/prot_set_store/run_unit_test.py index 37a78ec6..7db82617 100644 --- a/test/host/prot_set_store/run_unit_test.py +++ b/test/host/prot_set_store/run_unit_test.py @@ -21,7 +21,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 -设计依据:App/cfg/prot_set_store.h 的返回码表、docs/测试说明/主机单测覆盖率口径.md §9 P1 +设计依据:App/cfg/prot_set_store.h 的返回码表、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P1 创建日期:2026-10-23 """ import os diff --git a/test/host/soe_store/run_unit_test.py b/test/host/soe_store/run_unit_test.py index f508c377..bf689d84 100644 --- a/test/host/soe_store/run_unit_test.py +++ b/test/host/soe_store/run_unit_test.py @@ -39,7 +39,7 @@ r"""SOE 落盘胶水层(soe_store)的主机侧纯逻辑单元测试运行器 设计依据:docs/架构设计/STM32F4-Base存储架构说明.md §10.1 第 10/11 条、 docs/算法/继电保护功能复现规划.md §3.4(SOE 记录 / 动作记录,B9)、 -docs/测试说明/主机单测覆盖率口径.md §9 P2 第 2 项 +docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P2 第 2 项 创建日期:2026-10-24 """ import os diff --git a/test/host/sys_clock/run_unit_test.py b/test/host/sys_clock/run_unit_test.py index 889576e8..371428ec 100644 --- a/test/host/sys_clock/run_unit_test.py +++ b/test/host/sys_clock/run_unit_test.py @@ -24,7 +24,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 -设计依据:docs/测试说明/系统时钟单元测试说明.md(S1-a,原复审项已闭环); +设计依据:docs/测试说明/单元测试/系统时钟单元测试说明.md(S1-a,原复审项已闭环); 创建日期:2026-10-02 """ import os diff --git a/test/host/sys_clock/sys_clock_test.c b/test/host/sys_clock/sys_clock_test.c index 052f05c8..774a051d 100644 --- a/test/host/sys_clock/sys_clock_test.c +++ b/test/host/sys_clock/sys_clock_test.c @@ -13,7 +13,7 @@ * 断言,见 tc_000; * - 其余用例用 sys_clock_set(unix, NULL) 建立确定基准(无 RTC 副作用)。 * - * 覆盖点(对应 docs/测试说明/系统时钟单元测试说明.md 的 TC-CLK-xxx): + * 覆盖点(对应 docs/测试说明/单元测试/系统时钟单元测试说明.md 的 TC-CLK-xxx): * TC-SYSCLK-000 未初始化:sys_clock_get / get_time / get_str 的无效语义 * TC-SYSCLK-001 init 正常:RTC 合法 → 返回 0,基准 = 换算 Unix 秒 * TC-SYSCLK-002 init 闰年换算:2024-02-29 / 2000-02-29(世纪闰)/ 2/29→3/1 间隔 diff --git a/test/host/sys_log_mcu/run_unit_test.py b/test/host/sys_log_mcu/run_unit_test.py index d0742f21..c12c0b57 100644 --- a/test/host/sys_log_mcu/run_unit_test.py +++ b/test/host/sys_log_mcu/run_unit_test.py @@ -46,7 +46,7 @@ r"""运行/自检记录落盘后端(sys_log_mcu)的主机侧纯逻辑单元 设计依据:docs/子系统设计/运行与自检记录设计说明.md §4.4/§4.5/§5.3、 docs/架构设计/STM32F4-Base存储架构说明.md §10.1 第 10/11 条、 -docs/测试说明/主机单测覆盖率口径.md §9 P2 第 2 项 +docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P2 第 2 项 创建日期:2026-10-24 """ import os diff --git a/test/host/task_prof/run_unit_test.py b/test/host/task_prof/run_unit_test.py index e3172019..e9805a5e 100644 --- a/test/host/task_prof/run_unit_test.py +++ b/test/host/task_prof/run_unit_test.py @@ -23,7 +23,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误。 -设计依据:App/util/task_prof.h、docs/测试说明/主机单测覆盖率口径.md §9 P1 +设计依据:App/util/task_prof.h、docs/测试说明/单元测试/主机单测覆盖率口径.md §9 P1 创建日期:2026-10-23 """ import os diff --git a/test/host/watchdog/run_unit_test.py b/test/host/watchdog/run_unit_test.py index 8b3cee84..a6bade04 100644 --- a/test/host/watchdog/run_unit_test.py +++ b/test/host/watchdog/run_unit_test.py @@ -22,7 +22,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 -设计依据:docs/测试说明/看门狗单元测试说明.md +设计依据:docs/测试说明/单元测试/看门狗单元测试说明.md 创建日期:2026-10-01 """ import os diff --git a/test/host/watchdog/watchdog_test.c b/test/host/watchdog/watchdog_test.c index 7ee14479..8e65c138 100644 --- a/test/host/watchdog/watchdog_test.c +++ b/test/host/watchdog/watchdog_test.c @@ -10,7 +10,7 @@ * TASK_WATCHDOG_UNIT_TEST 守卫的测试专用复位,MCU 构建零开销) * 把模块静态态恢复到"刚上电"。 * - * 覆盖点(对应 docs/测试说明/看门狗单元测试说明.md 的 TC-WD-xxx): + * 覆盖点(对应 docs/测试说明/单元测试/看门狗单元测试说明.md 的 TC-WD-xxx): * TC-WATCHDOG-001 未启动时 poll 不做任何判定(也不喂狗) * TC-WATCHDOG-002 节流:< 100ms 的 poll 直接返回 * TC-WATCHDOG-003 全员到位置位 → 喂狗一次,且位图取走清零 diff --git a/test/run_all_suites.py b/test/run_all_suites.py index ed9669d0..2d1fcfa3 100644 --- a/test/run_all_suites.py +++ b/test/run_all_suites.py @@ -40,7 +40,7 @@ ② 防止"某套件长期编不过而无人知"(2026-08~09 CH395F 套件实例)。 注意 RAM 溢出会自然暴露为链接错误 L6406E——这正是想要的。 -设计依据:docs/测试说明/测试开发标准流程.md §3.1 +设计依据:docs/测试说明/流程与规范/测试开发标准流程.md §3.1 创建日期:2026-10-01 """ diff --git a/tools/README.md b/tools/README.md index e02adc21..b8f1fdda 100644 --- a/tools/README.md +++ b/tools/README.md @@ -40,4 +40,4 @@ - `docs/架构设计/图形绘制流程.md` — 配图规范与选型 - `docs/架构设计/引用关系图说明.md` -- `docs/测试说明/串口助手使用指南.md`、`docs/测试说明/串口助手设计说明.md` +- `docs/测试说明/测试工具/串口助手使用指南.md`、`docs/测试说明/测试工具/串口助手设计说明.md`