Commit 5343ae68 authored by Bjarki Arge Andreasen's avatar Bjarki Arge Andreasen Committed by Anas Nashif
Browse files

tests: drivers: rtc: rtc_api: add config for alarm time mask

RTCs support a variety of combinations of alarm time fields, set
by the alarm time mask. Until now, alarm tests have selected
only the minute and hour fields, as these are always supported,
but some RTCs require setting every supported field when setting
the alarm time, while other RTCs don't support setting every field.

To support all RTCs in the test suite, a configuration has been
added which makes the alarm time mask configurable. Boards can now
define the specific alarm time mask they want to test within
their boards .conf files.

Additionally, the alarm tests have been refactored to not depend
on the time.h library to determine the struct rtc_time times to
set as these are constant, so they are now provided as const
structs instead.

Signed-off-by: default avatarBjarki Arge Andreasen <bjarki@arge-andreasen.me>
parent 90ab94f6
Loading
Loading
Loading
Loading
+16 −0
Changes for tests/drivers/rtc/rtc_api/Kconfig: 16 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Copyright (c) 2024 Bjarki Arge Andreasen
# SPDX-License-Identifier: Apache-2.0

source "Kconfig.zephyr"

if RTC_ALARM

config TEST_RTC_ALARM_TIME_MASK
	int "Alarm fields to set"
	default 6
	range 1 511
	help
	  Set the RTC_ALARM_TIME_MASK_ bitmask to use when setting
	  RTC alarms during testing.

endif # RTC_ALARM
+98 −62
Changes for tests/drivers/rtc/rtc_api/src/test_alarm.c: 98 added lines, 62 removed lines.
Original line number Diff line number Diff line
@@ -9,29 +9,67 @@
#include <zephyr/device.h>
#include <zephyr/drivers/rtc.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/sys/timeutil.h>
#include <zephyr/sys/util.h>

#include <time.h>

/* Fri Jan 01 2021 13:29:50 GMT+0000 */
#define RTC_TEST_ALARM_SET_TIME		      (1609507790)
#define RTC_TEST_ALARM_TEST_NOT_PENDING_DELAY (3)
#define RTC_TEST_ALARM_TEST_PENDING_DELAY     (10)
#define RTC_TEST_ALARM_TIME_MINUTE	      (30)
#define RTC_TEST_ALARM_TIME_HOUR	      (13)

static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
static const uint16_t alarms_count = DT_PROP(DT_ALIAS(rtc), alarms_count);
static const uint16_t test_alarm_time_mask_set = CONFIG_TEST_RTC_ALARM_TIME_MASK;

/* Fri Jan 01 2021 13:29:50 GMT+0000 */
static const struct rtc_time test_rtc_time_set = {
	.tm_sec = 50,
	.tm_min = 29,
	.tm_hour = 13,
	.tm_mday = 1,
	.tm_mon = 0,
	.tm_year = 121,
	.tm_wday = 5,
	.tm_yday = 1,
	.tm_isdst = -1,
	.tm_nsec = 0,
};

/* Fri Jan 01 2021 13:30:00 GMT+0000 */
static const struct rtc_time test_alarm_time_set = {
	.tm_sec = 0,
	.tm_min = 30,
	.tm_hour = 13,
	.tm_mday = 1,
	.tm_mon = 0,
	.tm_year = 121,
	.tm_wday = 5,
	.tm_yday = 1,
	.tm_isdst = -1,
	.tm_nsec = 0,
};

static const struct rtc_time test_alarm_time_invalid = {
	.tm_sec = 70,
	.tm_min = 70,
	.tm_hour = 25,
	.tm_mday = 35,
	.tm_mon = 15,
	.tm_year = 8000,
	.tm_wday = 8,
	.tm_yday = 370,
	.tm_nsec = INT32_MAX,
};

static const uint16_t test_alarm_time_masks[] = {
	RTC_ALARM_TIME_MASK_SECOND,  RTC_ALARM_TIME_MASK_MINUTE,
	RTC_ALARM_TIME_MASK_HOUR,    RTC_ALARM_TIME_MASK_MONTHDAY,
	RTC_ALARM_TIME_MASK_MONTH,   RTC_ALARM_TIME_MASK_YEAR,
	RTC_ALARM_TIME_MASK_WEEKDAY, RTC_ALARM_TIME_MASK_YEARDAY,
	RTC_ALARM_TIME_MASK_NSEC
};

