/* * Copyright 2022 Bjarki Arge Andreasen * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include /* 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); 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; /* Clear alarm alarm time */ for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_set_time(rtc, i, 0, NULL); zassert_ok(ret, "Failed to clear alarm time"); } /* Disable alarm callback */ for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_set_callback(rtc, i, NULL, NULL); zassert_true((ret == 0) || (ret == -ENOTSUP), "Failed to clear and disable alarm callback"); } /* 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 fields"); 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) { if (masks[j] & alarm_time_mask_supported) { ret = rtc_alarm_set_time(rtc, i, masks[j], &alarm_time_set); zassert_equal( -EINVAL, ret, "%s: RTC should reject invalid alarm time in field %zu.", rtc->name, j); } } } /* 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 fields"); /* 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); zassert_ok(ret, "Failed to set alarm time"); } /* 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 time"); zassert_equal(alarm_time_mask_get, alarm_time_mask_set, "Incorrect alarm time mask"); zassert_equal(alarm_time_get.tm_min, alarm_time_set.tm_min, "Incorrect alarm time minute field"); zassert_equal(alarm_time_get.tm_hour, alarm_time_set.tm_hour, "Incorrect alarm time hour field"); } /* 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; for (uint8_t k = 0; k < 2; k++) { /* Set RTC time */ ret = rtc_set_time(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 pending status"); } /* Wait before validating alarm pending status has not been set prematurely */ k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_NOT_PENDING_DELAY)); /* 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 should not be pending"); } /* Wait for alarm to trigger */ k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_PENDING_DELAY)); /* 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 should be pending"); } } /* 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"); ret = rtc_alarm_is_pending(rtc, i); zassert_true(ret > -1, "Failed to clear alarm pending state"); } }