clock_time.c 16 KB

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