From 214bc50965d7074213db4dbab8e1b3105ba72b3c Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 15 Feb 2015 08:19:23 -0600 Subject: RTC: A little more clean-up of the RTC driver --- nuttx/arch/arm/src/stm32/stm32_rtc_lowerhalf.c | 89 ++++++++++++++++++++++---- nuttx/drivers/timers/Kconfig | 42 ++++++++++-- nuttx/drivers/timers/rtc.c | 14 ++++ nuttx/include/nuttx/rtc.h | 16 +++++ 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. -- cgit v1.2.3