Files
STM32F4-Base/docs/SD2506_Test_Guide.md

253 lines
13 KiB
Markdown
Raw 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 测试规范
## 1. 概述
本文档定义 SD2506API-G 高精度温补实时时钟驱动STM32F407ZGTxI2C1 接口 PB6-SCL / PB7-SDA的测试规范。RTC 为本地外设,测试**无需 PC 配合**仅串口日志观察覆盖时间读写、写保护WRTC解锁时序、跨重启持久化三大主题。测试按阶段`TM-RTC-NN`)组织,每阶段含独立用例(`TC-RTC-NNN`)。
> **背景**:本驱动曾出现"时间同步后写入不生效、重启回到旧时间"的缺陷。根因是 `sd2506_write_enable()` 的 WRTC 解锁时序与 SD2506API-G 实际位布局不符——写操作 I2C 返回 OK但芯片因写保护未真正打开而**静默忽略**数据。本测试 Phase 2 用穷举探测法定位正确时序。
### 设计原则
| 原则 | 描述 | 验证用例 |
|------|------|----------|
| DP-01 | 写保护时序正确:写时间前必须用正确的 WRTC 解锁时序打开 CTR1/CTR2 写保护否则写被芯片静默忽略I2C 仍返回 OK | TC-RTC-002、TC-RTC-101、TC-RTC-201 |
| DP-02 | 时间须一次性 7 字节写入00H~06H不可单独写某一时间寄存器 | TC-RTC-002 |
| DP-03 | 跨重启持久化:写入后由纽扣电池/充电维持,重启后读回一致 | TC-RTC-201 |
| DP-04 | 24 小时制 + 自动复位ARST配置正确时间寄存器可读 | TC-RTC-001 |
### SD2506 关键参数
| 参数 | 值 | 说明 |
|------|-----|------|
| I2C 器件地址7 位) | `0x32` | HAL 用 8 位:写 `0x64`、读 `0x65``SD2506_I2C_ADDR_WRITE/READ` |
| 接口 | I2C1PB6-SCL / PB7-SDA | CubeMX 已完成初始化 |
| 时间寄存器 | `00H` SEC ~ `06H` YEARBCD | 一次性连续读写 7 字节 |
| 控制寄存器 | `0FH` CTR1、`10H` CTR2 | WRTC写 RTC 保护)位在此 |
| 24 小时制 | HOUR 寄存器 bit7 = `1` | `sd2506_set_time``hour \| 0x80` |
| YEAR 存储 | 后两位 BCD`year % 100` | `get_time` 回读 `+2000` 还原 |
| 写保护宏(头文件注释) | `SD2506_CTR1_WRITE_ON = 0xFF``SD2506_CTR1_WRITE_OFF = 0x7B` | `sd2506.h:124-126` 记载的"使能/禁止"建议值 |
> **关键约束**SD2506 的 WRTC 位布局在不同参考设计/批次间存在差异。本驱动原实现(`sd2506_write_enable()` @ `sd2506.c:121`)采用 `CTR2=0x80, CTR1=0x84`(源自 SD2403 参考),但实测未生效;头文件宏则指向 `CTR1=0xFF`。**正确时序须由 Phase 2 探测确认,不得臆测**。
### 测试环境
```
MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC)
外设: SD2506API-G (I2C1, PB6/PB7),纽扣电池或充电供电
工具: 串口终端(观察 DBG_INFO 日志),无 PC 网络端
```
### 构建模式与执行顺序
测试固件复用既有 `ch395fTestTask``StartCh395fTestTask`调度框架SD2506 作为独立 `TEST_SUITE_RTC` 套件接入,不新增 FreeRTOS 任务三个相位顺序执行Phase 1 → 2 → 3。各相位由 `test/sd2506_test.h``ENABLE_RTC_*` 宏独立开关,套件整体由 `test/test_config.h``TEST_SUITE_RTC` 选择。
| 构建宏 | 相位 | 说明 |
|--------|------|------|
| `ENABLE_RTC_BASIC_TESTS` | Phase 1 | 公共 API 基本读写 / 走时 |
| `ENABLE_RTC_WRTC_PROBE_TESTS` | Phase 2 | WRTC 解锁时序穷举探测 |
| `ENABLE_RTC_PERSIST_TESTS` | Phase 3 | 跨重启持久化(需人工重启核验) |
**执行顺序严格递增**:先确认 Phase 1若 FAIL 即证明当前驱动写无效),再 Phase 2定位正确 WRTC 时序),最后 Phase 3用命中时序验证持久化
### 启用测试
本测试复用既有 `ch395fTestTask``StartCh395fTestTask`)调度框架,作为独立 `TEST_SUITE_RTC` 套件接入,不新增 FreeRTOS 任务。
1. **Keil 工程**:把 `test/sd2506_test_task.c` 加入 `test/` 组(与 `ch395f_test_task.c` 等同级);`Options → C/C++ → Include Paths` 确认已含 `..\test`(其它测试套件已配置,无需重复添加)。
2. **选择套件**:编辑 `test/test_config.h`,注释掉其它 `TEST_SUITE_*`,取消注释 `#define TEST_SUITE_RTC`。一次构建仅能启用一个套件(互斥 `#error` 保护)。
3. **阶段开关**:编辑 `test/sd2506_test.h`,按需取消注释 `ENABLE_RTC_BASIC_TESTS` / `ENABLE_RTC_WRTC_PROBE_TESTS` / `ENABLE_RTC_PERSIST_TESTS`(默认全开)。
4. `@build` 验证 `0 Error(s), 0 Warning(s)` 后烧录,板子启动后 `StartCh395fTestTask` 自动进入 RTC 套件并顺序执行 Phase 1→2→3。
---
## 2. 阶段 1基本读写公共 API
| 阶段 ID | TM-RTC-01 |
|---------|-----------|
| **类型** | 独立运行 |
| **耗时** | ~5 秒 |
| **入口** | `StartCh395fTestTask → TEST_SUITE_RTC → sd2506_test_run()``sd2506_phase_basic()` |
| **出口** | 串口 `Phase 1 basic: N/N PASSED (failed=0)` |
### TC-RTC-001: 初始化与读取
| 字段 | 值 |
|------|-----|
| **ID** | TC-RTC-001 |
| **优先级** | P0 |
| **类型** | 功能测试 |
| **标题** | 验证 `sd2506_init()` 通信正常并可读取当前时间 |
| **前置条件** | 1. I2C1 已初始化<br>2. 未启用其他会并发访问 I2C 的测试 |
**测试步骤与判定标准**
| 步 | 操作 | 成功标准 | 失败标准 |
|----|------|----------|----------|
| 1 | `sd2506_init()` | 返回 `0``SD2506_OK` | 返回 `-2``SD2506_I2C_ERROR`I2C 通信失败/芯片未响应) |
| 2 | `sd2506_get_time(&r)` 读取当前时间 | 返回 `0``r.year` 落在 `2000~2099`、月/日/时/分/秒为合法 BCD 范围 | 返回非零,或字段越界(如月>12、秒>59 |
**通过标准**2/2 通过0 失败。任一失败 → 阶段标记 FAIL
**覆盖原则**DP-04
---
### TC-RTC-002: 写入后回读比对(核心判定)
| 字段 | 值 |
|------|-----|
| **ID** | TC-RTC-002 |
| **优先级** | P0 |
| **类型** | 功能测试 |
| **标题** | 写固定时间 `2026-08-28 12:00:00`,立即回读并比对 |
| **前置条件** | TC-RTC-001 通过 |
**测试步骤与判定标准**
| 步 | 操作 | 成功标准 | 失败标准 |
|----|------|----------|----------|
| 1 | `sd2506_set_time(&t)`t = 2026-08-28 12:00:00 | 返回 `0` | 返回非零I2C 错误) |
| 2 | `sd2506_get_time(&r)` 立即回读 | 返回 `0``r``t` 的 年月日时分 完全一致、`秒` 允许 `±1`(回读期间走 1 秒) | 回读字段不符(尤其时分秒) |
**通过标准**:回读与写入一致(秒允许 +1。若 FAIL → **证明当前 `sd2506_write_enable()` WRTC 时序无效,写被芯片静默忽略**,直接进入 Phase 2 定位。
**覆盖原则**DP-01、DP-02
---
### TC-RTC-003: 走时验证
| 字段 | 值 |
|------|-----|
| **ID** | TC-RTC-003 |
| **优先级** | P1 |
| **类型** | 功能测试 |
| **标题** | 写后等待 3 秒,确认时间向前推进约 3 秒 |
| **前置条件** | TC-RTC-002 通过(写已生效) |
**测试步骤与判定标准**
| 步 | 操作 | 成功标准 | 失败标准 |
|----|------|----------|----------|
| 1 | 记录 `set` 后回读时间,调用 `osDelay(3000)` 后再 `sd2506_get_time` | 时间前进 `2~5` 秒(含测试开销) | 时间不前进 / 回退(振荡器或配置异常) |
**通过标准**:时间单调前进且增量合理。任一异常 → 阶段标记 FAIL
**覆盖原则**DP-04
---
## 3. 阶段 2WRTC 解锁时序探测
| 阶段 ID | TM-RTC-02 |
|---------|-----------|
| **类型** | 独立运行 |
| **耗时** | ~3 秒 |
| **入口** | `StartCh395fTestTask → TEST_SUITE_RTC → sd2506_test_run()``sd2506_phase_wrtc_probe()` |
| **出口** | 串口 `Phase 2 WRTC probe: N/N PASSED (failed=0)``BEST sequence: ...` |
**分层说明**:本阶段为**黑盒 + 原始 I2C 诊断**,不依赖 `sd2506_write_enable()` 内部实现。直接以 `HAL_I2C_Mem_Write` 按不同 CTR1/CTR2 组合解锁→写 7 字节时间→立即回读,哪组能让写生效即为正确时序。每组写一组**互不相同的哨兵时间**,避免误判。
> 探测结论用于修正 `sd2506.c` 的 `sd2506_write_enable()`@ `sd2506.c:121`)与 `sd2506_write_disable()`@ `sd2506.c:142`)。
### TC-RTC-101: WRTC 候选序列穷举
| 字段 | 值 |
|------|-----|
| **ID** | TC-RTC-101 |
| **优先级** | P0 |
| **类型** | 功能测试 / 诊断 |
| **标题** | 穷举 8 组 CTR1/CTR2 解锁序列,找出令时间写生效的那组 |
| **前置条件** | 1. I2C1 正常<br>2. 无其它任务并发写 RTC |
**候选序列表**(索引 i每组写哨兵 `2020+i` 年避免互相干扰):
| idx | CTR1 | CTR2 | 顺序 | 说明 |
|-----|------|------|------|------|
| 0 | `0xFF` | `0x00` | CTR1→CTR2 | 仅 CTR1依照 `sd2506.h``SD2506_CTR1_WRITE_ON`)— **最可能正确** |
| 1 | `0x84` | `0x80` | CTR2→CTR1 | 当前驱动 `sd2506_write_enable` 实现SD2403 参考,待测) |
| 2 | `0x84` | `0x80` | CTR1→CTR2 | 同上,调换写顺序 |
| 3 | `0xFF` | `0x80` | CTR2→CTR1 | CTR1=0xFF 叠加 CTR2=0x80 |
| 4 | `0x00` | `0x80` | CTR2→CTR1 | 仅 CTR2WRTC1 |
| 5 | `0x80` | `0x00` | CTR1→CTR2 | 仅 CTR1 bit7WRTC1 |
| 6 | `0x70` | `0x00` | CTR1→CTR2 | CTR1 bit6/5/4 |
| 7 | `0x86` | `0x00` | CTR1→CTR2 | CTR1 bit7+bit2WRTC3+WRTC2 |
**测试步骤与判定标准**
| 步 | 操作 | 成功标准 | 失败标准 |
|----|------|----------|----------|
| 1 | 对每组候选:按指定顺序写 CTR1/CTR2 → 写 7 字节哨兵时间 → 立即回读 | 回读与哨兵一致(秒允许 +1 | 回读不符(写被忽略,该组无效) |
| 2 | 汇总 8 组结果,记录首个 PASS 的组为 `BEST` | 至少 1 组 PASS串口打印 `BEST sequence: CTR1=.. CTR2=.. ctr1_first=..` | 0 组 PASS |
**通过标准**:至少 1 组 PASS且打印出 `BEST sequence`。若 0 组 PASS → WRTC 不是根因,转查电池/充电/其它写入路径。
**覆盖原则**DP-01
---
## 4. 阶段 3跨重启持久化
| 阶段 ID | TM-RTC-03 |
|---------|-----------|
| **类型** | 需物理操作(重启板卡) |
| **耗时** | ~10 秒 + 人工重启 |
| **入口** | `StartCh395fTestTask → TEST_SUITE_RTC → sd2506_test_run()``sd2506_phase_persist()` |
| **出口** | 串口 `Phase 3 persist: N/N PASSED (failed=0)` |
**前提**Phase 2 必须已命中 `BEST sequence`(即 `s_best_found == 1`)。若未命中,本阶段跳过并打印指引。
### TC-RTC-201: 写哨兵时间 + 重启核验
| 字段 | 值 |
|------|-----|
| **ID** | TC-RTC-201 |
| **优先级** | P0 |
| **类型** | 恢复测试 / 持久化 |
| **标题** | 用命中时序写哨兵 `2026-09-09 09:09:09`,重启后读回应一致 |
| **前置条件** | TC-RTC-101 已命中 `BEST sequence` |
**测试步骤与判定标准**
| 步 | 操作 | 成功标准 | 失败标准 |
|----|------|----------|----------|
| 1 | 用 `BEST` 序列写哨兵时间 `2026-09-09 09:09:09` | 写返回 OK 且立即回读一致 | 写失败 / 回读不符(`BEST` 序列存疑) |
| 2 | 串口提示 `USER ACTION: reboot board, check boot log 'SD2506 time:' == 2026-09-09 09:09:09` | 用户重启后,板子开机日志 `SD2506 time:` 行显示 `2026-09-09 09:09:09` | 重启后读回为旧时间(电池/充电路径异常,或 `BEST` 序列仍不正确) |
**通过标准**:重启后开机日志时间 == 哨兵值。若不符 → 持久化链路(电池/充电/`sd2506_init` 上电逻辑)存在缺陷,需进一步排查。
**覆盖原则**DP-03
> 测试任务结束前会自动用 `BEST` 序列恢复测试开始时的原始时间,避免板子停留在哨兵值。
---
## 5. 已知陷阱
| 陷阱 | 现象 | 修复 |
|------|------|------|
| WRTC 解锁时序错误 | `sd2506_set_time` 返回 OK但时间不变化、重启回到旧值 | 以 Phase 2 `BEST sequence` 重写 `sd2506_write_enable()`/`sd2506_write_disable()` |
| 误以为 I2C 返回 OK 即写入成功 | 写保护未开时芯片静默忽略,`HAL_I2C_Mem_Write` 仍返回 `HAL_OK` | 必须**写后回读比对**确认TC-RTC-002 |
| YEAR 双偏移 | `unix_to_sd2506``sd2506_set_time` 各减一次 2000读出年份变成 20xx→溢出为 20xx+2000 | `set_time``year%100``get_time``+2000`;上层只传完整年 |
---
## 附录 A通过/失败汇总矩阵
| 阶段 | TC ID | 优先级 | 类型 | 状态 |
|------|-------|--------|------|------|
| TM-RTC-01 | TC-RTC-001 | P0 | 功能测试 | 待测 |
| TM-RTC-01 | TC-RTC-002 | P0 | 功能测试 | 待测 |
| TM-RTC-01 | TC-RTC-003 | P1 | 功能测试 | 待测 |
| TM-RTC-02 | TC-RTC-101 | P0 | 诊断 | 待测 |
| TM-RTC-03 | TC-RTC-201 | P0 | 恢复测试 | 待测 |
## 附录 B测试覆盖 vs 设计原则
| 原则 | 覆盖用例 |
|------|----------|
| DP-01 写保护时序正确 | TC-RTC-002、TC-RTC-101、TC-RTC-201 |
| DP-02 一次性 7 字节写入 | TC-RTC-002 |
| DP-03 跨重启持久化 | TC-RTC-201 |
| DP-04 24H + ARST 配置 | TC-RTC-001、TC-RTC-003 |