Files
wandering1 f754d59218 docs(测试说明): 按用途分六个子目录并同步全库引用
分层:流程与规范/ 单元测试/ 板级测试/ 专项验证/ 测试工具/ 测试数据/,
顶层只留新增的目录导航 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 处(无新增断链)。
2026-10-30 07:16:07 +08:00

120 lines
5.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SD2506_RTC 测试指南
> 对应驱动:`Drivers/BSP/SD2506/sd2506.c`
> 测试代码:`test/board/sd2506_test_task.c` + `test/board/sd2506_test.h`
## 1. 概述
本测试套件对 `sd2506.c` 做**黑盒功能自测**,只调用公共 API,不触碰驱动内部函数。
每个用例通过 `SD2506_TEST_CHECK` 记录 pass/fail,最终由 `SD2506_TEST_REPORT` 汇总。
历史背景:本驱动曾出现“时间写不进”问题,根因是寄存器宏写成 `0x0FH`(KEIL/ARMCC
不识别 `H` 整数后缀,被编译为 0),导致 `SD2506_REG_CTR1` 实际等于 0(秒寄存器),
`sd2506_write_enable()` 把 WRTC 写错地址、写保护永不解除。修正为 `0x0FU` 后恢复。
详见 `docs/问题记录/SD2506_Trap_Records.md`。
## 2. 启用与编译
`test/board/test_config.h` 中一次只能启用一个 `TEST_SUITE_*`(互斥):
```c
//#define TEST_SUITE_CH395F
//#define TEST_SUITE_STORAGE
//#define TEST_SUITE_GD5F
#define TEST_SUITE_RTC /* 启用 RTC 测试套件 */
//#define ENABLE_DESTRUCTIVE_TESTS /* 需跑改设备状态的用例时才打开(默认关闭) */
```
> **破坏性用例开关(2026-09-21 新增,默认关闭)**:本套件有 3 处会**改变设备状态**——
> TC-RTC-002(写 RTC 时间,套件结束会复原)、TC-RTC-014(写芯片 SRAM)、TC-RTC-015(写报警寄存器)。
> 关闭 `ENABLE_DESTRUCTIVE_TESTS` 时这三条跳过(开机打印 `mode: READ-ONLY` 与 `skipped` 提示),
> 只跑只读用例:init/读时间、BCD 互转、温度、电池电压、ID、走时校验;
> 打开后(`mode: DESTRUCTIVE`)全跑并在结尾复原原始时间——**中途断电可能把板子时间留在测试值**。
`test/board/sd2506_test.h` 中控制各阶段(默认全开):
```c
#define ENABLE_RTC_BASIC_TESTS /* Phase 1: 基本读写 / 走时 */
#define ENABLE_RTC_API_TESTS /* Phase 2: 全功能 API 覆盖 */
```
编译(要求 0 错误 0 警告):
```powershell
& '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py
```
烧录后在串口(USART1, 115200bps)观察 `[RTC_TEST]` 日志。
## 3. 测试用例
| 编号 | 目标 | 覆盖函数 | 判定 |
|------|------|----------|------|
| TC-RTC-001 | 初始化并读取当前时间 | `sd2506_init` / `sd2506_get_time` | init 返回 0;get 返回 0 |
| TC-RTC-002 | 写固定时间立即回读一致 | `sd2506_set_time` / `sd2506_get_time` | set==readback(允许 +1s 进位) |
| TC-RTC-003 | 走时验证 | `sd2506_get_time` | 延时 3s 后秒数前进 2~5s |
| TC-RTC-010 | BCD↔DEC 互转 | `sd2506_dec_to_bcd` / `sd2506_bcd_to_dec` | 10 组样本双向一致 |
| TC-RTC-011 | 内部温度读取 | `sd2506_get_temperature` | 返回 0;值 ∈ [-40, 85] |
| TC-RTC-012 | 电池电压(mV) | `sd2506_get_battery_voltage` | 返回 0;值 ∈ (2000, 5000) |
| TC-RTC-013 | 芯片 8 字节 ID | `sd2506_get_id` | 返回 0;读出 8 字节 |
| TC-RTC-014 | 用户 SRAM 回环 | `sd2506_write_sram` / `sd2506_read_sram` | 写入 8 字节后回读一致 |
| TC-RTC-015 | 报警设置 + 清除 | `sd2506_set_alarm` / `sd2506_clear_alarm` | 两者均返回 0 |
## 4. 覆盖矩阵
| 公共 API | 是否覆盖 | 用例 |
|----------|----------|------|
| `sd2506_init` | ✅ | TC-RTC-001 |
| `sd2506_get_time` | ✅ | TC-RTC-001/002/003 |
| `sd2506_set_time` | ✅ | TC-RTC-002 |
| `sd2506_get_temperature` | ✅ | TC-RTC-011 |
| `sd2506_get_battery_voltage` | ✅ | TC-RTC-012 |
| `sd2506_get_id` | ✅ | TC-RTC-013 |
| `sd2506_read_sram` | ✅ | TC-RTC-014 |
| `sd2506_write_sram` | ✅ | TC-RTC-014 |
| `sd2506_set_alarm` | ✅ | TC-RTC-015 |
| `sd2506_clear_alarm` | ✅ | TC-RTC-015 |
| `sd2506_read_ctr1` | △(诊断) | run() 内打印 CTR1 |
| `sd2506_bcd_to_dec` / `sd2506_dec_to_bcd` | ✅ | TC-RTC-010 |
> 未覆盖(需专项验证,不在本自测范围):倒计时寄存器、温度报警历史、
> 跨重启持久化(原 Phase 3 已废弃,依赖实际掉电/上电,建议手动或另写用例)。
## 5. 运行与判定
- `sd2506_test_run()` 由测试调度器调用,先 init 并记录原始时间,最后用
`sd2506_set_time` 把板子时间**恢复**为测试前的值(不污染真实时钟)。
- 输出形如(**只读模式**,默认):
```
[RTC_TEST] === SD2506 Phase 1: basic read/write (public API) ===
[RTC_TEST] [PASS] sd2506_init() ret=0 (expect 0)
...
[RTC_TEST] === Phase 1 basic: 3/3 PASSED (failed=0) ===
[RTC_TEST] === SD2506 Phase 2: full API coverage ===
...
[RTC_TEST] === Phase 2 API: 6/6 PASSED (failed=0) ===
[RTC_TEST] === RTC Tests: 9/9 PASSED (failed=0) ===
```
- **各 Phase 汇总行只反映本阶段**(进入各 Phase 前统计自清零);末尾
`=== RTC Tests: N/M PASSED (failed=0) ===` 是**套件级**汇总,也是
`run_all_suites.py --require-suite-summary "RTC Tests"` 的判定标记
(见 `test_common.h` / `测试开发标准流程.md` §3.2)。
- **破坏性模式**(`ENABLE_DESTRUCTIVE_TESTS`)额外跑 TC-RTC-002 / 014 / 015,
计数变为 Phase 1 = 6/6、Phase 2 = 11/11、套件级 = 17/17。
- 通过标准:所有 Phase 与套件级的 `failed=0`,且每行 `X/Y PASSED` 中 X = Y。
## 6. 失败排查
- **TC-RTC-002 FAIL(set≠readback)**:优先查 `sd2506.h` 中各寄存器宏是否被写成
`0xNNH`(H 后缀陷阱)。例如 `SD2506_REG_CTR1` 必须是 `0x0FU` 而非 `0x0FH`。
- **init/get/set 返回 -2(I2C 错误)**:查 I2C1 接线(PB6-SCL / PB7-SDA)、
上拉电阻、芯片供电与器件地址 `0x32`。
- **温度/电压越界**:多为芯片未上电或 I2C 读到全 0xFF,按 I2C 链路排查。
## 7. 已知限制
- TC-RTC-015 会让 `sd2506_set_alarm` 置 `CTR2.INTAE=1`(报警中断允许)。
测试固件未挂 INT 中断处理,且 INT 引脚在板上未连接,对运行无影响;
若要完全复位,可手动再调用一次 `set_alarm(..., mask=0)`。
- SRAM 回环会在 `addr=0` 写入测试数据(8 字节),属用户 SRAM 区域,不影响时间/控制寄存器。