Files
STM32F4-Base/docs/SD2506_Test_Guide.md
T

13 KiB
Raw Blame History

SD2506 RTC 测试规范

1. 概述

本文档定义 SD2506API-G 高精度温补实时时钟驱动(STM32F407ZGTx,I2C1 接口 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)
接口 I2C1(PB6-SCL / PB7-SDA) CubeMX 已完成初始化
时间寄存器 00H SEC ~ 06H YEAR(BCD) 一次性连续读写 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 已初始化
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. 阶段 2:WRTC 解锁时序探测

阶段 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 正常
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 仅 CTR2(WRTC1)
5 0x80 0x00 CTR1→CTR2 仅 CTR1 bit7(WRTC1)
6 0x70 0x00 CTR1→CTR2 CTR1 bit6/5/4
7 0x86 0x00 CTR1→CTR2 CTR1 bit7+bit2(WRTC3+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