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