From cb72c44e5a02832620918b59288406ef85811bdd Mon Sep 17 00:00:00 2001 From: "bernard.xiong" Date: Mon, 22 Nov 2010 09:51:40 +0000 Subject: [PATCH] add time related function. git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1090 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- components/libc/newlib/clock_time.c | 43 ++++++++++++++ components/libc/newlib/libc.c | 90 ++++++++++++++++++++++++----- components/libc/newlib/libc.h | 14 +++++ components/libc/newlib/syscalls.c | 14 +++++ 4 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 components/libc/newlib/clock_time.c diff --git a/components/libc/newlib/clock_time.c b/components/libc/newlib/clock_time.c new file mode 100644 index 0000000000..c0fd9d82e3 --- /dev/null +++ b/components/libc/newlib/clock_time.c @@ -0,0 +1,43 @@ +#include + +#include +#include +#include "libc.h" + +int clock_getres(clockid_t clock_id, struct timespec *res) +{ + if ((clock_id != CLOCK_REALTIME) || (res == RT_NULL)) + { + rt_set_errno(EINVAL); + return -1; + } + + res->tv_sec = 0; + res->tv_nsec = NANOSECOND_PER_TICK; + + return 0; +} + +int clock_gettime(clockid_t clock_id, struct timespec *tp) +{ + if ((clock_id != CLOCK_REALTIME) || (tp == RT_NULL)) + { + rt_set_errno(EINVAL); + return -1; + } + + libc_get_time(tp); + return 0; +} + +int clock_settime(clockid_t clock_id, const struct timespec *tp) +{ + if ((clock_id != CLOCK_REALTIME) || (tp == RT_NULL)) + { + rt_set_errno(EINVAL); + return -1; + } + + libc_set_time(tp); + return 0; +} diff --git a/components/libc/newlib/libc.c b/components/libc/newlib/libc.c index 90b0b7f2ee..8c298e513b 100644 --- a/components/libc/newlib/libc.c +++ b/components/libc/newlib/libc.c @@ -3,25 +3,95 @@ #include #include #include +#include "libc.h" struct timeval _timevalue; static void libc_system_time_init() { - rt_device_t device; time_t time; rt_tick_t tick; + rt_device_t device; - time = 0; tick = 0; + time = 0; device = rt_device_find("rtc"); if (device != RT_NULL) { + /* get realtime seconds */ rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time); } + /* get tick */ tick = rt_tick_get(); - _timevalue.tv_sec = time; - _timevalue.tv_usec = (1000000UL * tick)/RT_TICK_PER_SECOND; + _timevalue.tv_usec = MICROSECOND_PER_SECOND - (tick%RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK; + _timevalue.tv_sec = time - tick/RT_TICK_PER_SECOND - 1; +} + +int libc_get_time(struct timespec *time) +{ + rt_tick_t tick; + RT_ASSERT(time != RT_NULL); + + /* get tick */ + tick = rt_tick_get(); + + time->tv_sec = _timevalue.tv_sec + tick / RT_TICK_PER_SECOND; + time->tv_nsec = (_timevalue.tv_usec + (tick % RT_TICK_PER_SECOND) * NANOSECOND_PER_TICK) * 1000; + + return 0; +} + +int libc_set_time(const struct timespec *time) +{ + int second; + rt_tick_t tick; + rt_device_t device; + + second = time->tv_sec; + device = rt_device_find("rtc"); + if (device != RT_NULL) + { + /* get realtime seconds */ + rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &second); + } + else return -1; + + /* get tick */ + tick = rt_tick_get(); + + /* update timevalue */ + _timevalue.tv_usec = MICROSECOND_PER_SECOND - (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK; + _timevalue.tv_sec = second - tick/RT_TICK_PER_SECOND - 1; + + return 0; +} + +int libc_time_to_tick(const struct timespec *time) +{ + int tick; + int microsecond, second; + + RT_ASSERT(time != RT_NULL); + + tick = RT_WAITING_FOREVER; + if (time != NULL) + { + if ((time->tv_nsec/1000 - _timevalue.tv_usec) < 0) + { + microsecond = (1000000UL + time->tv_nsec/1000) - _timevalue.tv_usec; + second = time->tv_sec - 1; + } + else + { + microsecond = time->tv_nsec/1000 - _timevalue.tv_usec; + second = time->tv_sec; + } + + tick = second * RT_TICK_PER_SECOND + microsecond * RT_TICK_PER_SECOND / MICROSECOND_PER_SECOND; + if (tick < 0) tick = 0; + } + + return tick; } void libc_system_init(const char* tty_name) @@ -39,13 +109,7 @@ void libc_system_init(const char* tty_name) /* set PATH and HOME */ putenv("PATH=/"); putenv("HOME=/"); -} - -int libc_time_to_tick(const struct timespec *time) -{ - int tick; - - tick = RT_WAITING_FOREVER; - - return tick; + + /* initialize system time */ + libc_system_time_init(); } diff --git a/components/libc/newlib/libc.h b/components/libc/newlib/libc.h index 60a86e49a6..35788d9f18 100644 --- a/components/libc/newlib/libc.h +++ b/components/libc/newlib/libc.h @@ -1,7 +1,21 @@ #ifndef __RTT_LIBC_H__ #define __RTT_LIBC_H__ +#include + +#define MILLISECOND_PER_SECOND 1000UL +#define MICROSECOND_PER_SECOND 1000000UL +#define NANOSECOND_PER_SECOND 1000000000UL + +#define MILLISECOND_PER_TICK (MILLISECOND_PER_SECOND / RT_TICK_PER_SECOND) +#define MICROSECOND_PER_TICK (MICROSECOND_PER_SECOND / RT_TICK_PER_SECOND) +#define NANOSECOND_PER_TICK (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND) + void libc_system_init(const char* tty_name); + +/* some time related function */ +int libc_set_time(const struct timespec *time); +int libc_get_time(struct timespec *time); int libc_time_to_tick(const struct timespec *time); #endif diff --git a/components/libc/newlib/syscalls.c b/components/libc/newlib/syscalls.c index 6b040822ab..9960be97ab 100644 --- a/components/libc/newlib/syscalls.c +++ b/components/libc/newlib/syscalls.c @@ -1,5 +1,6 @@ #include #include +#include #include /* Reentrant versions of system calls. */ @@ -172,6 +173,19 @@ _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes) int _gettimeofday_r(struct _reent *ptr, struct timeval *__tp, void *__tzp) { + struct timespec tp; + + if (libc_get_time(&tp) == 0) + { + if (__tp != RT_NULL) + { + __tp->tv_sec = tp.tv_sec; + __tp->tv_usec = tp.tv_nsec * 1000UL; + } + + return tp.tv_sec; + } + /* return "not supported" */ ptr->_errno = ENOTSUP; return -1;