clock_time.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  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 <time.h>
  13. #include "clock_time.h"
  14. #include "lwp.h"
  15. static struct timeval _timevalue;
  16. int clock_time_system_init()
  17. {
  18. time_t time;
  19. rt_tick_t tick;
  20. rt_device_t device;
  21. time = 0;
  22. device = rt_device_find("rtc");
  23. if (device != RT_NULL)
  24. {
  25. /* get realtime seconds */
  26. rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time);
  27. }
  28. /* get tick */
  29. tick = rt_tick_get();
  30. _timevalue.tv_usec = (tick%RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK;
  31. _timevalue.tv_sec = time - tick/RT_TICK_PER_SECOND - 1;
  32. return 0;
  33. }
  34. INIT_COMPONENT_EXPORT(clock_time_system_init);
  35. int clock_time_to_tick(const struct timespec *time)
  36. {
  37. int tick = 0;
  38. long nsecond, second;
  39. struct timespec tp;
  40. RT_ASSERT(time != RT_NULL);
  41. if (time->tv_sec != 0 && time->tv_nsec != 0)
  42. {
  43. /* get current tp */
  44. clock_gettime(CLOCK_REALTIME, &tp);
  45. if ((time->tv_nsec - tp.tv_nsec) < 0)
  46. {
  47. nsecond = (long)NANOSECOND_PER_SECOND - (tp.tv_nsec - time->tv_nsec);
  48. second = time->tv_sec - tp.tv_sec - 1;
  49. }
  50. else
  51. {
  52. nsecond = time->tv_nsec - tp.tv_nsec;
  53. second = time->tv_sec - tp.tv_sec;
  54. }
  55. /*
  56. * Warning: NANOSECOND_PER_SECOND is unsigned long, division method instruction will be `divu`.
  57. * so then result is overflow undefined behavior.
  58. */
  59. tick = (int)(second * RT_TICK_PER_SECOND + (long)(nsecond * RT_TICK_PER_SECOND) / (long)NANOSECOND_PER_SECOND);
  60. if (tick < 0) tick = 0;
  61. }
  62. return tick;
  63. }
  64. RTM_EXPORT(clock_time_to_tick);
  65. int clock_getres(clockid_t clockid, struct timespec *res)
  66. {
  67. int ret = 0;
  68. if (res == RT_NULL)
  69. {
  70. rt_set_errno(EINVAL);
  71. return -RT_ERROR;
  72. }
  73. switch (clockid)
  74. {
  75. case CLOCK_REALTIME:
  76. res->tv_sec = 0;
  77. res->tv_nsec = NANOSECOND_PER_SECOND/RT_TICK_PER_SECOND;
  78. break;
  79. #ifdef RT_USING_CPUTIME
  80. case CLOCK_MONOTONIC:
  81. case CLOCK_CPUTIME_ID:
  82. res->tv_sec = 0;
  83. res->tv_nsec = clock_cpu_getres();
  84. break;
  85. #endif
  86. default:
  87. ret = -RT_ERROR;
  88. rt_set_errno(EINVAL);
  89. break;
  90. }
  91. return ret;
  92. }
  93. RTM_EXPORT(clock_getres);
  94. int clock_gettime(clockid_t clockid, struct timespec *tp)
  95. {
  96. int ret = 0;
  97. if (tp == RT_NULL)
  98. {
  99. rt_set_errno(EINVAL);
  100. return -RT_ERROR;
  101. }
  102. switch (clockid)
  103. {
  104. case CLOCK_REALTIME:
  105. {
  106. /* get tick */
  107. rt_tick_t tick = rt_tick_get();
  108. tp->tv_sec = _timevalue.tv_sec + tick / RT_TICK_PER_SECOND;
  109. tp->tv_nsec = (_timevalue.tv_usec + (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK) * 1000;
  110. }
  111. break;
  112. #ifdef RT_USING_CPUTIME
  113. case CLOCK_MONOTONIC:
  114. case CLOCK_CPUTIME_ID:
  115. {
  116. float unit = 0;
  117. uint64_t cpu_tick;
  118. unit = clock_cpu_getres();
  119. cpu_tick = clock_cpu_gettime();
  120. tp->tv_sec = ((uint64_t)(cpu_tick * unit)) / NANOSECOND_PER_SECOND;
  121. tp->tv_nsec = ((uint64_t)(cpu_tick * unit)) % NANOSECOND_PER_SECOND;
  122. }
  123. break;
  124. #endif
  125. default:
  126. rt_set_errno(EINVAL);
  127. ret = -RT_ERROR;
  128. }
  129. return ret;
  130. }
  131. RTM_EXPORT(clock_gettime);
  132. int clock_settime(clockid_t clockid, const struct timespec *tp)
  133. {
  134. int second;
  135. rt_tick_t tick;
  136. rt_device_t device;
  137. if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL))
  138. {
  139. rt_set_errno(EINVAL);
  140. return -RT_ERROR;
  141. }
  142. /* get second */
  143. second = tp->tv_sec;
  144. /* get tick */
  145. tick = rt_tick_get();
  146. /* update timevalue */
  147. _timevalue.tv_usec = MICROSECOND_PER_SECOND - (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK;
  148. _timevalue.tv_sec = second - tick/RT_TICK_PER_SECOND - 1;
  149. /* update for RTC device */
  150. device = rt_device_find("rtc");
  151. if (device != RT_NULL)
  152. {
  153. /* set realtime seconds */
  154. rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &second);
  155. }
  156. else
  157. return -RT_ERROR;
  158. return 0;
  159. }
  160. RTM_EXPORT(clock_settime);
  161. int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp, struct timespec *rmtp)
  162. {
  163. if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= NANOSECOND_PER_SECOND)
  164. {
  165. rt_set_errno(EINVAL);
  166. return -RT_ERROR;
  167. }
  168. switch (clockid)
  169. {
  170. case CLOCK_REALTIME:
  171. {
  172. rt_tick_t tick;
  173. if (flags & TIMER_ABSTIME == TIMER_ABSTIME)
  174. {
  175. tick = (rqtp->tv_sec - _timevalue.tv_sec) * RT_TICK_PER_SECOND + (rqtp->tv_nsec - _timevalue.tv_usec) * (RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND);
  176. rt_tick_t rt_tick = rt_tick_get();
  177. tick = tick < rt_tick ? 0 : tick - rt_tick;
  178. }
  179. else
  180. {
  181. tick = rqtp->tv_sec * RT_TICK_PER_SECOND + ((uint64_t)(rqtp->tv_nsec) * RT_TICK_PER_SECOND) / NANOSECOND_PER_SECOND;
  182. }
  183. rt_thread_delay(tick);
  184. if (rt_get_errno() == -RT_EINTR)
  185. {
  186. if (rmtp)
  187. {
  188. tick = rt_tick_get() - tick;
  189. /* get the passed time */
  190. rmtp->tv_sec = tick / RT_TICK_PER_SECOND;
  191. rmtp->tv_nsec = (tick % RT_TICK_PER_SECOND) * (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND);
  192. }
  193. rt_set_errno(EINTR);
  194. return -RT_ERROR;
  195. }
  196. }
  197. break;
  198. #ifdef RT_USING_CPUTIME
  199. case CLOCK_MONOTONIC:
  200. case CLOCK_CPUTIME_ID:
  201. {
  202. uint64_t cpu_tick, cpu_tick_old;
  203. cpu_tick_old = clock_cpu_gettime();
  204. rt_tick_t tick;
  205. float unit = clock_cpu_getres();
  206. cpu_tick = (rqtp->tv_sec * NANOSECOND_PER_SECOND + rqtp->tv_nsec * (NANOSECOND_PER_SECOND / NANOSECOND_PER_SECOND)) / unit;
  207. if (flags & TIMER_ABSTIME == TIMER_ABSTIME)
  208. cpu_tick = cpu_tick < cpu_tick_old ? 0 : cpu_tick - cpu_tick_old;
  209. tick = (unit * cpu_tick) / (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND);
  210. rt_thread_delay(tick);
  211. if (rt_get_errno() == -RT_EINTR)
  212. {
  213. if (rmtp)
  214. {
  215. uint64_t rmtp_cpu_tick = clock_cpu_gettime() - tick * (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND);
  216. rmtp->tv_sec = ((int)(rmtp_cpu_tick * unit)) / NANOSECOND_PER_SECOND;
  217. rmtp->tv_nsec = ((int)(rmtp_cpu_tick * unit)) % NANOSECOND_PER_SECOND;
  218. }
  219. rt_set_errno(EINTR);
  220. return -RT_ERROR;
  221. }
  222. else
  223. while (clock_cpu_gettime() - cpu_tick_old < cpu_tick);
  224. }
  225. break;
  226. #endif
  227. default:
  228. rt_set_errno(EINVAL);
  229. return -RT_ERROR;
  230. }
  231. return 0;
  232. }
  233. RTM_EXPORT(clock_nanosleep);
  234. int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
  235. {
  236. if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= NANOSECOND_PER_SECOND)
  237. {
  238. rt_set_errno(EINVAL);
  239. return -RT_ERROR;
  240. }
  241. #ifdef RT_USING_CPUTIME
  242. uint64_t cpu_tick, cpu_tick_old;
  243. cpu_tick_old = clock_cpu_gettime();
  244. rt_tick_t tick;
  245. float unit = clock_cpu_getres();
  246. cpu_tick = (rqtp->tv_sec * NANOSECOND_PER_SECOND + ((uint64_t)rqtp->tv_nsec * NANOSECOND_PER_SECOND) / NANOSECOND_PER_SECOND)/unit;
  247. tick = (unit * cpu_tick) / (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND);
  248. rt_thread_delay(tick);
  249. if (rt_get_errno() == -RT_EINTR)
  250. {
  251. if (rmtp)
  252. {
  253. uint64_t rmtp_cpu_tick = clock_cpu_gettime() - tick * (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND);
  254. rmtp->tv_sec = ((int)(rmtp_cpu_tick * unit)) / NANOSECOND_PER_SECOND;
  255. rmtp->tv_nsec = ((int)(rmtp_cpu_tick * unit)) % NANOSECOND_PER_SECOND;
  256. }
  257. rt_set_errno(EINTR);
  258. return -RT_ERROR;
  259. }
  260. else
  261. while (clock_cpu_gettime() - cpu_tick_old < cpu_tick);
  262. #else
  263. rt_tick_t tick;
  264. tick = rqtp->tv_sec * RT_TICK_PER_SECOND + ((uint64_t)rqtp->tv_nsec * RT_TICK_PER_SECOND) / NANOSECOND_PER_SECOND;
  265. rt_thread_delay(tick);
  266. if (rt_get_errno() == -RT_EINTR)
  267. {
  268. if (rmtp)
  269. {
  270. tick = rt_tick_get() - tick;
  271. /* get the passed time */
  272. rmtp->tv_sec = tick / RT_TICK_PER_SECOND;
  273. rmtp->tv_nsec = (tick % RT_TICK_PER_SECOND) * (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND);
  274. }
  275. rt_set_errno(EINTR);
  276. return -RT_ERROR;
  277. }
  278. #endif
  279. return 0;
  280. }
  281. RTM_EXPORT(nanosleep);
  282. static void rtthread_timer_wrapper(void *timerobj)
  283. {
  284. struct timer_obj *timer;
  285. timer = (struct timer_obj *)timerobj;
  286. sys_kill(timer->pid, timer->sigev_signo);
  287. if (timer->reload == 0U)
  288. {
  289. timer->status = NOT_ACTIVE;
  290. }
  291. // if (timer->sigev_notify_function != RT_NULL)
  292. // {
  293. // (timer->sigev_notify_function)(timer->val);
  294. // }
  295. timer->reload = (timer->interval.tv_sec * RT_TICK_PER_SECOND) + (timer->interval.tv_nsec * RT_TICK_PER_SECOND) / NANOSECOND_PER_SECOND;
  296. rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_TIME, &(timer->reload));
  297. }
  298. int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
  299. {
  300. static int num = 0;
  301. struct timer_obj *timer;
  302. char timername[RT_NAME_MAX] = {0};
  303. if (clockid > CLOCK_TAI || evp->sigev_notify != SIGEV_NONE && evp->sigev_notify != SIGEV_SIGNAL)
  304. {
  305. rt_set_errno(EINVAL);
  306. return -RT_ERROR;
  307. }
  308. timer = rt_malloc(sizeof(struct timer_obj));
  309. if (timer == RT_NULL)
  310. {
  311. rt_set_errno(ENOMEM);
  312. return -RT_ENOMEM;
  313. }
  314. rt_snprintf(timername, RT_NAME_MAX, "psx_tm%02d", num++);
  315. num %= 100;
  316. timer->sigev_signo = evp->sigev_signo;
  317. timer->pid = lwp_self()->pid;
  318. timer->sigev_notify_function = evp->sigev_notify_function;
  319. timer->val = evp->sigev_value;
  320. timer->interval.tv_sec = 0;
  321. timer->interval.tv_nsec = 0;
  322. timer->reload = 0U;
  323. timer->status = NOT_ACTIVE;
  324. if (evp->sigev_notify == SIGEV_NONE)
  325. {
  326. rt_timer_init(&timer->timer, timername, RT_NULL, RT_NULL, 0, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
  327. }
  328. else
  329. {
  330. rt_timer_init(&timer->timer, timername, rtthread_timer_wrapper, timer, 0, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
  331. }
  332. *timerid = (timer_t)((uintptr_t)timer >> 1);
  333. return RT_EOK;
  334. }
  335. RTM_EXPORT(timer_create);
  336. int timer_delete(timer_t timerid)
  337. {
  338. struct timer_obj *timer = (struct timer_obj *)((uintptr_t)timerid << 1);
  339. if (timer == RT_NULL || rt_object_get_type(&timer->timer.parent) != RT_Object_Class_Timer)
  340. {
  341. rt_set_errno(EINVAL);
  342. return -RT_ERROR;
  343. }
  344. if (timer->status == ACTIVE)
  345. {
  346. timer->status = NOT_ACTIVE;
  347. rt_timer_stop(&timer->timer);
  348. }
  349. rt_timer_detach(&timer->timer);
  350. rt_free(timer);
  351. return RT_EOK;
  352. }
  353. RTM_EXPORT(timer_delete);
  354. int timer_getoverrun(timer_t timerid)
  355. {
  356. struct timer_obj *timer = (struct timer_obj *)((uintptr_t)timerid << 1);
  357. rt_set_errno(ENOSYS);
  358. return -RT_ERROR;
  359. }
  360. int timer_gettime(timer_t timerid, struct itimerspec *its)
  361. {
  362. struct timer_obj *timer = (struct timer_obj *)((uintptr_t)timerid << 1);
  363. rt_tick_t remaining;
  364. rt_uint32_t seconds, nanoseconds;
  365. if (timer == NULL || rt_object_get_type(&timer->timer.parent) != RT_Object_Class_Timer)
  366. {
  367. rt_set_errno(EINVAL);
  368. return -RT_ERROR;
  369. }
  370. if (its == NULL)
  371. {
  372. rt_set_errno(EFAULT);
  373. return -RT_ERROR;
  374. }
  375. if (timer->status == ACTIVE)
  376. {
  377. rt_tick_t remain_tick;
  378. rt_timer_control(&timer->timer, RT_TIMER_CTRL_GET_REMAIN_TIME, &remain_tick);
  379. /* 'remain_tick' is minimum-unit in the RT-Thread' timer,
  380. * so the seconds, nanoseconds will be calculated by 'remain_tick'.
  381. */
  382. remaining = remain_tick - rt_tick_get();
  383. /* calculate 'second' */
  384. seconds = remaining / RT_TICK_PER_SECOND;
  385. /* calculate 'nanosecond'; To avoid lost of accuracy, because "RT_TICK_PER_SECOND" maybe 100, 1000, 1024 and so on.
  386. *
  387. * remain_tick millisecond remain_tick * MILLISECOND_PER_SECOND
  388. * ------------------------- = -------------------------- ---> millisecond = -------------------------------------------
  389. * RT_TICK_PER_SECOND MILLISECOND_PER_SECOND RT_TICK_PER_SECOND
  390. *
  391. * remain_tick * MILLISECOND_PER_SECOND remain_tick * MILLISECOND_PER_SECOND * MICROSECOND_PER_SECOND
  392. * millisecond = ---------------------------------------- ---> nanosecond = -------------------------------------------------------------------
  393. * RT_TICK_PER_SECOND RT_TICK_PER_SECOND
  394. *
  395. */
  396. nanoseconds = (((remaining % RT_TICK_PER_SECOND) * MILLISECOND_PER_SECOND) * MICROSECOND_PER_SECOND) / RT_TICK_PER_SECOND;
  397. its->it_value.tv_sec = (rt_int32_t)seconds;
  398. its->it_value.tv_nsec = (rt_int32_t)nanoseconds;
  399. }
  400. else
  401. {
  402. /* Timer is disarmed */
  403. its->it_value.tv_sec = 0;
  404. its->it_value.tv_nsec = 0;
  405. }
  406. /* The interval last set by timer_settime() */
  407. its->it_interval = timer->interval;
  408. return RT_EOK;
  409. }
  410. RTM_EXPORT(timer_gettime);
  411. int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
  412. struct itimerspec *ovalue)
  413. {
  414. struct timer_obj *timer = (struct timer_obj *)((uintptr_t)timerid << 1);
  415. if (timer == NULL ||
  416. rt_object_get_type(&timer->timer.parent) != RT_Object_Class_Timer ||
  417. value->it_interval.tv_nsec < 0 ||
  418. value->it_interval.tv_nsec >= NANOSECOND_PER_SECOND ||
  419. value->it_interval.tv_sec < 0 ||
  420. value->it_value.tv_nsec < 0 ||
  421. value->it_value.tv_nsec >= NANOSECOND_PER_SECOND ||
  422. value->it_value.tv_sec < 0)
  423. {
  424. rt_set_errno(EINVAL);
  425. return -RT_ERROR;
  426. }
  427. /* Save time to expire and old reload value. */
  428. if (ovalue != NULL)
  429. {
  430. timer_gettime(timerid, ovalue);
  431. }
  432. /* Stop the timer if the value is 0 */
  433. if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0))
  434. {
  435. if (timer->status == ACTIVE)
  436. {
  437. rt_timer_stop(&timer->timer);
  438. }
  439. timer->status = NOT_ACTIVE;
  440. return RT_EOK;
  441. }
  442. if (flags & TIMER_ABSTIME == TIMER_ABSTIME)
  443. {
  444. rt_int64_t ts = ((value->it_value.tv_sec - _timevalue.tv_sec) * RT_TICK_PER_SECOND);
  445. rt_int64_t tns = (value->it_value.tv_nsec - _timevalue.tv_usec) * (RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND);
  446. rt_int64_t reload = ts + tns;
  447. rt_tick_t rt_tick = rt_tick_get();
  448. timer->reload = reload < rt_tick ? 0 : reload - rt_tick;
  449. }
  450. else
  451. timer->reload = (value->it_value.tv_sec * RT_TICK_PER_SECOND) + value->it_value.tv_nsec * (RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND);
  452. timer->interval.tv_sec = value->it_interval.tv_sec;
  453. timer->interval.tv_nsec = value->it_interval.tv_nsec;
  454. timer->value.tv_sec = value->it_value.tv_sec;
  455. timer->value.tv_nsec = value->it_value.tv_nsec;
  456. if (timer->status == ACTIVE)
  457. {
  458. rt_timer_stop(&timer->timer);
  459. }
  460. timer->status = ACTIVE;
  461. if ((value->it_interval.tv_sec == 0) && (value->it_interval.tv_nsec == 0))
  462. rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_ONESHOT, RT_NULL);
  463. else
  464. rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_PERIODIC, RT_NULL);
  465. rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_TIME, &(timer->reload));
  466. rt_timer_start(&timer->timer);
  467. return RT_EOK;
  468. }
  469. RTM_EXPORT(timer_settime);