ZTEST(rtc_api, test_alarm)
{
	int ret;
	time_t timer_set;
	struct rtc_time time_set;
	struct rtc_time alarm_time_set;
	uint16_t alarm_time_mask_supported;
	uint16_t alarm_time_mask_set;
	struct rtc_time alarm_time_get;
	uint16_t alarm_time_mask_get;

@@ -53,29 +91,13 @@ ZTEST(rtc_api, test_alarm)
	/* Every supported alarm field should reject invalid values. */
	for (uint16_t i = 0; i < alarms_count; i++) {
		ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported);

		zassert_ok(ret, "Failed to get supported alarm %d fields", i);

		alarm_time_set = (struct rtc_time) {
			.tm_sec = 70,
			.tm_min = 70,
			.tm_hour = 25,
			.tm_mday = 35,
			.tm_mon = 15,
			.tm_year = 8000,
			.tm_wday = 8,
			.tm_yday = 370,
			.tm_nsec = INT32_MAX,
		};
		uint16_t masks[] = {RTC_ALARM_TIME_MASK_SECOND,  RTC_ALARM_TIME_MASK_MINUTE,
				    RTC_ALARM_TIME_MASK_HOUR,    RTC_ALARM_TIME_MASK_MONTHDAY,
				    RTC_ALARM_TIME_MASK_MONTH,   RTC_ALARM_TIME_MASK_YEAR,
				    RTC_ALARM_TIME_MASK_WEEKDAY, RTC_ALARM_TIME_MASK_YEARDAY,
				    RTC_ALARM_TIME_MASK_NSEC};
		ARRAY_FOR_EACH(masks, j)
		ARRAY_FOR_EACH(test_alarm_time_masks, j)
		{
			if (masks[j] & alarm_time_mask_supported) {
				ret = rtc_alarm_set_time(rtc, i, masks[j], &alarm_time_set);
			if (test_alarm_time_masks[j] & alarm_time_mask_supported) {
				ret = rtc_alarm_set_time(rtc, i, test_alarm_time_masks[j],
							 &test_alarm_time_invalid);
				zassert_equal(
					-EINVAL, ret,
					"%s: RTC should reject invalid alarm %d time in field %zu.",
@@ -87,61 +109,79 @@ ZTEST(rtc_api, test_alarm)
	/* Validate alarms supported fields */
	for (uint16_t i = 0; i < alarms_count; i++) {
		ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported);

		zassert_ok(ret, "Failed to get supported alarm %d fields", i);

		/* Skip test if alarm does not support the minute and hour fields */
		if (((RTC_ALARM_TIME_MASK_MINUTE & alarm_time_mask_supported) == 0) ||
		((RTC_TEST_ALARM_TIME_HOUR & alarm_time_mask_supported) == 0)) {
			ztest_test_skip();
		}
		ret = (test_alarm_time_mask_set & (~alarm_time_mask_supported)) ? -EINVAL : 0;
		zassert_ok(ret, "Configured alarm time fields to set are not supported");
	}

	/* Set alarm time */
	alarm_time_set.tm_min = RTC_TEST_ALARM_TIME_MINUTE;
	alarm_time_set.tm_hour = RTC_TEST_ALARM_TIME_HOUR;
	alarm_time_mask_set = (RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR);

	for (uint16_t i = 0; i < alarms_count; i++) {
		ret = rtc_alarm_set_time(rtc, i, alarm_time_mask_set, &alarm_time_set);

		ret = rtc_alarm_set_time(rtc, i, test_alarm_time_mask_set, &test_alarm_time_set);
		zassert_ok(ret, "Failed to set alarm %d time", i);
	}

	/* Validate alarm time */
	for (uint16_t i = 0; i < alarms_count; i++) {
		ret = rtc_alarm_get_time(rtc, i, &alarm_time_mask_get, &alarm_time_get);

		zassert_ok(ret, "Failed to set alarm %d time", i);

		zassert_equal(alarm_time_mask_get, alarm_time_mask_set,
		zassert_equal(alarm_time_mask_get, test_alarm_time_mask_set,
			      "Incorrect alarm %d time mask", i);

		zassert_equal(alarm_time_get.tm_min, alarm_time_set.tm_min,
			      "Incorrect alarm %d time minute field", i);
		if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_SECOND) {
			zassert_equal(alarm_time_get.tm_sec, test_alarm_time_set.tm_sec,
				      "Incorrect alarm %d tm_sec field", i);
		}

		if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_MINUTE) {
			zassert_equal(alarm_time_get.tm_min, test_alarm_time_set.tm_min,
				      "Incorrect alarm %d tm_min field", i);
		}

		if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_HOUR) {
			zassert_equal(alarm_time_get.tm_hour, test_alarm_time_set.tm_hour,
				      "Incorrect alarm %d tm_hour field", i);
		}

		if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_MONTHDAY) {
			zassert_equal(alarm_time_get.tm_mday, test_alarm_time_set.tm_mday,
				      "Incorrect alarm %d tm_mday field", i);
		}

		zassert_equal(alarm_time_get.tm_hour, alarm_time_set.tm_hour,
			      "Incorrect alarm %d time hour field", i);
		if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_MONTH) {
			zassert_equal(alarm_time_get.tm_mon, test_alarm_time_set.tm_mon,
				      "Incorrect alarm %d tm_mon field", i);
		}

	/* Initialize RTC time to set */
	timer_set = RTC_TEST_ALARM_SET_TIME;
		if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_YEAR) {
			zassert_equal(alarm_time_get.tm_year, test_alarm_time_set.tm_year,
				      "Incorrect alarm %d tm_year field", i);
		}

	gmtime_r(&timer_set, (struct tm *)(&time_set));
		if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_WEEKDAY) {
			zassert_equal(alarm_time_get.tm_wday, test_alarm_time_set.tm_wday,
				      "Incorrect alarm %d tm_wday field", i);
		}

	time_set.tm_isdst = -1;
	time_set.tm_nsec = 0;
		if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_YEARDAY) {
			zassert_equal(alarm_time_get.tm_yday, test_alarm_time_set.tm_yday,
				      "Incorrect alarm %d tm_yday field", i);
		}

		if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_NSEC) {
			zassert_equal(alarm_time_get.tm_nsec, test_alarm_time_set.tm_nsec,
				      "Incorrect alarm %d tm_nsec field", i);
		}
	}

	for (uint8_t k = 0; k < 2; k++) {
		/* Set RTC time */
		ret = rtc_set_time(rtc, &time_set);

		ret = rtc_set_time(rtc, &test_rtc_time_set);
		zassert_ok(ret, "Failed to set time");

		/* Clear alarm pending status */
		for (uint16_t i = 0; i < alarms_count; i++) {
			ret = rtc_alarm_is_pending(rtc, i);

			zassert_true(ret > -1, "Failed to clear alarm %d pending status", i);
		}

@@ -151,7 +191,6 @@ ZTEST(rtc_api, test_alarm)
		/* Validate alarm are not pending */
		for (uint16_t i = 0; i < alarms_count; i++) {
			ret = rtc_alarm_is_pending(rtc, i);

			zassert_ok(ret, "Alarm %d should not be pending", i);
		}

@@ -161,7 +200,6 @@ ZTEST(rtc_api, test_alarm)
		/* Validate alarm is pending */
		for (uint16_t i = 0; i < alarms_count; i++) {
			ret = rtc_alarm_is_pending(rtc, i);

			zassert_equal(ret, 1, "Alarm %d should be pending", i);
		}
	}
