xref: /nrf52832-nimble/rt-thread/components/drivers/rtc/rtc.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * Copyright (c) 2006-2018, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2012-01-29     aozima       first version.
9  * 2012-04-12     aozima       optimization: find rtc device only first.
10  * 2012-04-16     aozima       add scheduler lock for set_date and set_time.
11  * 2018-02-16     armink       add auto sync time by NTP
12  */
13 
14 #include <time.h>
15 #include <string.h>
16 #include <rtthread.h>
17 
18 #ifdef RT_USING_RTC
19 
20 /* Using NTP auto sync RTC time */
21 #ifdef RTC_SYNC_USING_NTP
22 /* NTP first sync delay time for network connect, unit: second */
23 #ifndef RTC_NTP_FIRST_SYNC_DELAY
24 #define RTC_NTP_FIRST_SYNC_DELAY                 (30)
25 #endif
26 /* NTP sync period, unit: second */
27 #ifndef RTC_NTP_SYNC_PERIOD
28 #define RTC_NTP_SYNC_PERIOD                      (1L*60L*60L)
29 #endif
30 #endif /* RTC_SYNC_USING_NTP */
31 
32 /**
33  * Set system date(time not modify).
34  *
35  * @param rt_uint32_t year  e.g: 2012.
36  * @param rt_uint32_t month e.g: 12 (1~12).
37  * @param rt_uint32_t day   e.g: 31.
38  *
39  * @return rt_err_t if set success, return RT_EOK.
40  *
41  */
set_date(rt_uint32_t year,rt_uint32_t month,rt_uint32_t day)42 rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day)
43 {
44     time_t now;
45     struct tm *p_tm;
46     struct tm tm_new;
47     rt_device_t device;
48     rt_err_t ret = -RT_ERROR;
49 
50     /* get current time */
51     now = time(RT_NULL);
52 
53     /* lock scheduler. */
54     rt_enter_critical();
55     /* converts calendar time time into local time. */
56     p_tm = localtime(&now);
57     /* copy the statically located variable */
58     memcpy(&tm_new, p_tm, sizeof(struct tm));
59     /* unlock scheduler. */
60     rt_exit_critical();
61 
62     /* update date. */
63     tm_new.tm_year = year - 1900;
64     tm_new.tm_mon  = month - 1; /* tm_mon: 0~11 */
65     tm_new.tm_mday = day;
66 
67     /* converts the local time in time to calendar time. */
68     now = mktime(&tm_new);
69 
70     device = rt_device_find("rtc");
71     if (device == RT_NULL)
72     {
73         return -RT_ERROR;
74     }
75 
76     /* update to RTC device. */
77     ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &now);
78 
79     return ret;
80 }
81 
82 /**
83  * Set system time(date not modify).
84  *
85  * @param rt_uint32_t hour   e.g: 0~23.
86  * @param rt_uint32_t minute e.g: 0~59.
87  * @param rt_uint32_t second e.g: 0~59.
88  *
89  * @return rt_err_t if set success, return RT_EOK.
90  *
91  */
set_time(rt_uint32_t hour,rt_uint32_t minute,rt_uint32_t second)92 rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second)
93 {
94     time_t now;
95     struct tm *p_tm;
96     struct tm tm_new;
97     rt_device_t device;
98     rt_err_t ret = -RT_ERROR;
99 
100     /* get current time */
101     now = time(RT_NULL);
102 
103     /* lock scheduler. */
104     rt_enter_critical();
105     /* converts calendar time time into local time. */
106     p_tm = localtime(&now);
107     /* copy the statically located variable */
108     memcpy(&tm_new, p_tm, sizeof(struct tm));
109     /* unlock scheduler. */
110     rt_exit_critical();
111 
112     /* update time. */
113     tm_new.tm_hour = hour;
114     tm_new.tm_min  = minute;
115     tm_new.tm_sec  = second;
116 
117     /* converts the local time in time to calendar time. */
118     now = mktime(&tm_new);
119 
120     device = rt_device_find("rtc");
121     if (device == RT_NULL)
122     {
123         return -RT_ERROR;
124     }
125 
126     /* update to RTC device. */
127     ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &now);
128 
129     return ret;
130 }
131 
132 #ifdef RTC_SYNC_USING_NTP
ntp_sync_thread_enrty(void * param)133 static void ntp_sync_thread_enrty(void *param)
134 {
135     extern time_t ntp_sync_to_rtc(const char *host_name);
136     /* first sync delay for network connect */
137     rt_thread_delay(RTC_NTP_FIRST_SYNC_DELAY * RT_TICK_PER_SECOND);
138 
139     while (1)
140     {
141         ntp_sync_to_rtc(NULL);
142         rt_thread_delay(RTC_NTP_SYNC_PERIOD * RT_TICK_PER_SECOND);
143     }
144 }
145 
rt_rtc_ntp_sync_init(void)146 int rt_rtc_ntp_sync_init(void)
147 {
148     static rt_bool_t init_ok = RT_FALSE;
149     rt_thread_t thread;
150 
151     if (init_ok)
152     {
153         return 0;
154     }
155 
156     thread = rt_thread_create("ntp_sync", ntp_sync_thread_enrty, RT_NULL, 1536, 26, 2);
157     if (thread)
158     {
159         rt_thread_startup(thread);
160     }
161     else
162     {
163         return -RT_ENOMEM;
164     }
165 
166     init_ok = RT_TRUE;
167 
168     return RT_EOK;
169 }
170 INIT_COMPONENT_EXPORT(rt_rtc_ntp_sync_init);
171 #endif /* RTC_SYNC_USING_NTP */
172 
173 #ifdef RT_USING_FINSH
174 #include <finsh.h>
175 #include <rtdevice.h>
176 
list_date(void)177 void list_date(void)
178 {
179     time_t now;
180 
181     now = time(RT_NULL);
182     rt_kprintf("%s\n", ctime(&now));
183 }
184 FINSH_FUNCTION_EXPORT(list_date, show date and time.)
185 
186 FINSH_FUNCTION_EXPORT(set_date, set date. e.g: set_date(2010,2,28))
187 FINSH_FUNCTION_EXPORT(set_time, set time. e.g: set_time(23,59,59))
188 
189 #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
date(uint8_t argc,char ** argv)190 static void date(uint8_t argc, char **argv)
191 {
192     if (argc == 1)
193     {
194         time_t now;
195         /* output current time */
196         now = time(RT_NULL);
197         rt_kprintf("%s", ctime(&now));
198     }
199     else if (argc >= 7)
200     {
201         /* set time and date */
202         uint16_t year;
203         uint8_t month, day, hour, min, sec;
204         year = atoi(argv[1]);
205         month = atoi(argv[2]);
206         day = atoi(argv[3]);
207         hour = atoi(argv[4]);
208         min = atoi(argv[5]);
209         sec = atoi(argv[6]);
210         if (year > 2099 || year < 2000)
211         {
212             rt_kprintf("year is out of range [2000-2099]\n");
213             return;
214         }
215         if (month == 0 || month > 12)
216         {
217             rt_kprintf("month is out of range [1-12]\n");
218             return;
219         }
220         if (day == 0 || day > 31)
221         {
222             rt_kprintf("day is out of range [1-31]\n");
223             return;
224         }
225         if (hour > 23)
226         {
227             rt_kprintf("hour is out of range [0-23]\n");
228             return;
229         }
230         if (min > 59)
231         {
232             rt_kprintf("minute is out of range [0-59]\n");
233             return;
234         }
235         if (sec > 59)
236         {
237             rt_kprintf("second is out of range [0-59]\n");
238             return;
239         }
240         set_time(hour, min, sec);
241         set_date(year, month, day);
242     }
243     else
244     {
245         rt_kprintf("please input: date [year month day hour min sec] or date\n");
246         rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n");
247     }
248 }
249 MSH_CMD_EXPORT(date, get date and time or set [year month day hour min sec]);
250 #endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */
251 
252 #endif /* RT_USING_FINSH */
253 
254 #endif /* RT_USING_RTC */
255