summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-02-15 08:19:23 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-02-15 08:19:23 -0600
commit214bc50965d7074213db4dbab8e1b3105ba72b3c (patch)
tree275fc436e05d9e436a76de219f6b29befbf801d2
parent2724d87aed90a1735fec74fb4d7afffef443ca48 (diff)
downloadnuttx-214bc50965d7074213db4dbab8e1b3105ba72b3c.tar.gz
nuttx-214bc50965d7074213db4dbab8e1b3105ba72b3c.tar.bz2
nuttx-214bc50965d7074213db4dbab8e1b3105ba72b3c.zip
RTC: A little more clean-up of the RTC driver
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_rtc_lowerhalf.c89
-rw-r--r--nuttx/drivers/timers/Kconfig42
-rw-r--r--nuttx/drivers/timers/rtc.c14
-rw-r--r--nuttx/include/nuttx/rtc.h16
4 files changed, 145 insertions, 16 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_rtc_lowerhalf.c b/nuttx/arch/arm/src/stm32/stm32_rtc_lowerhalf.c
index 0d3fd8e86..75ab32953 100644
--- a/nuttx/arch/arm/src/stm32/stm32_rtc_lowerhalf.c
+++ b/nuttx/arch/arm/src/stm32/stm32_rtc_lowerhalf.c
@@ -79,12 +79,10 @@ struct stm32_lowerhalf_s
****************************************************************************/
/* Prototypes for static methods in struct rtc_ops_s */
-#ifdef CONFIG_RTC_DATETIME
static int stm32_rdtime(FAR struct rtc_lowerhalf_s *lower,
FAR struct rtc_time *rtctime);
static int stm32_settime(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *rtctime);
-#endif
/****************************************************************************
* Private Data
@@ -93,24 +91,33 @@ static int stm32_settime(FAR struct rtc_lowerhalf_s *lower,
static const struct rtc_ops_s g_rtc_ops =
{
-#ifdef CONFIG_RTC_DATETIME
.rdtime = stm32_rdtime,
.settime = stm32_settime,
-#else
- .rdtime = NULL,
- .settime = NULL,
-#endif
+#ifdef CONFIG_RTC_ALARM
.almread = NULL,
.almset = NULL,
+#endif
+#ifdef CONFIG_RTC_PERIODIC
.irqpread = NULL,
.irqpset = NULL,
+#endif
+#ifdef CONFIG_RTC_ALARM
.aie = NULL,
+#endif
+#ifdef CONFIG_RTC_ONESEC
.uie = NULL,
+#endif
+#ifdef CONFIG_RTC_PERIODIC
.pie = NULL,
+#endif
+#ifdef CONFIG_RTC_EPOCHYEAR
.rdepoch = NULL,
.setepoch = NULL,
+#endif
+#ifdef CONFIG_RTC_ALARM
.rdwkalm = NULL,
.setwkalm = NULL,
+#endif
.destroy = NULL,
};
@@ -141,17 +148,62 @@ static struct stm32_lowerhalf_s g_rtc_lowerhalf =
*
****************************************************************************/
-#ifdef CONFIG_RTC_DATETIME
static int stm32_rdtime(FAR struct rtc_lowerhalf_s *lower,
FAR struct rtc_time *rtctime)
{
+#if defined(CONFIG_RTC_DATETIME)
/* This operation depends on the fact that struct rtc_time is cast
* compatible with struct tm.
*/
return up_rtc_getdatetime((FAR struct tm *)rtctime);
-}
+
+#elif defined(CONFIG_RTC_HIRES)
+ FAR struct timespec ts;
+ int ret;
+
+ /* Get the higher resolution time */
+
+ int ret = up_rtc_gettime(&ts);
+ if (ret < 0)
+ {
+ goto errout_with_errno;
+ }
+
+ /* Convert the one second epoch time to a struct tm. This operation
+ * depends on the fact that struct rtc_time and struct tm are cast
+ * compatible.
+ */
+
+ if (!gmtime_r(&ts.tv_sec, (FAR struct tm *)rtctime)
+ {
+ goto errout_with_errno;
+ }
+
+errout_with_errno;
+ ret = get_errno();
+ DEBUGASSERT(ret > 0);
+ return -ret;
+
+#else
+ FAR struct time_t timer;
+
+ /* The resolution of time is only 1 second */
+
+ timer = up_rtc_time();
+
+ /* Convert the one second epoch time to a struct tm */
+
+ if (!gmtime_r(&timer, rtctime)
+ {
+ int errcode = get_errno();
+ DEBUGASSERT(errcode > 0);
+ return -errcode;
+ }
+
+ return OK;
#endif
+}
/****************************************************************************
* Name: stm32_settime
@@ -169,17 +221,32 @@ static int stm32_rdtime(FAR struct rtc_lowerhalf_s *lower,
*
****************************************************************************/
-#ifdef CONFIG_RTC_DATETIME
static int stm32_settime(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *rtctime)
{
+#ifdef CONFIG_RTC_DATETIME
/* This operation depends on the fact that struct rtc_time is cast
* compatible with struct tm.
*/
return stm32_rtc_setdatetime((FAR const struct tm *)rtctime);
-}
+
+#else
+ struct timespec ts;
+ int ret;
+
+ /* Convert the struct rtc_time to a time_t. Here we assume that struct
+ * rtc_time is cast compatible with struct tm.
+ */
+
+ ts.tv_sec = mktime((FAR const struct tm *)rtctime)
+ ts.tv_nsec = 0;
+
+ /* Now set the time (to one second accuracy) */
+
+ return up_rtc_settime(&ts);
#endif
+}
/****************************************************************************
* Public Functions
diff --git a/nuttx/drivers/timers/Kconfig b/nuttx/drivers/timers/Kconfig
index cf05db345..af0fb3e42 100644
--- a/nuttx/drivers/timers/Kconfig
+++ b/nuttx/drivers/timers/Kconfig
@@ -61,6 +61,16 @@ config RTC_FREQUENCY
endif # !RTC_DATETIME
+config RTC_DRIVER
+ bool "RTC Driver Support"
+ default n
+ ---help---
+ This selection enables building of the "upper-half" RTC
+ driver. See include/nuttx/rtc.h for further RTC driver
+ information.
+
+if RTC_DRIVER
+
config RTC_ALARM
bool "RTC Alarm Support"
default n
@@ -68,14 +78,36 @@ config RTC_ALARM
Enable if the RTC hardware supports setting of an alarm. A callback
function will be executed when the alarm goes off.
-config RTC_DRIVER
- bool "RTC Driver Support"
+config RTC_PERIODIC
+ bool "RTC Periodic Interrupts"
default n
+ depends on EXPERIMENTAL
---help---
- This selection enables building of the "upper-half" RTC
- driver. See include/nuttx/rtc.h for further RTC driver
- information.
+ Add interrupt controls for RTCs that support periodic interrupts.
+
+config RTC_ONESEC
+ bool "RTC Once-per-second interrupts"
+ default n
+ depends on EXPERIMENTAL
+ ---help---
+ Add interrupt controls for RTCs that support once-per-second interrupts.
+
+config RTC_EPOCHYEAR
+ bool "RTC epoch year"
+ default n
+ depends on EXPERIMENTAL
+ ---help---
+ Add controls for RTCs that support epoch year settings.
+
+ Many RTCs encode the year in an 8-bit register which is either interpreted
+ as an 8-bit binary number or as a BCD number. In both cases, the number is
+ interpreted relative to this RTC's Epoch. The RTC's Epoch is initialized to
+ 1900 on most systems but on Alpha and MIPS it might also be initialized to
+ 1952, 1980, or 2000, depending on the value of an RTC register for the year.
+ With some RTCs, these operations can be used to read or to set the RTC's
+ Epoch, respectively.
+endif # RTC_DRIVER
endif # RTC
menuconfig WATCHDOG
diff --git a/nuttx/drivers/timers/rtc.c b/nuttx/drivers/timers/rtc.c
index 74f041c8c..1d4a0c827 100644
--- a/nuttx/drivers/timers/rtc.c
+++ b/nuttx/drivers/timers/rtc.c
@@ -264,6 +264,7 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
+#ifdef CONFIG_RTC_ALARM
/* RTC_ALM_READ reads the alarm time (for RTCs that support alarms)
*
* Argument: A writeable reference to a struct rtc_time to receive the
@@ -298,7 +299,9 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
}
break;
+#endif /* CONFIG_RTC_ALARM */
+#ifdef CONFIG_RTC_PERIODIC
/* RTC_IRQP_READ read the frequency for periodic interrupts (for RTCs
* that support periodic interrupts)
*
@@ -331,7 +334,9 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
}
break;
+#endif /* CONFIG_RTC_PERIODIC */
+#ifdef CONFIG_RTC_ALARM
/* RTC_AIE_ON enable alarm interrupts (for RTCs that support alarms)
*
* Argument: None
@@ -360,7 +365,9 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
}
break;
+#endif /* CONFIG_RTC_ALARM */
+#ifdef CONFIG_RTC_ONESEC
/* RTC_UIE_ON enable the interrupt on every clock update (for RTCs that
* support this once-per-second interrupt).
*
@@ -390,7 +397,9 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
}
break;
+#endif /* CONFIG_RTC_ONESEC */
+#ifdef CONFIG_RTC_PERIODIC
/* RTC_PIE_ON enable the periodic interrupt (for RTCs that support these
* periodic interrupts).
*
@@ -420,7 +429,9 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
}
break;
+#endif /* CONFIG_RTC_PERIODIC */
+#ifdef CONFIG_RTC_EPOCHYEAR
/* RTC_EPOCH_READ read the Epoch.
*
* Argument: A reference to a writeable unsigned low variable that will
@@ -452,7 +463,9 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
}
break;
+#endif /* CONFIG_RTC_EPOCHYEAR */
+#ifdef CONFIG_RTC_ALARM
/* RTC_WKALM_RD read the current alarm
*
* Argument: A writeable reference to struct rtc_wkalrm to receive the
@@ -487,6 +500,7 @@ static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
}
break;
+#endif /* CONFIG_RTC_ALARM */
default:
ret = -ENOTTY;
diff --git a/nuttx/include/nuttx/rtc.h b/nuttx/include/nuttx/rtc.h
index 1c30d2a33..3ffc5f2f2 100644
--- a/nuttx/include/nuttx/rtc.h
+++ b/nuttx/include/nuttx/rtc.h
@@ -286,6 +286,7 @@ struct rtc_time
int tm_isdst; /* unused */
};
+#ifdef CONFIG_RTC_ALARM
/* Structure used with the RTC_WKALM_RD and RTC_WKALM_SET IOCTL commands.
*
* The enabled flag is used to enable or disable the alarm interrupt, or to
@@ -302,6 +303,7 @@ struct rtc_wkalrm
unsigned char pending;
struct rtc_time time;
};
+#endif
/* The RTC driver is implemented as a common, upper-half character driver
* that provides the RTC driver structure and a lower-level, hardware
@@ -328,6 +330,7 @@ struct rtc_ops_s
CODE int (*settime)(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *rtctime);
+#ifdef CONFIG_RTC_ALARM
/* almread reads the alarm time (for RTCs that support alarms) */
CODE int (*almread)(FAR struct rtc_lowerhalf_s *lower,
@@ -337,7 +340,9 @@ struct rtc_ops_s
CODE int (*almset)(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *almtime);
+#endif
+#ifdef CONFIG_RTC_PERIODIC
/* irqpread the frequency for periodic interrupts (for RTCs that support
* periodic interrupts)
*/
@@ -351,23 +356,31 @@ struct rtc_ops_s
CODE int (*irqpset)(FAR struct rtc_lowerhalf_s *lower,
unsigned long irqpfreq);
+#endif
+#ifdef CONFIG_RTC_ALARM
/* aie enable/disable alarm interrupts (for RTCs that support alarms) */
CODE int (*aie)(FAR struct rtc_lowerhalf_s *lower, bool enable);
+#endif
+#ifdef CONFIG_RTC_ONESEC
/* uie enable/disable the interrupt on every clock update (for RTCs that
* support this once-per-second interrupt).
*/
CODE int (*uie)(FAR struct rtc_lowerhalf_s *lower, bool enable);
+#endif
+#ifdef CONFIG_RTC_PERIODIC
/* pie enable the periodic interrupt (for RTCs that support these periodic
* interrupts).
*/
CODE int (*pie)(FAR struct rtc_lowerhalf_s *lower, bool enable);
+#endif
+#ifdef CONFIG_RTC_EPOCHYEAR
/* rdepoch read the Epoch. */
CODE int (*rdepoch)(FAR struct rtc_lowerhalf_s *lower,
@@ -377,7 +390,9 @@ struct rtc_ops_s
CODE int (*setepoch)(FAR struct rtc_lowerhalf_s *lower,
unsigned long epoch);
+#endif
+#ifdef CONFIG_RTC_ALARM
/* rdwkalm read the current alarm */
CODE int (*rdwkalm)(FAR struct rtc_lowerhalf_s *lower,
@@ -387,6 +402,7 @@ struct rtc_ops_s
CODE int (*setwkalm)(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_wkalrm *wkalrm);
+#endif
/* The driver has been unlinked and there are no further open references
* to the driver.