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