1 /*
2 * Copyright (c) 2006-2025, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-08-14 Mr.Tiger first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "board.h"
14 #include <sys/time.h>
15 #include "hal_data.h"
16
17 #ifdef BSP_USING_ONCHIP_RTC
18
19 #define DBG_TAG "drv.rtc"
20 #ifdef DRV_DEBUG
21 #define DBG_LVL DBG_LOG
22 #else
23 #define DBG_LVL DBG_INFO
24 #endif /* DRV_DEBUG */
25 #include <rtdbg.h>
26
ra_rtc_init(void)27 static rt_err_t ra_rtc_init(void)
28 {
29 rt_err_t result = RT_EOK;
30
31 if (R_RTC_Open(&g_rtc_ctrl, &g_rtc_cfg) != RT_EOK)
32 {
33 LOG_E("rtc init failed.");
34 result = -RT_ERROR;
35 }
36
37 #if defined(SOC_SERIES_R9A07G0)
38 rtc_time_t default_set_time =
39 {
40 .tm_sec = 0,
41 .tm_min = 0,
42 .tm_hour = 0,
43 .tm_mday = 1,
44 .tm_wday = 1,
45 .tm_mon = 1,
46 .tm_year = 1900,
47 };
48
49 R_RTC_CalendarTimeSet(&g_rtc_ctrl, &default_set_time);
50 #endif
51 return result;
52 }
53
get_rtc_timestamp(void)54 static time_t get_rtc_timestamp(void)
55 {
56 struct tm tm_new = {0};
57 rtc_time_t g_current_time = {0};
58
59 R_RTC_CalendarTimeGet(&g_rtc_ctrl, &g_current_time);
60
61 tm_new.tm_year = g_current_time.tm_year;
62 tm_new.tm_mon = g_current_time.tm_mon;
63 tm_new.tm_mday = g_current_time.tm_mday;
64
65 tm_new.tm_hour = g_current_time.tm_hour;
66 tm_new.tm_min = g_current_time.tm_min;
67 tm_new.tm_sec = g_current_time.tm_sec;
68
69 tm_new.tm_wday = g_current_time.tm_wday;
70 tm_new.tm_yday = g_current_time.tm_yday;
71 tm_new.tm_isdst = g_current_time.tm_isdst;
72
73 return timegm(&tm_new);
74 }
75
ra_get_secs(time_t * sec)76 static rt_err_t ra_get_secs(time_t *sec)
77 {
78 *(rt_uint32_t *)sec = get_rtc_timestamp();
79 LOG_D("RTC: get rtc_time %x\n", *(rt_uint32_t *)sec);
80
81 return RT_EOK;
82 }
83
set_rtc_time_stamp(time_t time_stamp)84 static rt_err_t set_rtc_time_stamp(time_t time_stamp)
85 {
86 struct tm now;
87 rtc_time_t g_current_time = {0};
88 gmtime_r(&time_stamp, &now);
89 if (now.tm_year < 100)
90 {
91 return -RT_ERROR;
92 }
93
94 g_current_time.tm_sec = now.tm_sec ;
95 g_current_time.tm_min = now.tm_min ;
96 g_current_time.tm_hour = now.tm_hour;
97 g_current_time.tm_mday = now.tm_mday;
98 g_current_time.tm_mon = now.tm_mon;
99 g_current_time.tm_year = now.tm_year;
100 g_current_time.tm_wday = now.tm_wday;
101 g_current_time.tm_yday = now.tm_yday;
102
103 if (R_RTC_CalendarTimeSet(&g_rtc_ctrl, &g_current_time) != FSP_SUCCESS)
104 {
105 LOG_E("set rtc time failed.");
106 return -RT_ERROR;
107 }
108
109 return RT_EOK;
110 }
111
ra_set_secs(time_t * sec)112 static rt_err_t ra_set_secs(time_t *sec)
113 {
114
115 rt_err_t result = RT_EOK;
116
117 if (set_rtc_time_stamp(*(rt_uint32_t *)sec))
118 {
119 result = -RT_ERROR;
120 }
121 LOG_D("RTC: set rtc_time %x\n", *(rt_uint32_t *)sec);
122
123 return result;
124 }
125
126 #ifdef RT_USING_ALARM
ra_get_alarm(struct rt_rtc_wkalarm * alarm)127 static rt_err_t ra_get_alarm(struct rt_rtc_wkalarm *alarm)
128 {
129 rt_err_t result = RT_EOK;
130 struct rt_rtc_wkalarm *wkalarm = alarm;
131 rtc_alarm_time_t alarm_time_get =
132 {
133 .sec_match = RT_FALSE,
134 .min_match = RT_FALSE,
135 .hour_match = RT_FALSE,
136 .mday_match = RT_FALSE,
137 .mon_match = RT_FALSE,
138 .year_match = RT_FALSE,
139 .dayofweek_match = RT_FALSE,
140 };
141
142 if (RT_EOK == R_RTC_CalendarAlarmGet(&g_rtc_ctrl, &alarm_time_get))
143 {
144 wkalarm->tm_hour = alarm_time_get.time.tm_hour;
145 wkalarm->tm_min = alarm_time_get.time.tm_min;
146 wkalarm->tm_sec = alarm_time_get.time.tm_sec;
147 }
148 else
149 {
150 LOG_E("Calendar alarm Get failed.");
151 }
152
153 return result;
154 }
155
ra_set_alarm(struct rt_rtc_wkalarm * alarm)156 static rt_err_t ra_set_alarm(struct rt_rtc_wkalarm *alarm)
157 {
158 rt_err_t result = RT_EOK;
159 struct rt_rtc_wkalarm *wkalarm = alarm;
160 rtc_alarm_time_t alarm_time_set =
161 {
162 .sec_match = RT_TRUE,
163 .min_match = RT_TRUE,
164 .hour_match = RT_TRUE,
165 .mday_match = RT_FALSE,
166 .mon_match = RT_FALSE,
167 .year_match = RT_FALSE,
168 .dayofweek_match = RT_FALSE,
169 };
170
171 alarm_time_set.time.tm_hour = wkalarm->tm_hour;
172 alarm_time_set.time.tm_min = wkalarm->tm_min;
173 alarm_time_set.time.tm_sec = wkalarm->tm_sec;
174 if (1 == wkalarm->enable)
175 {
176 if (RT_EOK != R_RTC_CalendarAlarmSet(&g_rtc_ctrl, &alarm_time_set))
177 {
178 LOG_E("Calendar alarm Set failed.");
179 result = -RT_ERROR;
180 }
181 }
182 else
183 {
184 alarm_time_set.sec_match = RT_FALSE;
185 alarm_time_set.min_match = RT_FALSE;
186 alarm_time_set.hour_match = RT_FALSE;
187 if (RT_EOK != R_RTC_CalendarAlarmSet(&g_rtc_ctrl, &alarm_time_set))
188 {
189 LOG_E("Calendar alarm Stop failed.");
190 result = -RT_ERROR;
191 }
192 }
193 return result;
194 }
195 #endif /* RT_USING_ALARM */
196
rtc_callback(rtc_callback_args_t * p_args)197 void rtc_callback(rtc_callback_args_t *p_args)
198 {
199 #ifdef RT_USING_ALARM
200 static rt_device_t ra_device;
201 if (RTC_EVENT_ALARM_IRQ == p_args->event)
202 {
203 rt_alarm_update(ra_device, 1);
204 }
205 #endif
206 }
207
208 static const struct rt_rtc_ops ra_rtc_ops =
209 {
210 .init = ra_rtc_init,
211 .get_secs = ra_get_secs,
212 .set_secs = ra_set_secs,
213 #ifdef RT_USING_ALARM
214 .set_alarm = ra_set_alarm,
215 .get_alarm = ra_get_alarm,
216 #endif
217 };
218
219 static rt_rtc_dev_t ra_rtc_dev;
220
rt_hw_rtc_init(void)221 static int rt_hw_rtc_init(void)
222 {
223 rt_err_t result;
224
225 ra_rtc_dev.ops = &ra_rtc_ops;
226
227 result = rt_hw_rtc_register(&ra_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
228 if (result != RT_EOK)
229 {
230 LOG_E("rtc register err code: %d", result);
231 return result;
232 }
233 LOG_D("rtc init success");
234
235 return RT_EOK;
236 }
237 INIT_DEVICE_EXPORT(rt_hw_rtc_init);
238 #endif
239