diff --git a/tests/periph/rtc/Makefile b/tests/periph/rtc/Makefile index a16ff91cda70..48f0b6eab9d8 100644 --- a/tests/periph/rtc/Makefile +++ b/tests/periph/rtc/Makefile @@ -1,12 +1,11 @@ include ../Makefile.periph_common FEATURES_REQUIRED += periph_rtc -FEATURES_OPTIONAL += periph_rtc_ms -FEATURES_OPTIONAL += periph_rtc_mem +FEATURES_OPTIONAL += periph_rtc_ms periph_rtc_mem DISABLE_MODULE += periph_init_rtc -USEMODULE += xtimer +USEMODULE += shell ztimer ztimer_msec # avoid running Kconfig by default SHOULD_RUN_KCONFIG ?= diff --git a/tests/periph/rtc/README.md b/tests/periph/rtc/README.md index 315220551055..2499c2915e7f 100644 --- a/tests/periph/rtc/README.md +++ b/tests/periph/rtc/README.md @@ -1,7 +1,41 @@ Expected result =============== -When everything works as expected, after start-up, 4 alarm messages are -displayed every 2 seconds. + +When running the test application execute the following commands and verify the +output. If `periph_rtc_mem` is not supported on the particular board go straight +to step 8. + +1. `rtc_clear` returns `RTC mem cleared` +2. `rtc_verify` returns `RTC mem content does not match` +3. `rtc_write` returns `RTC mem set` +4. `rtc_verify` returns `RTC mem OK` +5. `rtc_reboot` reboots device +6. `rtc_verify` returns `RTC mem OK` +7. `rtc_clear` returns `RTC mem cleared`. This is to clear RTC for the future. +8. `rtc_test_alarms` returns + +``` +This test will display 'Alarm!' every 2 seconds for 4 times +Clock value is now 2024-02-20 15:41:43.176 + Setting clock to 2020-02-28 23:59:57 +Clock value is now 2020-02-28 23:59:57.176 + Setting alarm to 2020-02-28 23:59:59 + Alarm is set to 2020-02-28 23:59:59 + Alarm cleared at 2020-02-28 23:59:57.176 + No alarm at 2020-02-28 23:59:59.176 + Setting alarm to 2020-02-28 23:59:61 + +Alarm! +Alarm! +Alarm! +Alarm! +``` + +This procedure is also included in the `tests/01-run.py` so `make test` on a +board that supports the `periph_rtc_mem` feature will execute the above steps. +On a board without `periph_rtc_mem` support, it will just execute the +`rtc_test_alarms`. + Background ========== diff --git a/tests/periph/rtc/main.c b/tests/periph/rtc/main.c index 3e5813350662..03803285b912 100644 --- a/tests/periph/rtc/main.c +++ b/tests/periph/rtc/main.c @@ -24,41 +24,44 @@ #include #include #include +#include "shell.h" #include "mutex.h" #include "periph_conf.h" #include "periph/rtc.h" #include "periph/rtc_mem.h" -#include "xtimer.h" +#include "ztimer.h" + +#ifdef MODULE_PERIPH_RTC_MEM +#include "periph/pm.h" +#endif #define PERIOD (2U) #define REPEAT (4U) #define TM_YEAR_OFFSET (1900) -static unsigned cnt = 0; - static void print_time(const char *label, const struct tm *time) { printf("%s %04d-%02d-%02d %02d:%02d:%02d\n", label, - time->tm_year + TM_YEAR_OFFSET, - time->tm_mon + 1, - time->tm_mday, - time->tm_hour, - time->tm_min, - time->tm_sec); + time->tm_year + TM_YEAR_OFFSET, + time->tm_mon + 1, + time->tm_mday, + time->tm_hour, + time->tm_min, + time->tm_sec); } static void print_time_ms(const char *label, const struct tm *time, uint16_t ms) { printf("%s %04d-%02d-%02d %02d:%02d:%02d.%03d\n", label, - time->tm_year + TM_YEAR_OFFSET, - time->tm_mon + 1, - time->tm_mday, - time->tm_hour, - time->tm_min, - time->tm_sec, - ms); + time->tm_year + TM_YEAR_OFFSET, + time->tm_mon + 1, + time->tm_mday, + time->tm_hour, + time->tm_min, + time->tm_sec, + ms); } static void inc_secs(struct tm *time, unsigned val) @@ -74,21 +77,52 @@ static void cb(void *arg) #ifdef MODULE_PERIPH_RTC_MEM static const uint8_t riot_msg_offset = 1; static const char riot_msg[] = "RIOT"; -static void _set_rtc_mem(void) + +static int _reboot(int arg, char **argv) +{ + (void)arg; + (void)argv; + puts("Rebooting"); + pm_reboot(); + return 0; +} +static int _clear_rtc_mem(int arg, char **argv) { + (void)arg; + (void)argv; + uint8_t pos = rtc_mem_size(); + uint8_t zero = 0; + + while (pos--) { + rtc_mem_write(zero, &zero, sizeof(zero)); + } + puts("RTC mem cleared"); + return 0; +} + +static int _set_rtc_mem(int arg, char **argv) +{ + (void)arg; + (void)argv; /* first fill the whole memory */ uint8_t size = rtc_mem_size(); + while (size--) { rtc_mem_write(size, &size, sizeof(size)); } /* write test data */ rtc_mem_write(riot_msg_offset, riot_msg, sizeof(riot_msg) - 1); + puts("RTC mem set"); + return 0; } -static void _get_rtc_mem(void) +static int _verify_rtc_mem(int arg, char **argv) { + (void)arg; + (void)argv; char buf[4]; + rtc_mem_read(riot_msg_offset, buf, sizeof(buf)); if (memcmp(buf, riot_msg, sizeof(buf))) { @@ -96,10 +130,11 @@ static void _get_rtc_mem(void) for (unsigned i = 0; i < sizeof(buf); ++i) { printf("%02x - %02x\n", riot_msg[i], buf[i]); } - return; + return -1; } uint8_t size = rtc_mem_size(); + while (size--) { uint8_t data; @@ -114,61 +149,54 @@ static void _get_rtc_mem(void) printf("%02x: %02x\n", size, data); } } - - puts("RTC mem OK"); + return 0; } -#else -static inline void _set_rtc_mem(void) {} -static inline void _get_rtc_mem(void) {} #endif - -int main(void) +static mutex_t rtc_mtx = MUTEX_INIT_LOCKED; +static int _test_alarms(int arg, char **argv) { - struct tm time = (struct tm){0}; - uint16_t ms; - - mutex_t rtc_mtx = MUTEX_INIT_LOCKED; + (void)arg; + (void)argv; - puts("\nRIOT RTC low-level driver test"); printf("This test will display 'Alarm!' every %u seconds for %u times\n", - PERIOD, REPEAT); - - rtc_init(); + PERIOD, REPEAT); - _set_rtc_mem(); - _get_rtc_mem(); + struct tm time = (struct tm){ 0 }; + uint16_t ms; - /* read RTC to retrieve initial */ +/* read RTC to retrieve initial */ if (IS_USED(MODULE_PERIPH_RTC_MS)) { rtc_get_time_ms(&time, &ms); print_time_ms("Clock value is now ", &time, ms); - } else { + } + else { rtc_get_time(&time); print_time("Clock value is now ", &time); } time = (struct tm){ .tm_year = 2020 - TM_YEAR_OFFSET, /* years are counted from 1900 */ - .tm_mon = 1, /* 0 = January, 11 = December */ + .tm_mon = 1, /* 0 = January, 11 = December */ .tm_mday = 28, .tm_hour = 23, - .tm_min = 59, - .tm_sec = 57 + .tm_min = 59, + .tm_sec = 57 }; /* set RTC */ print_time(" Setting clock to ", &time); rtc_set_time(&time); - time = (struct tm){0}; + time = (struct tm){ 0 }; ms = 0; /* read RTC to confirm value */ if (IS_USED(MODULE_PERIPH_RTC_MS)) { rtc_get_time_ms(&time, &ms); print_time_ms("Clock value is now ", &time, ms); - } else { + } + else { rtc_get_time(&time); print_time("Clock value is now ", &time); } @@ -178,14 +206,14 @@ int main(void) print_time(" Setting alarm to ", &time); rtc_set_alarm(&time, cb, &rtc_mtx); - time = (struct tm){0}; + time = (struct tm){ 0 }; ms = 0; /* verify alarm */ rtc_get_alarm(&time); print_time(" Alarm is set to ", &time); - time = (struct tm){0}; + time = (struct tm){ 0 }; ms = 0; /* clear alarm */ @@ -193,33 +221,37 @@ int main(void) if (IS_USED(MODULE_PERIPH_RTC_MS)) { rtc_get_time_ms(&time, &ms); print_time_ms(" Alarm cleared at ", &time, ms); - } else { + } + else { rtc_get_time(&time); print_time(" Alarm cleared at ", &time); } /* verify alarm has been cleared */ - xtimer_sleep(PERIOD); + ztimer_sleep(ZTIMER_MSEC, PERIOD*1000); const char *message; + if (mutex_trylock(&rtc_mtx)) { message = " Error: Alarm at "; - } else { + } + else { message = " No alarm at "; } - time = (struct tm){0}; + time = (struct tm){ 0 }; ms = 0; if (IS_USED(MODULE_PERIPH_RTC_MS)) { rtc_get_time_ms(&time, &ms); print_time_ms(message, &time, ms); - } else { + } + else { rtc_get_time(&time); print_time(message, &time); } - time = (struct tm){0}; + time = (struct tm){ 0 }; ms = 0; /* set alarm */ @@ -230,17 +262,41 @@ int main(void) puts(""); /* loop over a few alarm cycles */ + unsigned int cnt = 0; + do { mutex_lock(&rtc_mtx); puts("Alarm!"); - struct tm time; + struct tm time = { 0 }; rtc_get_alarm(&time); inc_secs(&time, PERIOD); rtc_set_alarm(&time, cb, &rtc_mtx); } while (++cnt < REPEAT); + return 0; +} + +static const shell_command_t commands[] = { +#ifdef MODULE_PERIPH_RTC_MEM + { "rtc_reboot", "reboots the MCU", _reboot }, + { "rtc_clear", "clears the RTC memory", _clear_rtc_mem }, + { "rtc_verify", "verifies the RTC memory", _verify_rtc_mem }, + { "rtc_write", "writes to the RTC memory", _set_rtc_mem }, +#endif + { "rtc_test_alarms", "tests RTC alarms", _test_alarms }, + { NULL, NULL, NULL } +}; - _get_rtc_mem(); +int main(void) +{ + + puts(""); + puts("RIOT RTC low-level driver test"); + puts("Write help to see available commands"); + + rtc_init(); + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(commands, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/tests/periph/rtc/tests/01-run.py b/tests/periph/rtc/tests/01-run.py index 9ffda2c6b44d..1cd97e265211 100755 --- a/tests/periph/rtc/tests/01-run.py +++ b/tests/periph/rtc/tests/01-run.py @@ -13,9 +13,33 @@ BOARD = os.getenv('BOARD', 'native') DATE_PATTERN = r'\d{4}\-\d{2}\-\d{2} \d{2}\:\d{2}\:\d{2}' +TEST_RTC_MEM = 'periph_rtc_mem' in os.getenv('FEATURES_USED', '') -def testfunc(child): +def test_rtc_mem(child): + child.sendline("rtc_clear") + child.expect("RTC mem cleared") + + child.sendline("rtc_verify") + child.expect("RTC mem content does not match") + + child.sendline("rtc_write") + child.expect("RTC mem set") + + child.sendline("rtc_verify") + child.expect("RTC mem OK") + + child.sendline("rtc_reboot") + child.expect("Rebooting") + + child.sendline("rtc_verify") + child.expect("RTC mem OK") + + child.sendline("rtc_clear") + + +def test_alarm(child): + child.sendline("rtc_test_alarms") child.expect(r'This test will display \'Alarm\!\' every 2 seconds ' r'for (\d{1}) times') alarm_count = int(child.match.group(1)) @@ -43,6 +67,10 @@ def testfunc(child): for _ in range(alarm_count): child.expect_exact('Alarm!') + child.expect_exact(">") + if __name__ == "__main__": - sys.exit(run(testfunc)) + if TEST_RTC_MEM: + run(test_rtc_mem) + sys.exit(run(test_alarm))