From 0b910748505672560ea8b2a4e7c13b832ed1b4e8 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 25 Dec 2017 13:56:06 -0600 Subject: [PATCH] arch/arm/src/lpc54xx: Add an RTC driver and a RTC character driver lower half. configs/lpcxpresso-lpc54628: Add logic to register the RTC character driver if it is enabled. Enable the RTC and RTC character driver in the NSH configuration. --- arch/arm/src/lpc54xx/Kconfig | 5 + arch/arm/src/lpc54xx/Make.defs | 7 + arch/arm/src/lpc54xx/chip/lpc54_rtc.h | 96 +++ arch/arm/src/lpc54xx/chip/lpc54_syscon.h | 10 +- arch/arm/src/lpc54xx/lpc54_rtc.c | 377 ++++++++++ arch/arm/src/lpc54xx/lpc54_rtc.h | 172 +++++ arch/arm/src/lpc54xx/lpc54_rtc_lowerhalf.c | 660 ++++++++++++++++++ arch/arm/src/stm32/stm32_rtc.h | 8 +- configs/lpcxpresso-lpc54628/README.txt | 17 + configs/lpcxpresso-lpc54628/nsh/defconfig | 4 + .../lpcxpresso-lpc54628/src/lpc54_bringup.c | 32 +- .../src/lpcxpresso-lpc54628.h | 13 +- 12 files changed, 1389 insertions(+), 12 deletions(-) create mode 100644 arch/arm/src/lpc54xx/chip/lpc54_rtc.h create mode 100644 arch/arm/src/lpc54xx/lpc54_rtc.c create mode 100644 arch/arm/src/lpc54xx/lpc54_rtc.h create mode 100644 arch/arm/src/lpc54xx/lpc54_rtc_lowerhalf.c diff --git a/arch/arm/src/lpc54xx/Kconfig b/arch/arm/src/lpc54xx/Kconfig index 825dfb3b43..9e186a5637 100644 --- a/arch/arm/src/lpc54xx/Kconfig +++ b/arch/arm/src/lpc54xx/Kconfig @@ -406,6 +406,11 @@ config LPC54_LCD default n depends on ARCH_LPC54_HAVE_LCD +config LPC54_RTC + bool "RTC" + default n + select RTC + config LPC54_SDMMC bool "SD/MMC" default n diff --git a/arch/arm/src/lpc54xx/Make.defs b/arch/arm/src/lpc54xx/Make.defs index 8b4d643290..519d3fbf78 100644 --- a/arch/arm/src/lpc54xx/Make.defs +++ b/arch/arm/src/lpc54xx/Make.defs @@ -105,6 +105,13 @@ ifeq ($(CONFIG_LPC54_GPIOIRQ),y) CHIP_CSRCS += lpc54_gpioirq.c endif +ifeq ($(CONFIG_RTC),y) +CHIP_CSRCS += lpc54_rtc.c +ifeq ($(CONFIG_RTC_DRIVER),y) +CHIP_CSRCS += lpc54_rtc_lowerhalf.c +endif +endif + ifeq ($(CONFIG_LPC54_WWDT),y) CHIP_CSRCS += lpc54_wwdt.c endif diff --git a/arch/arm/src/lpc54xx/chip/lpc54_rtc.h b/arch/arm/src/lpc54xx/chip/lpc54_rtc.h new file mode 100644 index 0000000000..5a6f730cdd --- /dev/null +++ b/arch/arm/src/lpc54xx/chip/lpc54_rtc.h @@ -0,0 +1,96 @@ +/******************************************************************************************** + * arch/arm/src/lpc54xx/lpc54_rtc.h + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_RTC_H +#define __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_RTC_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include +#include "chip/lpc54_memorymap.h" + +/******************************************************************************************** + * Pre-processor Definitions + ********************************************************************************************/ + +#define LPC54_RTC_NGPREGS 8 /* Nubmer of general purpose registers */ + +/* Register offsets *************************************************************************/ + +#define LPC54_RTC_CTRL_OFFSET 0x0000 /* RTC control */ +#define LPC54_RTC_MATCH_OFFSET 0x0004 /* RTC match */ +#define LPC54_RTC_COUNT_OFFSET 0x0008 /* RTC counter */ +#define LPC54_RTC_WAKE_OFFSET 0x000c /* High-resolution/wake-up timer control */ + +/* General purpose registers */ + +#define LPC54_RTC_GPREG_OFFSET(n) (0x0040 + ((n) << 2)) + +/* Register addresses ***********************************************************************/ + +#define LPC54_RTC_CTRL (LPC54_RTC_BASE + LPC54_RTC_CTRL_OFFSET) +#define LPC54_RTC_MATCH (LPC54_RTC_BASE + LPC54_RTC_MATCH_OFFSET) +#define LPC54_RTC_COUNT (LPC54_RTC_BASE + LPC54_RTC_COUNT_OFFSET) +#define LPC54_RTC_WAKE (LPC54_RTC_BASE + LPC54_RTC_WAKE_OFFSET) + +/* General purpose registers */ + +#define LPC54_RTC_GPREG(n) (LPC54_RTC_BASE + LPC54_RTC_GPREG_OFFSET(n)) + +/* Register bit definitions *****************************************************************/ + +/* RTC control */ + +#define RTC_CTRL_SWRESET (1 << 0) /* Bit 0: Software reset control */ +#define RTC_CTRL_ALARM1HZ (1 << 2) /* Bit 2: RTC 1 Hz timer alarm flag status */ +#define RTC_CTRL_WAKE1KHZ (1 << 3) /* Bit 3: RTC 1 kHz timer wake-up flag status */ +#define RTC_CTRL_ALARMDPDEN (1 << 4) /* Bit 4: RTC 1 Hz timer alarm enable for deep power-down */ +#define RTC_CTRL_WAKEDPDEN (1 << 5) /* Bit 5: RTC 1 kHz timer wake-up enable for deep power-down */ +#define RTC_CTRL_RTC1KHZEN (1 << 6) /* Bit 6: RTC 1 kHz clock enable */ +#define RTC_CTRL_RTCEN (1 << 7) /* Bit 7: RTC enable */ +#define RTC_CTRL_OSCPD (1 << 8) /* Bit 8: RTC oscillator power-down control */ + +/* RTC match (32-bit timer match value) */ +/* RTC counter (32-bit counter value) */ + +/* High-resolution/wake-up timer control */ + +#define RTC_WAKE_MASK 0xffff /* Bits 0-15: 16 hi-resoution/wake-up timer */ + +/* General purpose registers (32-bit value) */ + +#endif /* __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_RTC_H */ diff --git a/arch/arm/src/lpc54xx/chip/lpc54_syscon.h b/arch/arm/src/lpc54xx/chip/lpc54_syscon.h index 5f8883bfd0..c9ea6b29a1 100644 --- a/arch/arm/src/lpc54xx/chip/lpc54_syscon.h +++ b/arch/arm/src/lpc54xx/chip/lpc54_syscon.h @@ -279,7 +279,7 @@ #define LPC54_SYSCON_FROCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_FROCTRL_OFFSET) #define LPC54_SYSCON_SYSOSCCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_SYSOSCCTRL_OFFSET) #define LPC54_SYSCON_WDTOSCCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_WDTOSCCTRL_OFFSET) -#define LPC54_SYSCON_RTCOSCCTRL_ (LPC54_SYSCON_BASE + LPC54_SYSCON_RTCOSCCTRL_OFFSET) +#define LPC54_SYSCON_RTCOSCCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_RTCOSCCTRL_OFFSET) #define LPC54_SYSCON_USBPLLCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_USBPLLCTRL_OFFSET) #define LPC54_SYSCON_USBPLLSTAT (LPC54_SYSCON_BASE + LPC54_SYSCON_USBPLLSTAT_OFFSET) #define LPC54_SYSCON_SYSPLLCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_SYSPLLCTRL_OFFSET) @@ -741,8 +741,8 @@ #define SYSCON_WDTOSCCTRL_FREQSEL_SHIFT (5) /* Bits 5-9: Frequency select */ #define SYSCON_WDTOSCCTRL_FREQSEL_MASK (0x1f << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) # define SYSCON_WDTOSCCTRL_FREQSEL_04pMHZ (1 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.4 MHz */ -# define SYSCON_WDTOSCCTRL_FREQSEL_0p75MHZ (2 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.6 MHz */ -# define SYSCON_WDTOSCCTRL_FREQSEL_0p9MHZ (3 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.75 MHz */ +# define SYSCON_WDTOSCCTRL_FREQSEL_0p6MHZ (2 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.6 MHz */ +# define SYSCON_WDTOSCCTRL_FREQSEL_0p75MHZ (3 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.75 MHz */ # define SYSCON_WDTOSCCTRL_FREQSEL_0p9MHZ (4 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.9 MHz */ # define SYSCON_WDTOSCCTRL_FREQSEL_1p0MHZ (5 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 1.0 MHz */ # define SYSCON_WDTOSCCTRL_FREQSEL_1p2MHZ (6 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 1.2 MHz */ @@ -773,7 +773,9 @@ # define SYSCON_WDTOSCCTRL_FREQSEL_3p05MHZ (31 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 3.05 MHz */ /* RTC oscillator 32 kHz output control */ -#define SYSCON_RTCOSCCTRL_ + +#define SYSCON_RTCOSCCTRL_EN (1 << 0) /* Bit 0: RTC 32 kHz clock enable */ + /* USB PLL control */ #define SYSCON_USBPLLCTRL_ /* USB PLL status */ diff --git a/arch/arm/src/lpc54xx/lpc54_rtc.c b/arch/arm/src/lpc54xx/lpc54_rtc.c new file mode 100644 index 0000000000..064100b3b4 --- /dev/null +++ b/arch/arm/src/lpc54xx/lpc54_rtc.c @@ -0,0 +1,377 @@ +/**************************************************************************** + * arch/arm/src/lpc54/lpc54_rtc.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "up_arch.h" + +#include "chip/lpc54_rtc.h" +#include "lpc54_enableclk.h" +#include "lpc54_rtc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifdef CONFIG_RTC_HIRES +# error "CONFIG_RTC_HIRES is not supported" +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +/* Callback to use when the alarm expires */ + +static alarmcb_t g_alarmcb; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Variable determines if the RTC has been initialized and enabled. */ + +volatile bool g_rtc_enabled = false; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lpc54_rtc_interrupt + * + * Description: + * RTC interrupt service routine + * + * Input Parameters: + * irq - The IRQ number that generated the interrupt + * context - Architecture specific register save information. + * + * Returned Value: + * Zero (OK) on success; A negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static int lpc54_rtc_interrupt(int irq, void *context, FAR void *arg) +{ + uint32_t status = getreg16(LPC54_RTC_CTRL); + + if ((status & RTC_CTRL_ALARM1HZ) != 0 && g_alarmcb != NULL) + { + /* Clear pending status */ + + putreg32(status | RTC_CTRL_ALARM1HZ | RTC_CTRL_WAKE1KHZ, LPC54_RTC_CTRL); + + /* Perform the alarm callback */ + + g_alarmcb(); + g_alarmcb = NULL; + } + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_rtc_initialize + * + * Description: + * Initialize the hardware RTC per the selected configuration. This function is + * called once during the OS initialization sequence + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int up_rtc_initialize(void) +{ + uint32_t regval; + + /* Enable the clock to the RTC register interface and peripheral clock. */ + + lpc54_rtc_enableclk(); + + /* If the 32 kHz output of the RTC is used by another part of the system, enable it + * via the EN bit in the RTCOSCCTRL register + */ + + putreg32(SYSCON_RTCOSCCTRL_EN, LPC54_SYSCON_RTCOSCCTRL); + + /* The RTC is already running or, perhaps waiting to be enabled if it was never + * configured. We will set enable the RTC only if the time if initialized by + * higher level logic. + */ + + g_rtc_enabled = true; + return OK; +} + +/**************************************************************************** + * Name: up_rtc_time + * + * Description: + * Get the current time in seconds. This is similar to the standard time() + * function. This interface is only required if the low-resolution RTC/counter + * hardware implementation selected. It is only used by the RTOS during + * initialization to set up the system time when CONFIG_RTC is set. + * + * Input Parameters: + * None + * + * Returned Value: + * The current time in seconds + * + ****************************************************************************/ + +time_t up_rtc_time(void) +{ + /* Read and return the 32-bit 1Hz RTC counter value */ + + return getreg32(LPC54_RTC_COUNT); +} + +/**************************************************************************** + * Name: up_rtc_settime + * + * Description: + * Set the RTC to the provided time. All RTC implementations must be + * able to set their time based on a standard timespec. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int up_rtc_settime(FAR const struct timespec *tp) +{ + irqstate_t flags; + uint32_t regval; + + /* Read the Break out the time values */ + + flags = enter_critical_section(); + + /* Make sure the the RTC is out of reset, but not enabled. */ + + regval = getreg32(LPC54_RTC_CTRL); + regval &= ~(RTC_CTRL_SWRESET | RTC_CTRL_RTCEN | RTC_CTRL_RTC1KHZEN | + RTC_CTRL_OSCPD); + putreg32(regval, LPC54_RTC_CTRL); + + /* Then write the time in seconds to the counter register. NOTE that we + * can only write to this register when the RTC_EN bit in the RTC CTRL + * Register is 0. + */ + + putreg32(tp->tv_sec, LPC54_RTC_COUNT); + + /* (Re-)enabled the RTC. The counter increments one second after the + * RTC_EN bit is set. + */ + + regval |= RTC_CTRL_RTCEN; + putreg32(regval, LPC54_RTC_CTRL); + + /* Make sure that magic value is in the general purpose register */ + + putreg32(RTC_MAGIC, RTC_MAGIC_REG); + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: lpc54_rtc_setalarm + * + * Description: + * Set up an alarm. + * + * Input Parameters: + * tp - The time to set the alarm + * callback - The function to call when the alarm expires. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int lpc54_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback) +{ + irqstate_t flags; + uint32_t regval; + int ret = -EBUSY; + + /* Is there already something waiting on the ALARM? */ + + flags = enter_critical_section(); + if (g_alarmcb == NULL) + { + /* No.. Save the callback function pointer */ + + g_alarmcb = callback; + + /* Make sure the the RTC is out of reset. */ + + regval = getreg32(LPC54_RTC_CTRL); + regval &= ~(RTC_CTRL_SWRESET | RTC_CTRL_ALARMDPDEN | RTC_CTRL_RTC1KHZEN | + RTC_CTRL_WAKEDPDEN | RTC_CTRL_OSCPD); + putreg32(regval, LPC54_RTC_CTRL); + + /* Make sure that the ALARM interrupt is attached and enabled. */ + + irq_attach(LPC54_IRQ_RTC, lpc54_rtc_interrupt, NULL); + up_enable_irq(LPC54_IRQ_RTC); + + /* Set the alarm match register */ + + putreg32(tp->tv_sec, LPC54_RTC_MATCH); + + /* Enable RTC alarm */ + + regval |= RTC_CTRL_ALARMDPDEN; + putreg32(regval, LPC54_RTC_CTRL); + ret = OK; + } + + leave_critical_section(flags); + return ret; +} +#endif + +/**************************************************************************** + * Name: lpc54_rtc_rdalarm + * + * Description: + * Query an alarm configured in hardware. + * + * Input Parameters: + * time - Current alarm setting. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int lpc54_rtc_rdalarm(FAR struct tm *time) +{ + uint32_t match; + + match = getreg32(LPC54_RTC_MATCH); + (void)gmtime_r((time_t *)&match, time); + return OK; +} +#endif + +/**************************************************************************** + * Name: lpc54_rtc_cancelalarm + * + * Description: + * Cancel a pending alarm alarm + * + * Input Parameters: + * none + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int lpc54_rtc_cancelalarm(void) +{ + irqstate_t flags; + uint32_t regval; + int ret = -ENODATA; + + flags = enter_critical_section(); + if (g_alarmcb != NULL) + { + /* Cancel the global callback function */ + + g_alarmcb = NULL; + + /* Disable the Alarm interrupt */ + + up_disable_irq(LPC54_IRQ_RTC); + + /* Unset the alarm */ + + regval = getreg32(LPC54_RTC_CTRL); + regval &= ~(RTC_CTRL_SWRESET | RTC_CTRL_ALARMDPDEN | RTC_CTRL_RTC1KHZEN | + RTC_CTRL_WAKEDPDEN | RTC_CTRL_OSCPD); + putreg32(regval, LPC54_RTC_CTRL); + + ret = OK; + } + + leave_critical_section(flags); + return ret; +} +#endif diff --git a/arch/arm/src/lpc54xx/lpc54_rtc.h b/arch/arm/src/lpc54xx/lpc54_rtc.h new file mode 100644 index 0000000000..cad7452b2b --- /dev/null +++ b/arch/arm/src/lpc54xx/lpc54_rtc.h @@ -0,0 +1,172 @@ +/**************************************************************************** + * arch/arm/src/lpc54xx/lpc54_rtc.h + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LPC54XX_LPC54_RTC_H +#define __ARCH_ARM_SRC_LPC54XX_LPC54_RTC_H + +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define RTC_MAGIC (0xfacefeed) +#define RTC_MAGIC_REG LPC54_RTC_GPREG(0) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_RTC_ALARM +/* The form of an alarm callback */ + +typedef CODE void (*alarmcb_t)(void); +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lpc54_rtc_setalarm + * + * Description: + * Set up an alarm. + * + * Input Parameters: + * tp - the time to set the alarm + * callback - the function to call when the alarm expires. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +struct timespec; +int lpc54_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback); +#endif + +/**************************************************************************** + * Name: lpc54_rtc_rdalarm + * + * Description: + * Query an alarm configured in hardware. + * + * Input Parameters: + * time - Current alarm setting. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +struct tm; +int lpc54_rtc_rdalarm(FAR struct tm *time); +#endif + +/**************************************************************************** + * Name: lpc54_rtc_cancelalarm + * + * Description: + * Cancel a pending alarm alarm + * + * Input Parameters: + * none + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int lpc54_rtc_cancelalarm(void); +#endif + +/**************************************************************************** + * Name: lpc54_rtc_lowerhalf + * + * Description: + * Instantiate the RTC lower half driver for the LPC54. General usage: + * + * #include + * #include "lpc54_rtc.h" + * + * struct rtc_lowerhalf_s *lower; + * lower = lpc54_rtc_lowerhalf(); + * rtc_initialize(0, lower); + * + * Input Parameters: + * None + * + * Returned Value: + * On success, a non-NULL RTC lower interface is returned. NULL is + * returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_DRIVER +struct rtc_lowerhalf_s; +FAR struct rtc_lowerhalf_s *lpc54_rtc_lowerhalf(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LPC54XX_LPC54_RTC_H */ diff --git a/arch/arm/src/lpc54xx/lpc54_rtc_lowerhalf.c b/arch/arm/src/lpc54xx/lpc54_rtc_lowerhalf.c new file mode 100644 index 0000000000..6413c6d3f7 --- /dev/null +++ b/arch/arm/src/lpc54xx/lpc54_rtc_lowerhalf.c @@ -0,0 +1,660 @@ +/**************************************************************************** + * arch/arm/src/lpc54xx/lpc54_rtc_lowerhalf.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" + +#include "chip/lpc54_rtc.h" +#include "lpc54_rtc.h" + +#ifdef CONFIG_RTC_DRIVER + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +struct lpc54_cbinfo_s +{ + volatile rtc_alarm_callback_t cb; /* Callback when the alarm expires */ + volatile FAR void *priv; /* Private argument to accompany callback */ +}; +#endif + +/* This is the private type for the RTC state. It must be cast compatible + * with struct rtc_lowerhalf_s. + */ + +struct lpc54_lowerhalf_s +{ + /* This is the contained reference to the read-only, lower-half + * operations vtable (which may lie in FLASH or ROM) + */ + + FAR const struct rtc_ops_s *ops; + + /* Data following is private to this driver and not visible outside of + * this file. + */ + + sem_t devsem; /* Threads can only exclusively access the RTC */ + +#ifdef CONFIG_RTC_ALARM + /* Alarm callback information */ + + struct lpc54_cbinfo_s cbinfo; +#endif + +#ifdef CONFIG_RTC_PERIODIC + /* Periodic wakeup information */ + + struct lower_setperiodic_s periodic; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Prototypes for static methods in struct rtc_ops_s */ + +static int lpc54_rdtime(FAR struct rtc_lowerhalf_s *lower, + FAR struct rtc_time *rtctime); +static int lpc54_settime(FAR struct rtc_lowerhalf_s *lower, + FAR const struct rtc_time *rtctime); +static bool lpc54_havesettime(FAR struct rtc_lowerhalf_s *lower); + +#ifdef CONFIG_RTC_ALARM +static int lpc54_setalarm(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setalarm_s *alarminfo); +static int lpc54_setrelative(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setrelative_s *alarminfo); +static int lpc54_cancelalarm(FAR struct rtc_lowerhalf_s *lower, + int alarmid); +static int lpc54_rdalarm(FAR struct rtc_lowerhalf_s *lower, + FAR struct lower_rdalarm_s *alarminfo); +#endif + +#ifdef CONFIG_RTC_PERIODIC +static int lpc54_setperiodic(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setperiodic_s *alarminfo); +static int lpc54_cancelperiodic(FAR struct rtc_lowerhalf_s *lower, int id); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* LPC54 RTC driver operations */ + +static const struct rtc_ops_s g_rtc_ops = +{ + .rdtime = lpc54_rdtime, + .settime = lpc54_settime, + .havesettime = lpc54_havesettime, +#ifdef CONFIG_RTC_ALARM + .setalarm = lpc54_setalarm, + .setrelative = lpc54_setrelative, + .cancelalarm = lpc54_cancelalarm, + .rdalarm = lpc54_rdalarm, +#endif +#ifdef CONFIG_RTC_PERIODIC + .setperiodic = lpc54_setperiodic, + .cancelperiodic = lpc54_cancelperiodic, +#endif +#ifdef CONFIG_RTC_IOCTL + .ioctl = NULL, +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + .destroy = NULL, +#endif +}; + +/* LPC54 RTC device state */ + +static struct lpc54_lowerhalf_s g_rtc_lowerhalf = +{ + .ops = &g_rtc_ops, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lpc54_alarm_callback + * + * Description: + * This is the function that is called from the RTC driver when the alarm + * goes off. It just invokes the upper half drivers callback. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static void lpc54_alarm_callback(void) +{ + FAR struct lpc54_cbinfo_s *cbinfo = &g_rtc_lowerhalf.cbinfo; + + /* Sample and clear the callback information to minimize the window in + * time in which race conditions can occur. + */ + + rtc_alarm_callback_t cb = (rtc_alarm_callback_t)cbinfo->cb; + FAR void *arg = (FAR void *)cbinfo->priv; + + cbinfo->cb = NULL; + cbinfo->priv = NULL; + + /* Perform the callback */ + + if (cb != NULL) + { + cb(arg, 0); + } +} +#endif /* CONFIG_RTC_ALARM */ + +/**************************************************************************** + * Name: lpc54_rdtime + * + * Description: + * Implements the rdtime() method of the RTC driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * rcttime - The location in which to return the current RTC time. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +static int lpc54_rdtime(FAR struct rtc_lowerhalf_s *lower, + FAR struct rtc_time *rtctime) +{ + 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, (FAR struct tm *)rtctime)) + { + int errcode = get_errno(); + DEBUGASSERT(errcode > 0); + return -errcode; + } + + return OK; +} + +/**************************************************************************** + * Name: lpc54_settime + * + * Description: + * Implements the settime() method of the RTC driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * rcttime - The new time to set + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +static int lpc54_settime(FAR struct rtc_lowerhalf_s *lower, + FAR const struct rtc_time *rtctime) +{ + struct timespec ts; + + /* 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 struct tm *)rtctime); + ts.tv_nsec = 0; + + /* Now set the time (to one second accuracy) */ + + return up_rtc_settime(&ts); +} + +/**************************************************************************** + * Name: lpc54_havesettime + * + * Description: + * Implements the havesettime() method of the RTC driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * + * Returned Value: + * Returns true if RTC date-time have been previously set. + * + ****************************************************************************/ + +static bool lpc54_havesettime(FAR struct rtc_lowerhalf_s *lower) +{ + return getreg32(RTC_MAGIC_REG) == RTC_MAGIC; +} + +/**************************************************************************** + * Name: lpc54_setalarm + * + * Description: + * Set a new alarm. This function implements the setalarm() method of the + * RTC driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * alarminfo - Provided information needed to set the alarm + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static int lpc54_setalarm(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setalarm_s *alarminfo) +{ + FAR struct lpc54_lowerhalf_s *priv; + FAR struct lpc54_cbinfo_s *cbinfo; + int ret; + + DEBUGASSERT(lower != NULL && alarminfo != NULL && alarminfo->id == 0); + priv = (FAR struct lpc54_lowerhalf_s *)lower; + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + ret = -EINVAL; + if (alarminfo->id == 0) + { + struct timespec ts; + + /* Convert the RTC time to a timespec (1 second accuracy) */ + + ts.tv_sec = mktime((FAR struct tm *)&alarminfo->time); + ts.tv_nsec = 0; + + /* Remember the callback information */ + + cbinfo = &priv->cbinfo; + cbinfo->cb = alarminfo->cb; + cbinfo->priv = alarminfo->priv; + + /* And set the alarm */ + + ret = lpc54_rtc_setalarm(&ts, lpc54_alarm_callback); + if (ret < 0) + { + cbinfo->cb = NULL; + cbinfo->priv = NULL; + } + } + + nxsem_post(&priv->devsem); + return ret; +} +#endif + +/**************************************************************************** + * Name: lpc54_setrelative + * + * Description: + * Set a new alarm relative to the current time. This function implements + * the setrelative() method of the RTC driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * alarminfo - Provided information needed to set the alarm + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static int lpc54_setrelative(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setrelative_s *alarminfo) +{ + FAR struct lpc54_lowerhalf_s *priv; + FAR struct lpc54_cbinfo_s *cbinfo; + FAR struct timespec ts; + int ret = -EINVAL; + + DEBUGASSERT(lower != NULL && alarminfo != NULL && alarminfo->id == 0); + priv = (FAR struct lpc54_lowerhalf_s *)lower; + + if (alarminfo->id == 0 && alarminfo->reltime > 0) + { + /* Disable pre-emption while we do this so that we don't have to worry + * about being suspended and working on an old time. + */ + + sched_lock(); + + /* Get the current time in seconds */ + + ts.tv_sec = up_rtc_time(); + ts.tv_nsec = 0; + + /* Add the seconds offset. Add one to the number of seconds because + * we are unsure of the phase of the timer. + */ + + ts.tv_sec += (alarminfo->reltime + 1); + + /* Remember the callback information */ + + cbinfo = &priv->cbinfo; + cbinfo->cb = alarminfo->cb; + cbinfo->priv = alarminfo->priv; + + /* And set the alarm */ + + ret = lpc54_rtc_setalarm(&ts, lpc54_alarm_callback); + if (ret < 0) + { + cbinfo->cb = NULL; + cbinfo->priv = NULL; + } + + sched_unlock(); + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: lpc54_cancelalarm + * + * Description: + * Cancel the current alarm. This function implements the cancelalarm() + * method of the RTC driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * alarminfo - Provided information needed to set the alarm + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static int lpc54_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid) +{ + FAR struct lpc54_lowerhalf_s *priv; + FAR struct lpc54_cbinfo_s *cbinfo; + + DEBUGASSERT(lower != NULL); + DEBUGASSERT(alarmid == 0); + priv = (FAR struct lpc54_lowerhalf_s *)lower; + + /* Nullify callback information to reduce window for race conditions */ + + cbinfo = &priv->cbinfo; + cbinfo->cb = NULL; + cbinfo->priv = NULL; + + /* Then cancel the alarm */ + + return lpc54_rtc_cancelalarm(); +} +#endif + +/**************************************************************************** + * Name: lpc54_rdalarm + * + * Description: + * Query the RTC alarm. + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * alarminfo - Provided information needed to query the alarm + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static int lpc54_rdalarm(FAR struct rtc_lowerhalf_s *lower, + FAR struct lower_rdalarm_s *alarminfo) +{ + int ret = -EINVAL; + + DEBUGASSERT(lower != NULL && alarminfo != NULL && alarminfo->id == 0 && + alarminfo->time != NULL); + + if (alarminfo->id == 0) + { + ret = lpc54_rtc_rdalarm((FAR struct tm *)alarminfo->time); + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: lpc54_periodic_callback + * + * Description: + * This is the function that is called from the RTC driver when the periodic + * wakeup goes off. It just invokes the upper half drivers callback. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +static int lpc54_periodic_callback(void) +{ + FAR struct lpc54_lowerhalf_s *lower; + struct lower_setperiodic_s *cbinfo; + rtc_wakeup_callback_t cb; + FAR void *priv; + + lower = (FAR struct lpc54_lowerhalf_s *)&g_rtc_lowerhalf; + + cbinfo = &lower->periodic; + cb = (rtc_wakeup_callback_t)cbinfo->cb; + priv = (FAR void *)cbinfo->priv; + + /* Perform the callback */ + + if (cb != NULL) + { + cb(priv, 0); + } + + return OK; +} +#endif /* CONFIG_RTC_PERIODIC */ + +/**************************************************************************** + * Name: lpc54_setperiodic + * + * Description: + * Set a new periodic wakeup relative to the current time, with a given + * period. This function implements the setperiodic() method of the RTC + * driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * alarminfo - Provided information needed to set the wakeup activity + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +static int lpc54_setperiodic(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setperiodic_s *alarminfo) +{ + FAR struct lpc54_lowerhalf_s *priv; + int ret; + + ASSERT(lower != NULL && alarminfo != NULL); + priv = (FAR struct lpc54_lowerhalf_s *)lower; + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + memcpy(&priv->periodic, alarminfo, sizeof(struct lower_setperiodic_s)); + + ret = lpc54_rtc_setperiodic(&alarminfo->period, lpc54_periodic_callback); + + nxsem_post(&priv->devsem); + return ret; +} +#endif + +/**************************************************************************** + * Name: lpc54_cancelperiodic + * + * Description: + * Cancel the current periodic wakeup activity. This function implements + * the cancelperiodic() method of the RTC driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +static int lpc54_cancelperiodic(FAR struct rtc_lowerhalf_s *lower, int id) +{ + FAR struct lpc54_lowerhalf_s *priv; + int ret; + + DEBUGASSERT(lower != NULL); + priv = (FAR struct lpc54_lowerhalf_s *)lower; + + DEBUGASSERT(id == 0); + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + ret = lpc54_rtc_cancelperiodic(); + + nxsem_post(&priv->devsem); + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lpc54_rtc_lowerhalf + * + * Description: + * Instantiate the RTC lower half driver for the LPC54. General usage: + * + * #include + * #include "lpc54_rtc.h> + * + * struct rtc_lowerhalf_s *lower; + * lower = lpc54_rtc_lowerhalf(); + * rtc_initialize(0, lower); + * + * Input Parameters: + * None + * + * Returned Value: + * On success, a non-NULL RTC lower interface is returned. NULL is + * returned on any failure. + * + ****************************************************************************/ + +FAR struct rtc_lowerhalf_s *lpc54_rtc_lowerhalf(void) +{ + nxsem_init(&g_rtc_lowerhalf.devsem, 0, 1); + + return (FAR struct rtc_lowerhalf_s *)&g_rtc_lowerhalf; +} + +#endif /* CONFIG_RTC_DRIVER */ diff --git a/arch/arm/src/stm32/stm32_rtc.h b/arch/arm/src/stm32/stm32_rtc.h index fff697af45..c18daf9144 100644 --- a/arch/arm/src/stm32/stm32_rtc.h +++ b/arch/arm/src/stm32/stm32_rtc.h @@ -96,7 +96,7 @@ #else /* !CONFIG_STM32_STM32F10XX */ #if !defined(CONFIG_RTC_MAGIC) -# define CONFIG_RTC_MAGIC (0xfacefeee) +# define CONFIG_RTC_MAGIC (0xfacefeed) #endif #if !defined(CONFIG_RTC_MAGIC_REG) @@ -137,7 +137,7 @@ extern "C" * Public Functions ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Name: stm32_rtc_irqinitialize * * Description: @@ -150,7 +150,7 @@ extern "C" * Returned Value: * Zero (OK) on success; a negated errno on failure * - ************************************************************************************/ + ****************************************************************************/ int stm32_rtc_irqinitialize(void); @@ -208,7 +208,7 @@ int stm32_rtc_setdatetime(FAR const struct tm *tp); * Instantiate the RTC lower half driver for the STM32. General usage: * * #include - * #include "stm32_rtc.h> + * #include "stm32_rtc.h" * * struct rtc_lowerhalf_s *lower; * lower = stm32_rtc_lowerhalf(); diff --git a/configs/lpcxpresso-lpc54628/README.txt b/configs/lpcxpresso-lpc54628/README.txt index 920c6882fb..b2e85c1192 100644 --- a/configs/lpcxpresso-lpc54628/README.txt +++ b/configs/lpcxpresso-lpc54628/README.txt @@ -73,6 +73,8 @@ STATUS 2017-12-24: Added basic DMA support; brought in the WWDT driver from the LPC43 which has the same peripheral. Neither tested; almost certainly non-functional without some additional investment. + 2017-12-25: Added an RTC driver. It appears to be functional but has not + been well tested. There is still no support for the Accelerometer, SPIFI, Ethernet, or USB. There is a complete, but not-yet-functional SD card drirver. There is a @@ -344,6 +346,21 @@ Configurations CONFIG_NSH_MMCSDSLOTNO=0 + 6. The RTC is enabled in this configuration. + + NuttShell (NSH) NuttX-7.23 + nsh> date + Jan 01 00:00:06 1970 + nsh> date -s "DEC 25 08:00:00 2017" + nsh> date + Dec 25 08:00:01 2017 + + After reset: + + NuttShell (NSH) NuttX-7.23 + nsh> date + Dec 25 08:00:05 2017 + nxwm: This is a special configuration setup for the NxWM window manager diff --git a/configs/lpcxpresso-lpc54628/nsh/defconfig b/configs/lpcxpresso-lpc54628/nsh/defconfig index e3deeddb28..2695a86915 100644 --- a/configs/lpcxpresso-lpc54628/nsh/defconfig +++ b/configs/lpcxpresso-lpc54628/nsh/defconfig @@ -25,6 +25,7 @@ CONFIG_LPC54_EMC_DYNAMIC_CS0=y CONFIG_LPC54_EMC=y CONFIG_LPC54_GPIOIRQ=y CONFIG_LPC54_I2C2_MASTER=y +CONFIG_LPC54_RTC=y CONFIG_LPC54_USART0=y CONFIG_MAX_TASKS=16 CONFIG_MAX_WDOGPARMS=2 @@ -43,6 +44,9 @@ CONFIG_RAM_SIZE=163840 CONFIG_RAM_START=0x10000000 CONFIG_RAW_BINARY=y CONFIG_RR_INTERVAL=200 +CONFIG_RTC_ALARM=y +CONFIG_RTC_DRIVER=y +CONFIG_RTC_IOCTL=y CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y CONFIG_START_DAY=2 diff --git a/configs/lpcxpresso-lpc54628/src/lpc54_bringup.c b/configs/lpcxpresso-lpc54628/src/lpc54_bringup.c index 12d32ce6b8..5b1bf5152b 100644 --- a/configs/lpcxpresso-lpc54628/src/lpc54_bringup.c +++ b/configs/lpcxpresso-lpc54628/src/lpc54_bringup.c @@ -57,6 +57,11 @@ # include "lpc54_sdmmc.h" #endif +#ifdef CONFIG_RTC_DRIVER +# include +# include "lpc54_rtc.h" +#endif + #include "lpcxpresso-lpc54628.h" /**************************************************************************** @@ -81,6 +86,9 @@ int lpc54_bringup(void) { #ifdef HAVE_MMCSD struct sdio_dev_s *sdmmc; +#endif +#ifdef HAVE_RTC_DRIVER + struct rtc_lowerhalf_s *rtc; #endif int ret; @@ -94,8 +102,30 @@ int lpc54_bringup(void) } #endif -FAR struct sdio_dev_s *lpc54_sdmmc_initialize(int slotno); +#ifdef HAVE_RTC_DRIVER + /* Instantiate the STM32 lower-half RTC driver */ + rtc = lpc54_rtc_lowerhalf(); + if (rtc == NULL) + { + syslog(LOG_ERR, + "ERROR: Failed to instantiate the RTC lower-half driver\n"); + } + else + { + /* Bind the lower half driver and register the combined RTC driver + * as /dev/rtc0 + */ + + ret = rtc_initialize(0, rtc); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to bind/register the RTC driver: %d\n", + ret); + } + } +#endif #ifdef HAVE_I2CTOOL /* Register I2C drivers on behalf of the I2C tool */ diff --git a/configs/lpcxpresso-lpc54628/src/lpcxpresso-lpc54628.h b/configs/lpcxpresso-lpc54628/src/lpcxpresso-lpc54628.h index ca44a1608f..b3411c3f7d 100644 --- a/configs/lpcxpresso-lpc54628/src/lpcxpresso-lpc54628.h +++ b/configs/lpcxpresso-lpc54628/src/lpcxpresso-lpc54628.h @@ -49,9 +49,10 @@ * Pre-processor Definitions ****************************************************************************/ -#define HAVE_I2CTOOL 1 -#define HAVE_FT5x06 1 -#define HAVE_MMCSD 1 +#define HAVE_I2CTOOL 1 +#define HAVE_FT5x06 1 +#define HAVE_MMCSD 1 +#define HAVE_RTC_DRIVER 1 /* Do we need to register I2C drivers on behalf of the I2C tool? */ @@ -118,6 +119,12 @@ # undef HAVE_MMCSD #endif +/* Check if we can support the RTC driver */ + +#if !defined(CONFIG_RTC) || !defined(CONFIG_RTC_DRIVER) +# undef HAVE_RTC_DRIVER +#endif + /* Indices into a sparse I2C array. Used with lpc54_i2c_handle() */ #ifdef CONFIG_LPC54_I2C0_MASTER