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 
13 #define RTC_TEST_ALARM_TEST_NOT_CALLED_DELAY (3)
14 #define RTC_TEST_ALARM_TEST_CALLED_DELAY     (10)
15 
16 static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
17 static const uint16_t alarms_count = DT_PROP(DT_ALIAS(rtc), alarms_count);
18 static uint32_t callback_user_data_odd = 0x4321;
19 static uint32_t callback_user_data_even = 0x1234;
20 static atomic_t callback_called_mask_odd;
21 static atomic_t callback_called_mask_even;
22 
23 static const uint16_t test_alarm_time_mask_set = CONFIG_TEST_RTC_ALARM_TIME_MASK;
24 
25 /* Fri Jan 01 2021 13:29:50 GMT+0000 */
26 static const struct rtc_time test_rtc_time_set = {
27 	.tm_sec = 50,
28 	.tm_min = 29,
29 	.tm_hour = 13,
30 	.tm_mday = 1,
31 	.tm_mon = 0,
32 	.tm_year = 121,
33 	.tm_wday = 5,
34 	.tm_yday = 1,
35 	.tm_isdst = -1,
36 	.tm_nsec = 0,
37 };
38 
39 /* Fri Jan 01 2021 13:30:00 GMT+0000 */
40 static const struct rtc_time test_alarm_time_set = {
41 	.tm_sec = 0,
42 	.tm_min = 30,
43 	.tm_hour = 13,
44 	.tm_mday = 1,
45 	.tm_mon = 0,
46 	.tm_year = 121,
47 	.tm_wday = 5,
48 	.tm_yday = 1,
49 	.tm_isdst = -1,
50 	.tm_nsec = 0,
51 };
52 
test_rtc_alarm_callback_handler_odd(const struct device * dev,uint16_t id,void * user_data)53 static void test_rtc_alarm_callback_handler_odd(const struct device *dev, uint16_t id,
54 						void *user_data)
55 {
56 	atomic_set_bit(&callback_called_mask_odd, id);
57 }
58 
test_rtc_alarm_callback_handler_even(const struct device * dev,uint16_t id,void * user_data)59 static void test_rtc_alarm_callback_handler_even(const struct device *dev, uint16_t id,
60 						 void *user_data)
61 {
62 	atomic_set_bit(&callback_called_mask_even, id);
63 }
64 
ZTEST(rtc_api,test_alarm_callback)65 ZTEST(rtc_api, test_alarm_callback)
66 {
67 	int ret;
68 	atomic_val_t callback_called_mask_status_odd;
69 	atomic_val_t callback_called_mask_status_even;
70 	bool callback_called_status;
71 
72 	/* Disable alarm callback */
73 	for (uint16_t i = 0; i < alarms_count; i++) {
74 		ret = rtc_alarm_set_callback(rtc, i, NULL, NULL);
75 
76 		if (ret == -ENOTSUP) {
77 			TC_PRINT("Alarm callbacks not supported\n");
78 			ztest_test_skip();
79 		} else {
80 			zassert_ok(ret, "Failed to clear and disable alarm %d", i);
81 		}
82 	}
83 
84 	for (uint16_t i = 0; i < alarms_count; i++) {
85 		ret = rtc_alarm_set_time(rtc, i, test_alarm_time_mask_set, &test_alarm_time_set);
86 		zassert_ok(ret, "Failed to set alarm %d time", i);
87 	}
88 
89 	/* Set RTC time */
90 	ret = rtc_set_time(rtc, &test_rtc_time_set);
91 	zassert_ok(ret, "Failed to set time");
92 
93 	/* Clear alarm pending status */
94 	for (uint16_t i = 0; i < alarms_count; i++) {
95 		ret = rtc_alarm_is_pending(rtc, i);
96 		zassert_true(ret > -1, "Failed to clear alarm %d pending status", i);
97 	}
98 
99 	/* Set and enable alarm callback */
100 	for (uint16_t i = 0; i < alarms_count; i++) {
101 		if (i % 2) {
102 			ret = rtc_alarm_set_callback(rtc, i,
103 						test_rtc_alarm_callback_handler_odd,
104 						&callback_user_data_odd);
105 		} else {
106 			ret = rtc_alarm_set_callback(rtc, i,
107 						test_rtc_alarm_callback_handler_even,
108 						&callback_user_data_even);
109 		}
110 
111 		zassert_ok(ret, "Failed to set alarm %d callback", i);
112 	}
113 
114 	for (uint8_t i = 0; i < 2; i++) {
115 		/* Clear callback called atomics */
116 		atomic_set(&callback_called_mask_odd, 0);
117 		atomic_set(&callback_called_mask_even, 0);
118 
119 		/* Wait before validating alarm callbacks have not been called prematurely */
120 		k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_NOT_CALLED_DELAY));
121 
122 		/* Validate alarm callbacks have not been called prematurely */
123 		callback_called_mask_status_odd = atomic_get(&callback_called_mask_odd);
124 		callback_called_mask_status_even = atomic_get(&callback_called_mask_even);
125 
126 		zassert_equal(callback_called_mask_status_odd, 0,
127 			      "Alarm callback called prematurely");
128 		zassert_equal(callback_called_mask_status_even, 0,
129 			      "Alarm callback called prematurely");
130 
131 		/* Wait for alarm to trigger */
132 		k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_CALLED_DELAY));
133 
134 		/* Validate alarm callback called */
135 		for (uint16_t j = 0; j < alarms_count; j++) {
136 			callback_called_status =
137 				(j % 2) ? atomic_test_bit(&callback_called_mask_odd, j)
138 					: atomic_test_bit(&callback_called_mask_even, j);
139 
140 			zassert_equal(callback_called_status, true,
141 				      "Alarm %d callback should have been called", j);
142 		}
143 
144 		/* Reset RTC time */
145 		ret = rtc_set_time(rtc, &test_rtc_time_set);
146 		zassert_ok(ret, "Failed to set time");
147 	}
148 
149 	/* Disable and clear alarms */
150 	for (uint16_t i = 0; i < alarms_count; i++) {
151 		ret = rtc_alarm_set_callback(rtc, i, NULL, NULL);
152 		zassert_ok(ret, "Failed to disable alarm %d callback", i);
153 
154 		ret = rtc_alarm_set_time(rtc, i, 0, NULL);
155 		zassert_ok(ret, "Failed to disable alarm %d", i);
156 
157 		ret = rtc_alarm_is_pending(rtc, i);
158 		zassert_true(ret > -1, "Failed to clear alarm %d pending state", i);
159 	}
160 }
161