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; 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 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 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 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 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