1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2018-03-15 Liuguang the first version.
9 * 2019-04-22 tyustli add imxrt series support
10 *
11 */
12 #include <rtthread.h>
13 #include <rtdevice.h>
14 #include <sys/time.h>
15 #ifdef BSP_USING_RTC
16
17 #define LOG_TAG "drv.rtc"
18 #include <drv_log.h>
19
20 #include "drv_rtc.h"
21 #include "fsl_snvs_hp.h"
22 #include "fsl_snvs_lp.h"
23 #include <sys/time.h>
24
25 #if defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
26 #error "Please don't define 'FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL'!"
27 #endif
28
imxrt_hp_get_timestamp(void)29 static time_t imxrt_hp_get_timestamp(void)
30 {
31 struct tm tm_new = {0};
32 snvs_hp_rtc_datetime_t rtcDate = {0};
33 snvs_lp_srtc_datetime_t srtcDate = {0};
34
35 SNVS_LP_SRTC_GetDatetime(SNVS, &srtcDate);
36 SNVS_HP_RTC_TimeSynchronize(SNVS);
37 SNVS_HP_RTC_GetDatetime(SNVS, &rtcDate);
38
39 tm_new.tm_sec = rtcDate.second;
40 tm_new.tm_min = rtcDate.minute;
41 tm_new.tm_hour = rtcDate.hour;
42
43 tm_new.tm_mday = rtcDate.day;
44 tm_new.tm_mon = rtcDate.month - 1;
45 tm_new.tm_year = rtcDate.year - 1900;
46
47 return timegm(&tm_new);
48 }
49
imxrt_hp_set_timestamp(time_t timestamp)50 static int imxrt_hp_set_timestamp(time_t timestamp)
51 {
52 struct tm now;
53 snvs_lp_srtc_datetime_t srtcDate = {0};
54
55 gmtime_r(×tamp, &now);
56
57 srtcDate.second = now.tm_sec;
58 srtcDate.minute = now.tm_min;
59 srtcDate.hour = now.tm_hour;
60
61 srtcDate.day = now.tm_mday;
62 srtcDate.month = now.tm_mon + 1;
63 srtcDate.year = now.tm_year + 1900;
64
65
66 if (SNVS_LP_SRTC_SetDatetime(SNVS, &srtcDate) != kStatus_Success)
67 {
68 LOG_E("set rtc date time failed\n");
69 return -RT_ERROR;
70 }
71
72 SNVS_HP_RTC_TimeSynchronize(SNVS);
73
74 return RT_EOK;
75 }
76
imxrt_hp_rtc_init(rt_device_t dev)77 static rt_err_t imxrt_hp_rtc_init(rt_device_t dev)
78 {
79 snvs_hp_rtc_config_t snvsRtcConfig;
80 snvs_lp_srtc_config_t snvsSrtcConfig;
81
82 /* Init SNVS_HP */
83 SNVS_HP_RTC_GetDefaultConfig(&snvsRtcConfig);
84 SNVS_HP_RTC_Init(SNVS, &snvsRtcConfig);
85
86 /* Init SNVS_LP */
87 SNVS_LP_SRTC_GetDefaultConfig(&snvsSrtcConfig);
88 SNVS_LP_SRTC_Init(SNVS, &snvsSrtcConfig);
89 return RT_EOK;
90 }
91
imxrt_hp_rtc_open(rt_device_t dev,rt_uint16_t oflag)92 static rt_err_t imxrt_hp_rtc_open(rt_device_t dev, rt_uint16_t oflag)
93 {
94 SNVS_HP_RTC_StartTimer(SNVS);
95 SNVS_LP_SRTC_StartTimer(SNVS);
96 return RT_EOK;
97 }
98
imxrt_hp_rtc_close(rt_device_t dev)99 static rt_err_t imxrt_hp_rtc_close(rt_device_t dev)
100 {
101 SNVS_HP_RTC_StopTimer(SNVS);
102
103 return RT_EOK;
104 }
105
imxrt_hp_rtc_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)106 static rt_ssize_t imxrt_hp_rtc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
107 {
108 return -RT_EINVAL;
109 }
110
imxrt_hp_rtc_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)111 static rt_ssize_t imxrt_hp_rtc_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
112 {
113 return -RT_EINVAL;
114 }
115
imxrt_hp_rtc_control(rt_device_t dev,int cmd,void * args)116 static rt_err_t imxrt_hp_rtc_control(rt_device_t dev, int cmd, void *args)
117 {
118 RT_ASSERT(dev != RT_NULL);
119
120 switch(cmd)
121 {
122 case RT_DEVICE_CTRL_RTC_GET_TIME:
123 {
124 *(uint32_t *)args = imxrt_hp_get_timestamp();
125 }
126 break;
127
128 case RT_DEVICE_CTRL_RTC_SET_TIME:
129 {
130 imxrt_hp_set_timestamp(*(time_t *)args);
131 }
132 break;
133
134 default:
135 return -RT_EINVAL;
136 }
137
138 return RT_EOK;
139 }
140
141 static struct rt_device device =
142 {
143 .type = RT_Device_Class_RTC,
144 .init = imxrt_hp_rtc_init,
145 .open = imxrt_hp_rtc_open,
146 .close = imxrt_hp_rtc_close,
147 .read = imxrt_hp_rtc_read,
148 .write = imxrt_hp_rtc_write,
149 .control = imxrt_hp_rtc_control,
150 };
151
rt_hw_rtc_init(void)152 int rt_hw_rtc_init(void)
153 {
154 rt_err_t ret = RT_EOK;
155
156 ret = rt_device_register(&device, "rtc", RT_DEVICE_FLAG_RDWR);
157
158 if(ret != RT_EOK)
159 {
160 LOG_E("rt device register failed %d\n", ret);
161 return ret;
162 }
163
164 rt_device_open(&device, RT_DEVICE_OFLAG_RDWR);
165
166 return RT_EOK;
167 }
168
169 INIT_DEVICE_EXPORT(rt_hw_rtc_init);
170
171 #include <rtthread.h>
172 #include <rtdevice.h>
173
174 #define RTC_NAME "rtc"
175
rtc_sample(int argc,char * argv[])176 static int rtc_sample(int argc, char *argv[])
177 {
178 rt_err_t ret = RT_EOK;
179 time_t now;
180 rt_device_t device = RT_NULL;
181
182 device = rt_device_find(RTC_NAME);
183 if (!device)
184 {
185 LOG_E("find %s failed!", RTC_NAME);
186 return -RT_ERROR;
187 }
188
189 if(rt_device_open(device, 0) != RT_EOK)
190 {
191 LOG_E("open %s failed!", RTC_NAME);
192 return -RT_ERROR;
193 }
194
195 ret = set_date(2018, 12, 3);
196 if (ret != RT_EOK)
197 {
198 rt_kprintf("set RTC date failed\n");
199 return ret;
200 }
201
202 ret = set_time(11, 15, 50);
203 if (ret != RT_EOK)
204 {
205 rt_kprintf("set RTC time failed\n");
206 return ret;
207 }
208
209 rt_thread_mdelay(1000);
210
211 now = time(RT_NULL);
212 rt_kprintf("%s\n", ctime(&now));
213
214 return ret;
215 }
216 MSH_CMD_EXPORT(rtc_sample, rtc sample);
217 #endif /* BSP_USING_RTC */
218