Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests/periph/rtc: Add rtc mem survive reset test #20404

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions tests/periph/rtc/Makefile
Original file line number Diff line number Diff line change
@@ -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 ?=
Expand Down
38 changes: 36 additions & 2 deletions tests/periph/rtc/README.md
Original file line number Diff line number Diff line change
@@ -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
==========
Expand Down
162 changes: 109 additions & 53 deletions tests/periph/rtc/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,44 @@
#include <stdio.h>
#include <time.h>
#include <string.h>
#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)
Expand All @@ -74,32 +77,64 @@ 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))) {
puts("RTC mem content does not match");
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;

Expand All @@ -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);
}
Expand All @@ -178,48 +206,52 @@ 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 */
rtc_clear_alarm();
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 */
Expand All @@ -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;
}
Loading
Loading