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