/****************************************************************************** * 模块名称:SD2506 RTC Test Suite * 模块功能:SD2506API-G RTC 驱动功能自测(黑盒,仅用公共 API)。 * * 历史背景:本驱动曾出现"时间写不进"问题,根因是 sd2506.h 中寄存器宏写成 * "0x0FH"(H 后缀)。KEIL/ARMCC 不识别 H 整数后缀,将其编译为 0, * 导致 SD2506_REG_CTR1 实际等于 0(秒寄存器),sd2506_write_enable() * 把 WRTC 写到了错误寄存器,写保护永不解除。修正为 "0x0FU" 后恢复。 * 详见 docs/SD2506_Trap_Records.md。 * * 当前测试:Phase 1 基本读写(init / 读 / 写 / 回读一致 / 走时), * 结束后自动恢复板子原始时间。 * 入口:sd2506_test_run()(由 StartCh395fTestTask 经 TEST_SUITE_RTC 调度) * 创建日期:2026-08-28 ******************************************************************************/ #include #include #include "sd2506_test.h" #include "test_config.h" #include "cmsis_os.h" #include "sd2506.h" #define DBG_TAG "[RTC_TEST]" #include "dbg_log.h" #ifdef TEST_SUITE_RTC /* 全局测试统计(宏自动管理) */ sd2506_test_stats_t g_sd2506_test_stats; /* ===================== Phase 1:基本读写 ===================== */ #ifdef ENABLE_RTC_BASIC_TESTS static void sd2506_phase_basic(void) { DBG_INFO("=== SD2506 Phase 1: basic read/write (public API) ==="); /* TC-RTC-001: init + 读取当前时间 */ int ret = sd2506_init(); SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_init() ret=%d (expect 0)", ret); sd2506_time_t r; ret = sd2506_get_time(&r); SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_get_time() ret=%d (expect 0)", ret); if (ret == SD2506_OK) { DBG_INFO(" current RTC: %04u-%02u-%02u %02u:%02u:%02u wk=%u", (unsigned int)r.year, (unsigned int)r.month, (unsigned int)r.day, (unsigned int)r.hour, (unsigned int)r.minute, (unsigned int)r.second, (unsigned int)r.week); } /* TC-RTC-002: 写固定时间,立即回读比对。 * 若 FAIL -> 先查 sd2506.h 寄存器宏后缀是否为 H(曾因 0x0FH 被 KEIL 编译为 0 * 导致 SD2506_REG_CTR1 指向秒寄存器、WRTC 写错地址)。详见 docs/SD2506_Trap_Records.md。 */ sd2506_time_t t; t.year = 2026; t.month = 8; t.day = 28; t.hour = 12; t.minute = 0; t.second = 0; t.week = 4; ret = sd2506_set_time(&t); SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_set_time() ret=%d (expect 0)", ret); ret = sd2506_get_time(&r); SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_get_time() after set ret=%d (expect 0)", ret); if (ret == SD2506_OK) { DBG_INFO(" set : %04u-%02u-%02u %02u:%02u:%02u", (unsigned int)t.year, (unsigned int)t.month, (unsigned int)t.day, (unsigned int)t.hour, (unsigned int)t.minute, (unsigned int)t.second); DBG_INFO(" readback: %04u-%02u-%02u %02u:%02u:%02u", (unsigned int)r.year, (unsigned int)r.month, (unsigned int)r.day, (unsigned int)r.hour, (unsigned int)r.minute, (unsigned int)r.second); } int match = (r.year == t.year && r.month == t.month && r.day == t.day && r.hour == t.hour && r.minute == t.minute && (r.second == t.second || r.second == ((t.second + 1U) % 60U))); SD2506_TEST_CHECK(match, "set==readback (in-session write takes effect)"); /* TC-RTC-003: 走时。写后等 3s,应前进约 3 秒 */ if (ret == SD2506_OK) { osDelay(3000); sd2506_time_t r2; int ret2 = sd2506_get_time(&r2); if (ret2 == SD2506_OK) { int adv = (r2.second + 60 * (r2.minute + 60 * (r2.hour + 24 * r2.day))) - (r.second + 60 * (r.minute + 60 * (r.hour + 24 * r.day))); if (adv < 0) adv += 60 * 60 * 24 * 32; DBG_INFO(" 3s later: %04u-%02u-%02u %02u:%02u:%02u (advanced %d s)", (unsigned int)r2.year, (unsigned int)r2.month, (unsigned int)r2.day, (unsigned int)r2.hour, (unsigned int)r2.minute, (unsigned int)r2.second, adv); SD2506_TEST_CHECK(adv >= 2 && adv <= 5, "RTC ticking forward (~3s)"); } } SD2506_TEST_REPORT("Phase 1 basic"); } #endif /* ENABLE_RTC_BASIC_TESTS */ /* ===================== 套件入口 ===================== */ void sd2506_test_run(void) { DBG_INFO("SD2506 test suite started"); int ret = sd2506_init(); SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_init() ret=%d (expect 0)", ret); /* 信息:读取 CTR1 默认状态(确认 WRTC 初始/可写能力,纯诊断) */ uint8_t c1 = 0x00U; if (sd2506_read_ctr1(&c1) == SD2506_OK) { DBG_INFO(" CTR1=0x%02X (WRTC2=CTR1.2=%u WRTC3=CTR1.7=%u)", (unsigned int)c1, (unsigned int)((c1 >> 2) & 1U), (unsigned int)((c1 >> 7) & 1U)); } /* 记录原始时间,测试结束恢复,避免把板子时间留在测试值 */ sd2506_time_t orig; int have_orig = (sd2506_get_time(&orig) == SD2506_OK); if (!have_orig) { DBG_INFO(" WARN: cannot read original time; restore step will be skipped"); } memset(&g_sd2506_test_stats, 0, sizeof(g_sd2506_test_stats)); #ifdef ENABLE_RTC_BASIC_TESTS sd2506_phase_basic(); #endif /* 恢复原始时间(用公共 API,写保护逻辑已由 sd2506.c 正确处理) */ if (have_orig) { int r = sd2506_set_time(&orig); DBG_INFO(" restored original time (ret=%d)", r); } DBG_INFO("SD2506 test suite done"); for (;;) { osDelay(1000); } } #endif /* TEST_SUITE_RTC */