xref: /nrf52832-nimble/rt-thread/components/drivers/rtc/rtc.c (revision 104654410c56c573564690304ae786df310c91fc)
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