1 /*
2 * Copyright (c) 2022 Bjarki Arge Andreasen
3 * Copyright (c) 2024 STMicroelectronics
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/ztest.h>
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/rtc.h>
11 #include <zephyr/sys/atomic.h>
12 #include <zephyr/sys/util.h>
13
14 #define RTC_TEST_ALARM_TEST_NOT_PENDING_DELAY (3)
15 #define RTC_TEST_ALARM_TEST_PENDING_DELAY (10)
16
17 static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
18 static const uint16_t alarms_count = DT_PROP(DT_ALIAS(rtc), alarms_count);
19 static const uint16_t test_alarm_time_mask_set = CONFIG_TEST_RTC_ALARM_TIME_MASK;
20
21 /* Fri Jan 01 2021 13:29:50 GMT+0000 */
22 static const struct rtc_time test_rtc_time_set = {
23 .tm_sec = 50,
24 .tm_min = 29,
25 .tm_hour = 13,
26 .tm_mday = 1,
27 .tm_mon = 0,
28 .tm_year = 121,
29 .tm_wday = 5,
30 .tm_yday = 1,
31 .tm_isdst = -1,
32 .tm_nsec = 0,
33 };
34
35 /* Fri Jan 01 2021 13:30:00 GMT+0000 */
36 static const struct rtc_time test_alarm_time_set = {
37 .tm_sec = 0,
38 .tm_min = 30,
39 .tm_hour = 13,
40 .tm_mday = 1,
41 .tm_mon = 0,
42 .tm_year = 121,
43 .tm_wday = 5,
44 .tm_yday = 1,
45 .tm_isdst = -1,
46 .tm_nsec = 0,
47 };
48
49 static const struct rtc_time test_alarm_time_invalid = {
50 .tm_sec = 70,
51 .tm_min = 70,
52 .tm_hour = 25,
53 .tm_mday = 35,
54 .tm_mon = 15,
55 .tm_year = 8000,
56 .tm_wday = 8,
57 .tm_yday = 370,
58 .tm_nsec = INT32_MAX,
59 };
60
61 static const uint16_t test_alarm_time_masks[] = {
62 RTC_ALARM_TIME_MASK_SECOND, RTC_ALARM_TIME_MASK_MINUTE,
63 RTC_ALARM_TIME_MASK_HOUR, RTC_ALARM_TIME_MASK_MONTHDAY,
64 RTC_ALARM_TIME_MASK_MONTH, RTC_ALARM_TIME_MASK_YEAR,
65 RTC_ALARM_TIME_MASK_WEEKDAY, RTC_ALARM_TIME_MASK_YEARDAY,
66 RTC_ALARM_TIME_MASK_NSEC
67 };
68
ZTEST(rtc_api,test_alarm)69 ZTEST(rtc_api, test_alarm)
70 {
71 int ret;
72 uint16_t alarm_time_mask_supported;
73 struct rtc_time alarm_time_get;
74 uint16_t alarm_time_mask_get;
75
76 /* Clear alarm alarm time */
77 for (uint16_t i = 0; i < alarms_count; i++) {
78 ret = rtc_alarm_set_time(rtc, i, 0, NULL);
79
80 zassert_ok(ret, "Failed to clear alarm %d time", i);
81 }
82
83 /* Disable alarm callback */
84 for (uint16_t i = 0; i < alarms_count; i++) {
85 ret = rtc_alarm_set_callback(rtc, i, NULL, NULL);
86
87 zassert_true((ret == 0) || (ret == -ENOTSUP),
88 "Failed to clear and disable alarm %d callback", i);
89 }
90
91 /* Every supported alarm field should reject invalid values. */
92 for (uint16_t i = 0; i < alarms_count; i++) {
93 ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported);
94 zassert_ok(ret, "Failed to get supported alarm %d fields", i);
95
96 ARRAY_FOR_EACH(test_alarm_time_masks, j)
97 {
98 if (test_alarm_time_masks[j] & alarm_time_mask_supported) {
99 ret = rtc_alarm_set_time(rtc, i, test_alarm_time_masks[j],
100 &test_alarm_time_invalid);
101 zassert_equal(
102 -EINVAL, ret,
103 "%s: RTC should reject invalid alarm %d time in field %zu.",
104 rtc->name, i, j);
105 }
106 }
107 }
108
109 /* Validate alarms supported fields */
110 for (uint16_t i = 0; i < alarms_count; i++) {
111 ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported);
112 zassert_ok(ret, "Failed to get supported alarm %d fields", i);
113
114 ret = (test_alarm_time_mask_set & (~alarm_time_mask_supported)) ? -EINVAL : 0;
115 zassert_ok(ret, "Configured alarm time fields to set are not supported");
116 }
117
118 for (uint16_t i = 0; i < alarms_count; i++) {
119 ret = rtc_alarm_set_time(rtc, i, test_alarm_time_mask_set, &test_alarm_time_set);
120 zassert_ok(ret, "Failed to set alarm %d time", i);
121 }
122
123 /* Validate alarm time */
124 for (uint16_t i = 0; i < alarms_count; i++) {
125 ret = rtc_alarm_get_time(rtc, i, &alarm_time_mask_get, &alarm_time_get);
126 zassert_ok(ret, "Failed to set alarm %d time", i);
127
128 zassert_equal(alarm_time_mask_get, test_alarm_time_mask_set,
129 "Incorrect alarm %d time mask", i);
130
131 if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_SECOND) {
132 zassert_equal(alarm_time_get.tm_sec, test_alarm_time_set.tm_sec,
133 "Incorrect alarm %d tm_sec field", i);
134 }
135
136 if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_MINUTE) {
137 zassert_equal(alarm_time_get.tm_min, test_alarm_time_set.tm_min,
138 "Incorrect alarm %d tm_min field", i);
139 }
140
141 if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_HOUR) {
142 zassert_equal(alarm_time_get.tm_hour, test_alarm_time_set.tm_hour,
143 "Incorrect alarm %d tm_hour field", i);
144 }
145
146 if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_MONTHDAY) {
147 zassert_equal(alarm_time_get.tm_mday, test_alarm_time_set.tm_mday,
148 "Incorrect alarm %d tm_mday field", i);
149 }
150
151 if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_MONTH) {
152 zassert_equal(alarm_time_get.tm_mon, test_alarm_time_set.tm_mon,
153 "Incorrect alarm %d tm_mon field", i);
154 }
155
156 if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_YEAR) {
157 zassert_equal(alarm_time_get.tm_year, test_alarm_time_set.tm_year,
158 "Incorrect alarm %d tm_year field", i);
159 }
160
161 if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_WEEKDAY) {
162 zassert_equal(alarm_time_get.tm_wday, test_alarm_time_set.tm_wday,
163 "Incorrect alarm %d tm_wday field", i);
164 }
165
166 if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_YEARDAY) {
167 zassert_equal(alarm_time_get.tm_yday, test_alarm_time_set.tm_yday,
168 "Incorrect alarm %d tm_yday field", i);
169 }
170
171 if (test_alarm_time_mask_set & RTC_ALARM_TIME_MASK_NSEC) {
172 zassert_equal(alarm_time_get.tm_nsec, test_alarm_time_set.tm_nsec,
173 "Incorrect alarm %d tm_nsec field", i);
174 }
175 }
176
177 for (uint8_t k = 0; k < 2; k++) {
178 /* Set RTC time */
179 ret = rtc_set_time(rtc, &test_rtc_time_set);
180 zassert_ok(ret, "Failed to set time");
181
182 /* Clear alarm pending status */
183 for (uint16_t i = 0; i < alarms_count; i++) {
184 ret = rtc_alarm_is_pending(rtc, i);
185 zassert_true(ret > -1, "Failed to clear alarm %d pending status", i);
186 }
187
188 /* Wait before validating alarm pending status has not been set prematurely */
189 k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_NOT_PENDING_DELAY));
190
191 /* Validate alarm are not pending */
192 for (uint16_t i = 0; i < alarms_count; i++) {
193 ret = rtc_alarm_is_pending(rtc, i);
194 zassert_ok(ret, "Alarm %d should not be pending", i);
195 }
196
197 /* Wait for alarm to trigger */
198 k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_PENDING_DELAY));
199
200 /* Validate alarm is pending */
201 for (uint16_t i = 0; i < alarms_count; i++) {
202 ret = rtc_alarm_is_pending(rtc, i);
203 zassert_equal(ret, 1, "Alarm %d should be pending", i);
204 }
205 }
206
207 /* Disable and clear alarms */
208 for (uint16_t i = 0; i < alarms_count; i++) {
209 ret = rtc_alarm_set_time(rtc, i, 0, NULL);
210 zassert_ok(ret, "Failed to disable alarm %d", i);
211
212 ret = rtc_alarm_is_pending(rtc, i);
213 zassert_true(ret > -1, "Failed to clear alarm %d pending state", i);
214 }
215 }
216