summaryrefslogtreecommitdiff
path: root/nuttx/sched
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-10-01 22:09:00 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-10-01 22:09:00 +0000
commit078ff53de7f505ba714be768a94c1e52e7261b3e (patch)
tree9bf8b7599be1785b828c91655da7510937c92303 /nuttx/sched
parenta65f3d1d8c639d5f3c88cee9c41f95a812abfe13 (diff)
downloadpx4-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.c57
-rw-r--r--nuttx/sched/clock_initialize.c116
-rw-r--r--nuttx/sched/clock_settime.c30
-rw-r--r--nuttx/sched/clock_systimer.c14
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