xref: /nrf52832-nimble/rt-thread/components/libc/time/clock_time.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-12-08     Bernard      fix the issue of _timevalue.tv_usec initialization,
9*10465441SEvalZero  *                             which found by Rob <[email protected]>
10*10465441SEvalZero  */
11*10465441SEvalZero 
12*10465441SEvalZero #include <rtthread.h>
13*10465441SEvalZero #include <pthread.h>
14*10465441SEvalZero 
15*10465441SEvalZero #include "clock_time.h"
16*10465441SEvalZero 
17*10465441SEvalZero static struct timeval _timevalue;
clock_time_system_init()18*10465441SEvalZero int clock_time_system_init()
19*10465441SEvalZero {
20*10465441SEvalZero     time_t time;
21*10465441SEvalZero     rt_tick_t tick;
22*10465441SEvalZero     rt_device_t device;
23*10465441SEvalZero 
24*10465441SEvalZero     time = 0;
25*10465441SEvalZero     device = rt_device_find("rtc");
26*10465441SEvalZero     if (device != RT_NULL)
27*10465441SEvalZero     {
28*10465441SEvalZero         /* get realtime seconds */
29*10465441SEvalZero         rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time);
30*10465441SEvalZero     }
31*10465441SEvalZero 
32*10465441SEvalZero     /* get tick */
33*10465441SEvalZero     tick = rt_tick_get();
34*10465441SEvalZero 
35*10465441SEvalZero     _timevalue.tv_usec = (tick%RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK;
36*10465441SEvalZero     _timevalue.tv_sec = time - tick/RT_TICK_PER_SECOND - 1;
37*10465441SEvalZero 
38*10465441SEvalZero     return 0;
39*10465441SEvalZero }
40*10465441SEvalZero INIT_COMPONENT_EXPORT(clock_time_system_init);
41*10465441SEvalZero 
clock_time_to_tick(const struct timespec * time)42*10465441SEvalZero int clock_time_to_tick(const struct timespec *time)
43*10465441SEvalZero {
44*10465441SEvalZero     int tick;
45*10465441SEvalZero     int nsecond, second;
46*10465441SEvalZero     struct timespec tp;
47*10465441SEvalZero 
48*10465441SEvalZero     RT_ASSERT(time != RT_NULL);
49*10465441SEvalZero 
50*10465441SEvalZero     tick = RT_WAITING_FOREVER;
51*10465441SEvalZero     if (time != NULL)
52*10465441SEvalZero     {
53*10465441SEvalZero         /* get current tp */
54*10465441SEvalZero         clock_gettime(CLOCK_REALTIME, &tp);
55*10465441SEvalZero 
56*10465441SEvalZero         if ((time->tv_nsec - tp.tv_nsec) < 0)
57*10465441SEvalZero         {
58*10465441SEvalZero             nsecond = NANOSECOND_PER_SECOND - (tp.tv_nsec - time->tv_nsec);
59*10465441SEvalZero             second  = time->tv_sec - tp.tv_sec - 1;
60*10465441SEvalZero         }
61*10465441SEvalZero         else
62*10465441SEvalZero         {
63*10465441SEvalZero             nsecond = time->tv_nsec - tp.tv_nsec;
64*10465441SEvalZero             second  = time->tv_sec - tp.tv_sec;
65*10465441SEvalZero         }
66*10465441SEvalZero 
67*10465441SEvalZero         tick = second * RT_TICK_PER_SECOND + nsecond * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND;
68*10465441SEvalZero         if (tick < 0) tick = 0;
69*10465441SEvalZero     }
70*10465441SEvalZero 
71*10465441SEvalZero     return tick;
72*10465441SEvalZero }
73*10465441SEvalZero RTM_EXPORT(clock_time_to_tick);
74*10465441SEvalZero 
clock_getres(clockid_t clockid,struct timespec * res)75*10465441SEvalZero int clock_getres(clockid_t clockid, struct timespec *res)
76*10465441SEvalZero {
77*10465441SEvalZero     int ret = 0;
78*10465441SEvalZero 
79*10465441SEvalZero     if (res == RT_NULL)
80*10465441SEvalZero     {
81*10465441SEvalZero         rt_set_errno(EINVAL);
82*10465441SEvalZero         return -1;
83*10465441SEvalZero     }
84*10465441SEvalZero 
85*10465441SEvalZero     switch (clockid)
86*10465441SEvalZero     {
87*10465441SEvalZero     case CLOCK_REALTIME:
88*10465441SEvalZero         res->tv_sec = 0;
89*10465441SEvalZero         res->tv_nsec = NANOSECOND_PER_SECOND/RT_TICK_PER_SECOND;
90*10465441SEvalZero         break;
91*10465441SEvalZero 
92*10465441SEvalZero #ifdef RT_USING_CPUTIME
93*10465441SEvalZero     case CLOCK_CPUTIME_ID:
94*10465441SEvalZero         res->tv_sec  = 0;
95*10465441SEvalZero         res->tv_nsec = clock_cpu_getres();
96*10465441SEvalZero         break;
97*10465441SEvalZero #endif
98*10465441SEvalZero 
99*10465441SEvalZero     default:
100*10465441SEvalZero         ret = -1;
101*10465441SEvalZero         rt_set_errno(EINVAL);
102*10465441SEvalZero         break;
103*10465441SEvalZero     }
104*10465441SEvalZero 
105*10465441SEvalZero     return ret;
106*10465441SEvalZero }
107*10465441SEvalZero RTM_EXPORT(clock_getres);
108*10465441SEvalZero 
clock_gettime(clockid_t clockid,struct timespec * tp)109*10465441SEvalZero int clock_gettime(clockid_t clockid, struct timespec *tp)
110*10465441SEvalZero {
111*10465441SEvalZero     int ret = 0;
112*10465441SEvalZero 
113*10465441SEvalZero     if (tp == RT_NULL)
114*10465441SEvalZero     {
115*10465441SEvalZero         rt_set_errno(EINVAL);
116*10465441SEvalZero         return -1;
117*10465441SEvalZero     }
118*10465441SEvalZero 
119*10465441SEvalZero     switch (clockid)
120*10465441SEvalZero     {
121*10465441SEvalZero     case CLOCK_REALTIME:
122*10465441SEvalZero         {
123*10465441SEvalZero             /* get tick */
124*10465441SEvalZero             int tick = rt_tick_get();
125*10465441SEvalZero 
126*10465441SEvalZero             tp->tv_sec  = _timevalue.tv_sec + tick / RT_TICK_PER_SECOND;
127*10465441SEvalZero             tp->tv_nsec = (_timevalue.tv_usec + (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK) * 1000;
128*10465441SEvalZero         }
129*10465441SEvalZero         break;
130*10465441SEvalZero 
131*10465441SEvalZero #ifdef RT_USING_CPUTIME
132*10465441SEvalZero     case CLOCK_CPUTIME_ID:
133*10465441SEvalZero         {
134*10465441SEvalZero             float unit = 0;
135*10465441SEvalZero             long long cpu_tick;
136*10465441SEvalZero 
137*10465441SEvalZero             unit = clock_cpu_getres();
138*10465441SEvalZero             cpu_tick = clock_cpu_gettime();
139*10465441SEvalZero 
140*10465441SEvalZero             tp->tv_sec  = ((int)(cpu_tick * unit)) / NANOSECOND_PER_SECOND;
141*10465441SEvalZero             tp->tv_nsec = ((int)(cpu_tick * unit)) % NANOSECOND_PER_SECOND;
142*10465441SEvalZero         }
143*10465441SEvalZero         break;
144*10465441SEvalZero #endif
145*10465441SEvalZero     default:
146*10465441SEvalZero         rt_set_errno(EINVAL);
147*10465441SEvalZero         ret = -1;
148*10465441SEvalZero     }
149*10465441SEvalZero 
150*10465441SEvalZero     return ret;
151*10465441SEvalZero }
152*10465441SEvalZero RTM_EXPORT(clock_gettime);
153*10465441SEvalZero 
clock_settime(clockid_t clockid,const struct timespec * tp)154*10465441SEvalZero int clock_settime(clockid_t clockid, const struct timespec *tp)
155*10465441SEvalZero {
156*10465441SEvalZero     int second;
157*10465441SEvalZero     rt_tick_t tick;
158*10465441SEvalZero     rt_device_t device;
159*10465441SEvalZero 
160*10465441SEvalZero     if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL))
161*10465441SEvalZero     {
162*10465441SEvalZero         rt_set_errno(EINVAL);
163*10465441SEvalZero 
164*10465441SEvalZero         return -1;
165*10465441SEvalZero     }
166*10465441SEvalZero 
167*10465441SEvalZero     /* get second */
168*10465441SEvalZero     second = tp->tv_sec;
169*10465441SEvalZero     /* get tick */
170*10465441SEvalZero     tick = rt_tick_get();
171*10465441SEvalZero 
172*10465441SEvalZero     /* update timevalue */
173*10465441SEvalZero     _timevalue.tv_usec = MICROSECOND_PER_SECOND - (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK;
174*10465441SEvalZero     _timevalue.tv_sec = second - tick/RT_TICK_PER_SECOND - 1;
175*10465441SEvalZero 
176*10465441SEvalZero     /* update for RTC device */
177*10465441SEvalZero     device = rt_device_find("rtc");
178*10465441SEvalZero     if (device != RT_NULL)
179*10465441SEvalZero     {
180*10465441SEvalZero         /* set realtime seconds */
181*10465441SEvalZero         rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &second);
182*10465441SEvalZero     }
183*10465441SEvalZero     else
184*10465441SEvalZero         return -1;
185*10465441SEvalZero 
186*10465441SEvalZero     return 0;
187*10465441SEvalZero }
188*10465441SEvalZero RTM_EXPORT(clock_settime);
189