clock_time.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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 <rdent@iinet.net.au>
  10. */
  11. #include <rtdevice.h>
  12. #include "clock_time.h"
  13. static struct timeval _timevalue;
  14. int clock_time_system_init()
  15. {
  16. time_t time;
  17. rt_tick_t tick;
  18. rt_device_t device;
  19. time = 0;
  20. device = rt_device_find("rtc");
  21. if (device != RT_NULL)
  22. {
  23. /* get realtime seconds */
  24. rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time);
  25. }
  26. /* get tick */
  27. tick = rt_tick_get();
  28. _timevalue.tv_usec = (tick%RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK;
  29. _timevalue.tv_sec = time - tick/RT_TICK_PER_SECOND - 1;
  30. return 0;
  31. }
  32. INIT_COMPONENT_EXPORT(clock_time_system_init);
  33. int clock_time_to_tick(const struct timespec *time)
  34. {
  35. int tick;
  36. int nsecond, second;
  37. struct timespec tp;
  38. RT_ASSERT(time != RT_NULL);
  39. tick = RT_WAITING_FOREVER;
  40. if (time != RT_NULL)
  41. {
  42. /* get current tp */
  43. clock_gettime(CLOCK_REALTIME, &tp);
  44. if ((time->tv_nsec - tp.tv_nsec) < 0)
  45. {
  46. nsecond = NANOSECOND_PER_SECOND - (tp.tv_nsec - time->tv_nsec);
  47. second = time->tv_sec - tp.tv_sec - 1;
  48. }
  49. else
  50. {
  51. nsecond = time->tv_nsec - tp.tv_nsec;
  52. second = time->tv_sec - tp.tv_sec;
  53. }
  54. tick = second * RT_TICK_PER_SECOND + nsecond * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND;
  55. if (tick < 0) tick = 0;
  56. }
  57. return tick;
  58. }
  59. RTM_EXPORT(clock_time_to_tick);
  60. int clock_getres(clockid_t clockid, struct timespec *res)
  61. {
  62. int ret = 0;
  63. if (res == RT_NULL)
  64. {
  65. rt_set_errno(EINVAL);
  66. return -1;
  67. }
  68. switch (clockid)
  69. {
  70. case CLOCK_REALTIME:
  71. res->tv_sec = 0;
  72. res->tv_nsec = NANOSECOND_PER_SECOND/RT_TICK_PER_SECOND;
  73. break;
  74. #ifdef RT_USING_CPUTIME
  75. case CLOCK_CPUTIME_ID:
  76. res->tv_sec = 0;
  77. res->tv_nsec = clock_cpu_getres();
  78. break;
  79. #endif
  80. default:
  81. ret = -1;
  82. rt_set_errno(EINVAL);
  83. break;
  84. }
  85. return ret;
  86. }
  87. RTM_EXPORT(clock_getres);
  88. int clock_gettime(clockid_t clockid, struct timespec *tp)
  89. {
  90. int ret = 0;
  91. if (tp == RT_NULL)
  92. {
  93. rt_set_errno(EINVAL);
  94. return -1;
  95. }
  96. switch (clockid)
  97. {
  98. case CLOCK_REALTIME:
  99. {
  100. /* get tick */
  101. int tick = rt_tick_get();
  102. tp->tv_sec = _timevalue.tv_sec + tick / RT_TICK_PER_SECOND;
  103. tp->tv_nsec = (_timevalue.tv_usec + (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK) * 1000;
  104. }
  105. break;
  106. #ifdef RT_USING_CPUTIME
  107. case CLOCK_CPUTIME_ID:
  108. {
  109. float unit = 0;
  110. long long cpu_tick;
  111. unit = clock_cpu_getres();
  112. cpu_tick = clock_cpu_gettime();
  113. tp->tv_sec = ((int)(cpu_tick * unit)) / NANOSECOND_PER_SECOND;
  114. tp->tv_nsec = ((int)(cpu_tick * unit)) % NANOSECOND_PER_SECOND;
  115. }
  116. break;
  117. #endif
  118. default:
  119. rt_set_errno(EINVAL);
  120. ret = -1;
  121. }
  122. return ret;
  123. }
  124. RTM_EXPORT(clock_gettime);
  125. int clock_settime(clockid_t clockid, const struct timespec *tp)
  126. {
  127. int second;
  128. rt_tick_t tick;
  129. rt_device_t device;
  130. if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL))
  131. {
  132. rt_set_errno(EINVAL);
  133. return -1;
  134. }
  135. /* get second */
  136. second = tp->tv_sec;
  137. /* get tick */
  138. tick = rt_tick_get();
  139. /* update timevalue */
  140. _timevalue.tv_usec = MICROSECOND_PER_SECOND - (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK;
  141. _timevalue.tv_sec = second - tick/RT_TICK_PER_SECOND - 1;
  142. /* update for RTC device */
  143. device = rt_device_find("rtc");
  144. if (device != RT_NULL)
  145. {
  146. /* set realtime seconds */
  147. rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &second);
  148. }
  149. else
  150. return -1;
  151. return 0;
  152. }
  153. RTM_EXPORT(clock_settime);