diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-10-01 22:09:00 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-10-01 22:09:00 +0000 |
commit | 078ff53de7f505ba714be768a94c1e52e7261b3e (patch) | |
tree | 9bf8b7599be1785b828c91655da7510937c92303 /nuttx/sched | |
parent | a65f3d1d8c639d5f3c88cee9c41f95a812abfe13 (diff) | |
download | px4-nuttx-078ff53de7f505ba714be768a94c1e52e7261b3e.tar.gz px4-nuttx-078ff53de7f505ba714be768a94c1e52e7261b3e.tar.bz2 px4-nuttx-078ff53de7f505ba714be768a94c1e52e7261b3e.zip |
Add support for lo- and hi-res RTC hardware
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4005 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/sched')
-rw-r--r-- | nuttx/sched/clock_gettime.c | 57 | ||||
-rw-r--r-- | nuttx/sched/clock_initialize.c | 116 | ||||
-rw-r--r-- | nuttx/sched/clock_settime.c | 30 | ||||
-rw-r--r-- | nuttx/sched/clock_systimer.c | 14 |
4 files changed, 117 insertions, 100 deletions
diff --git a/nuttx/sched/clock_gettime.c b/nuttx/sched/clock_gettime.c index 1dc48aeb7..fc3a1593a 100644 --- a/nuttx/sched/clock_gettime.c +++ b/nuttx/sched/clock_gettime.c @@ -113,7 +113,12 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp) if (clock_id == CLOCK_REALTIME && tp) { + /* If CONFIG_SYSTEM_UTC is not defined, then we have to get the time + * from g_system_timer. + */ + #ifndef CONFIG_SYSTEM_UTC + /* Get the elapsed time since power up (in milliseconds) biased * as appropriate. */ @@ -151,47 +156,18 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp) tp->tv_sec = (time_t)secs; tp->tv_nsec = (long)nsecs; -#else /* if CONFIG_SYSTEM_UTC=y */ +#else /* CONFIG_SYSTEM_UTC */ + + /* CONFIG_SYSTEM_UTC is defined. But we might be able to get the time + * from the hardware if a high resolution RTC is available. + */ -#ifdef CONFIG_RTC +#ifdef CONFIG_RTC_HIRES if (g_rtc_enabled) { - /* up_rtc_gettime() returns the time in seconds and up_rtc_getclock() - * will return the time int RTC clock ticks. Under the hood, these - * are probably based on the same running time. However, since we - * sample this time twice, we have to add the following strange logic - * to assure that the fractional second value does not rollover to - * a full second between sampling times. - */ + /* Get the hi-resolution time from the RTC */ - clock_t rtc_frac; /* Current fractional seconds in RTC ticks */ - clock_t rtc_last; /* Previous fractional seconds in RTC ticks */ - time_t rtc_sec; /* Current seconds */ - - /* Interrupts are disabled here only to prevent interrupts and context - * switches from interfering with the consecutive time samples. I - * expect to go through this loop 1 time 99.9% of the time and then - * only twice on the remaining cornercases. - */ - - flags = irqsave(); - rtc_frac = up_rtc_getclock() & (RTC_CLOCKS_PER_SEC-1); - do - { - rtc_last = rtc_frac; - rtc_sec = up_rtc_gettime(); - rtc_frac = up_rtc_getclock() & (RTC_CLOCKS_PER_SEC-1); - } - while (rtc_frac < rtc_last); - irqrestore(flags); - - /* Okay.. the samples should be as close together in time as possible - * and we can be assured that no fractional second rollover occurred - * between the samples. - */ - - tp->tv_sec = rtc_sec; - tp->tv_nsec = rtc_frac * (1000000000/RTC_CLOCKS_PER_SEC); + ret = up_rtc_gettime(tp); } else #endif @@ -209,17 +185,16 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp) tp->tv_sec = system_utc; tp->tv_nsec = tickcount * (1000000000/TICK_PER_SEC); } -#endif +#endif /* CONFIG_SYSTEM_UTC */ - sdbg("Returning tp=(%d,%d)\n", - (int)tp->tv_sec, (int)tp->tv_nsec); + sdbg("Returning tp=(%d,%d)\n", (int)tp->tv_sec, (int)tp->tv_nsec); } /* CLOCK_ACTIVETIME is non-standard. Returns active UTC time, which is * disabled during power down modes. Unit is 1 second. */ -#ifdef CONFIG_RTC +#ifdef CONFIG_SYSTEM_UTC else if (clock_id == CLOCK_ACTIVETIME && g_rtc_enabled && tp) { /* Disable interrupts while g_system_utc and g_tickcount are sampled diff --git a/nuttx/sched/clock_initialize.c b/nuttx/sched/clock_initialize.c index 8919b6005..ed3a25828 100644 --- a/nuttx/sched/clock_initialize.c +++ b/nuttx/sched/clock_initialize.c @@ -54,6 +54,12 @@ * Definitions ****************************************************************************/ +#ifdef CONFIG_RTC +# ifndef CONFIG_SYSTEM_UTC +# error "In order to support hardware RTC system must have set the CONFIG_SYSTEM_UTC=y" +# endif +#endif + /* Standard time definitions (in units of seconds) */ #define SEC_PER_MIN ((time_t)60) @@ -85,11 +91,11 @@ ****************************************************************************/ #if CONFIG_SYSTEM_UTC -volatile time_t g_system_utc = 0; +volatile time_t g_system_utc; #else -volatile clock_t g_system_timer = 0; -struct timespec g_basetime = {0,0}; -uint32_t g_tickbias = 0; +volatile clock_t g_system_timer; +struct timespec g_basetime; +uint32_t g_tickbias; #endif /************************************************************************** @@ -102,11 +108,11 @@ uint32_t g_tickbias = 0; #if CONFIG_SYSTEM_UTC #if TICK_PER_SEC > 32767 -volatile uint32_t g_tickcount = 0; +volatile uint32_t g_tickcount; #elif TICK_PER_SEC > 255 -volatile uint16_t g_tickcount = 0; +volatile uint16_t g_tickcount; #else -volatile uint8_t g_tickcount = 0; +volatile uint8_t g_tickcount; #endif #endif /* CONFIG_SYSTEM_UTC */ @@ -114,7 +120,7 @@ volatile uint8_t g_tickcount = 0; * Private Functions **************************************************************************/ /**************************************************************************** - * Function: clock_timer + * Function: incr_utc * * Description: * This function must be called once every time the real @@ -139,49 +145,40 @@ static inline void incr_utc(void) #endif /**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Function: clock_initialize + * Function: clock_inittime * * Description: - * Perform one-time initialization of the timing facilities. + * Get the initial time value from the best source available. * ****************************************************************************/ -void clock_initialize(void) +#ifdef CONFIG_RTC +#ifdef CONFIG_RTC_HIRES + +static inline void clock_inittime(FAR struct timespec *tp) { -#ifndef CONFIG_SYSTEM_UTC - time_t jdn = 0; -#endif - /* Initialize the real time close (this should be un-nesssary except on a - * restart). - */ + /* Get the complete time from the hi-res RTC. */ + + (void)up_rtc_gettime(tp); +} -#ifdef CONFIG_SYSTEM_UTC - g_system_utc = 0; #else - g_system_timer = 0; -#endif - /* Do we have hardware RTC support? */ +static inline void clock_inittime(FAR struct timespec *tp) +{ + /* Get the seconds (only) from the lo-res RTC */ -#ifdef CONFIG_RTC + tp->tv_sec = up_rtc_time(); + tp->tv_nsec = 0; +} -#ifndef CONFIG_SYSTEM_UTC -# error In order to support hardware RTC system must have set the CONFIG_SYSTEM_UTC=y -#endif +#endif /* CONFIG_RTC_HIRES */ +#else /* CONFIG_RTC */ - up_rtcinitialize(); -#endif - -#ifndef CONFIG_SYSTEM_UTC +static inline void clock_inittime(FAR struct timespec *tp) +{ + time_t jdn = 0; /* Get the EPOCH-relative julian date from the calendar year, * month, and date @@ -192,12 +189,47 @@ void clock_initialize(void) /* Set the base time as seconds into this julian day. */ - g_basetime.tv_sec = jdn * SEC_PER_DAY; - g_basetime.tv_nsec = 0; + tp->tv_sec = jdn * SEC_PER_DAY; + tp->tv_nsec = 0; +} + +#endif /* CONFIG_RTC */ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: clock_initialize + * + * Description: + * Perform one-time initialization of the timing facilities. + * + ****************************************************************************/ + +void clock_initialize(void) +{ +#ifdef CONFIG_SYSTEM_UTC + struct timespec ts; +#endif + + /* Initialize the RTC hardware */ + +#ifdef CONFIG_RTC + up_rtcinitialize(); +#endif - /* These is no time bias from this time. */ + /* Initialize the time value */ - g_tickbias = 0; +#ifdef CONFIG_SYSTEM_UTC + clock_inittime(&ts); + g_system_utc = ts.tv_sec; + g_tickcount = ((ts.tv_nsec > 10) * CLOCKS_PER_SEC) / (1000000000 >> 10); +#else + clock_inittime(&g_basetime); + g_system_timer = 0; + g_tickbias = 0; #endif } diff --git a/nuttx/sched/clock_settime.c b/nuttx/sched/clock_settime.c index 77b6ebecc..299e8c65b 100644 --- a/nuttx/sched/clock_settime.c +++ b/nuttx/sched/clock_settime.c @@ -43,6 +43,8 @@ #include <time.h> #include <errno.h> #include <debug.h> + +#include <arch/irq.h> #include "clock_internal.h" /************************************************************************ @@ -85,7 +87,7 @@ * ************************************************************************/ -int clock_settime(clockid_t clock_id, const struct timespec *tp) +int clock_settime(clockid_t clock_id, FAR const struct timespec *tp) { int ret = OK; @@ -116,12 +118,13 @@ int clock_settime(clockid_t clock_id, const struct timespec *tp) #ifdef CONFIG_RTC if (g_rtc_enabled) { - up_rtc_settime(tp->tv_sec); + up_rtc_settime(tp); } else #endif - g_system_utc = tp->tv_sec; - + { + g_system_utc = tp->tv_sec; + } #endif sdbg("basetime=(%d,%d) tickbias=%d\n", @@ -133,10 +136,25 @@ int clock_settime(clockid_t clock_id, const struct timespec *tp) * disabled during power down modes. Unit is 1 second. */ -#ifdef CONFIG_RTC - else if (clock_id == CLOCK_ACTIVETIME && g_rtc_enabled && tp) +#ifdef CONFIG_SYSTEM_UTC + else if (clock_id == CLOCK_ACTIVETIME && tp) { + irqstate_t flags; + uint32_t tickcount; + + /* Calculate the number of ticks correspond to the nanosecond count... + * exercising care to avoid overflows. This could still overflow + * if CLOCKS_PER_SEC is very large (something like 4096). + */ + + tickcount = ((tp->tv_nsec >> 10) * CLOCKS_PER_SEC) / (1000000000 >> 10); + + /* Then set the UTC time (seconds) plus the tickcount (fractional seconds */ + + flags = irqsave(); g_system_utc = tp->tv_sec; + g_tickcount = tickcount; + irqrestore(flags); } #endif diff --git a/nuttx/sched/clock_systimer.c b/nuttx/sched/clock_systimer.c index cfa019fc7..2061b1de6 100644 --- a/nuttx/sched/clock_systimer.c +++ b/nuttx/sched/clock_systimer.c @@ -85,20 +85,12 @@ uint32_t clock_systimer(void) uint32_t tickcount; #endif - /* Fetch the g_system_timer value from timer hardware, if available */ - -#ifdef CONFIG_RTC - - /* Check if the periodic timer is initialized +#ifdef CONFIG_RTC_HIRES + /* Fetch the g_system_timer value from timer hardware, if available. * - * Note that the unit of the g_system_timer and and up_rtc_getclock() do + * Note that the unit of the g_system_timer and and up_rtc_gettime() do * not have the same unit. */ - - if (g_rtc_enabled) - { - /* return up_rtc_getclock(); */ - } #endif #ifndef CONFIG_SYSTEM_UTC |