@@ -169,11 +207,9 @@ ZTEST(rtc_api, test_alarm)
	/* Disable and clear alarms */
	for (uint16_t i = 0; i < alarms_count; i++) {
		ret = rtc_alarm_set_time(rtc, i, 0, NULL);

		zassert_ok(ret, "Failed to disable alarm %d", i);

		ret = rtc_alarm_is_pending(rtc, i);

		zassert_true(ret > -1, "Failed to clear alarm %d pending state", i);
	}
}
+33 −48
Changes for tests/drivers/rtc/rtc_api/src/test_alarm_callback.c: 33 added lines, 48 removed lines.
Original line number Diff line number Diff line
@@ -9,16 +9,9 @@
#include <zephyr/device.h>
#include <zephyr/drivers/rtc.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/sys/timeutil.h>

#include <time.h>

/* Fri Jan 01 2021 13:29:50 GMT+0000 */
#define RTC_TEST_ALARM_SET_TIME		     (1609507790)
#define RTC_TEST_ALARM_TEST_NOT_CALLED_DELAY (3)
#define RTC_TEST_ALARM_TEST_CALLED_DELAY     (10)
#define RTC_TEST_ALARM_TIME_MINUTE	     (30)
#define RTC_TEST_ALARM_TIME_HOUR	     (13)

static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
static const uint16_t alarms_count = DT_PROP(DT_ALIAS(rtc), alarms_count);
@@ -27,6 +20,36 @@ static uint32_t callback_user_data_even = 0x1234;
static atomic_t callback_called_mask_odd;
static atomic_t callback_called_mask_even;

