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