static const uint16_t test_alarm_time_mask_set = CONFIG_TEST_RTC_ALARM_TIME_MASK;

/* Fri Jan 01 2021 13:29:50 GMT+0000 */
static const struct rtc_time test_rtc_time_set = {
	.tm_sec = 50,
	.tm_min = 29,
	.tm_hour = 13,
	.tm_mday = 1,
	.tm_mon = 0,
	.tm_year = 121,
	.tm_wday = 5,
	.tm_yday = 1,
	.tm_isdst = -1,
	.tm_nsec = 0,
};

/* Fri Jan 01 2021 13:30:00 GMT+0000 */
static const struct rtc_time test_alarm_time_set = {
	.tm_sec = 0,
	.tm_min = 30,
	.tm_hour = 13,
	.tm_mday = 1,
	.tm_mon = 0,
	.tm_year = 121,
	.tm_wday = 5,
	.tm_yday = 1,
	.tm_isdst = -1,
	.tm_nsec = 0,
};

static void test_rtc_alarm_callback_handler_odd(const struct device *dev, uint16_t id,
						void *user_data)
{
@@ -42,11 +65,6 @@ static void test_rtc_alarm_callback_handler_even(const struct device *dev, uint1
ZTEST(rtc_api, test_alarm_callback)
{
	int ret;
	time_t timer_set;
	struct rtc_time time_set;
	struct rtc_time alarm_time_set;
	uint16_t alarm_time_mask_supported;
	uint16_t alarm_time_mask_set;
	atomic_val_t callback_called_mask_status_odd;
	atomic_val_t callback_called_mask_status_even;
	bool callback_called_status;
@@ -63,47 +81,18 @@ ZTEST(rtc_api, test_alarm_callback)
		}
	}

	/* Validate alarms supported fields */
	for (uint16_t i = 0; i < alarms_count; i++) {
		ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported);

		zassert_ok(ret, "Failed to get supported alarm %d fields", i);

		/* Skip test if alarm does not support the minute and hour fields */
		if (((RTC_ALARM_TIME_MASK_MINUTE & alarm_time_mask_supported) == 0) ||
		((RTC_TEST_ALARM_TIME_HOUR & alarm_time_mask_supported) == 0)) {
			ztest_test_skip();
		}
	}

	/* Set alarm time */
	alarm_time_set.tm_min = RTC_TEST_ALARM_TIME_MINUTE;
	alarm_time_set.tm_hour = RTC_TEST_ALARM_TIME_HOUR;
	alarm_time_mask_set = (RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR);

	for (uint16_t i = 0; i < alarms_count; i++) {
		ret = rtc_alarm_set_time(rtc, i, alarm_time_mask_set, &alarm_time_set);

		ret = rtc_alarm_set_time(rtc, i, test_alarm_time_mask_set, &test_alarm_time_set);
		zassert_ok(ret, "Failed to set alarm %d time", i);
	}

	/* Initialize RTC time to set */
	timer_set = RTC_TEST_ALARM_SET_TIME;

	gmtime_r(&timer_set, (struct tm *)(&time_set));

	time_set.tm_isdst = -1;
	time_set.tm_nsec = 0;

	/* Set RTC time */
	ret = rtc_set_time(rtc, &time_set);

	ret = rtc_set_time(rtc, &test_rtc_time_set);
	zassert_ok(ret, "Failed to set time");

	/* Clear alarm pending status */
	for (uint16_t i = 0; i < alarms_count; i++) {
		ret = rtc_alarm_is_pending(rtc, i);

		zassert_true(ret > -1, "Failed to clear alarm %d pending status", i);
	}

@@ -153,23 +142,19 @@ ZTEST(rtc_api, test_alarm_callback)
		}

		/* Reset RTC time */
		ret = rtc_set_time(rtc, &time_set);

		ret = rtc_set_time(rtc, &test_rtc_time_set);
		zassert_ok(ret, "Failed to set time");
	}

	/* Disable and clear alarms */
	for (uint16_t i = 0; i < alarms_count; i++) {
		ret = rtc_alarm_set_callback(rtc, i, NULL, NULL);

		zassert_ok(ret, "Failed to disable alarm %d callback", i);

		ret = rtc_alarm_set_time(rtc, i, 0, NULL);

		zassert_ok(ret, "Failed to disable alarm %d", i);

		ret = rtc_alarm_is_pending(rtc, i);

		zassert_true(ret > -1, "Failed to clear alarm %d pending state", i);
	}
}