diff options
Diffstat (limited to 'nuttx/arch/arm/src')
-rw-r--r-- | nuttx/arch/arm/src/stm32/chip/stm32_exti.h | 20 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h | 11 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_lse.c | 28 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_pwr.c | 40 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_pwr.h | 20 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_rcc.h | 5 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c | 3 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c | 2 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c | 504 |
9 files changed, 583 insertions, 50 deletions
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_exti.h b/nuttx/arch/arm/src/stm32/chip/stm32_exti.h index d295b6cb8..31b50136d 100644 --- a/nuttx/arch/arm/src/stm32/chip/stm32_exti.h +++ b/nuttx/arch/arm/src/stm32/chip/stm32_exti.h @@ -82,6 +82,26 @@ /* Register Bitfield Definitions ****************************************************/ +/* EXTI lines > 15 are associated with internal devices: */ + +#if defined(CONFIG_STM32_STM32F10XX) +# define EXTI_PVD_LINE (1 << 16) /* EXTI line 16 is connected to the PVD output */ +# define EXTI_RTC_ALARM (1 << 17) /* EXTI line 17 is connected to the RTC Alarm event */ +# define EXTI_USB_WAKEUP (1 << 18) /* EXTI line 18 is connected to the USB Wakeup event */ +# ifdef CONFIG_STM32_CONNECTIVITYLINE +# define EXTI_ETH_WAKEUP (1 << 19) /* EXTI line 19 is connected to the Ethernet Wakeup event */ +# endif +#elif defined(CONFIG_STM32_STM32F40XX) +# define EXTI_PVD_LINE (1 << 16) /* EXTI line 16 is connected to the PVD output */ +# define EXTI_RTC_ALARM (1 << 17) /* EXTI line 17 is connected to the RTC Alarm event */ +# define EXTI_OTGFS_WAKEUP (1 << 18) /* EXTI line 18 is connected to the USB OTG FS Wakeup event */ +# define EXTI_ETH_WAKEUP (1 << 19) /* EXTI line 19 is connected to the Ethernet Wakeup event */ +# define EXTI_OTGHS_WAKEUP (1 << 20) /* EXTI line 20 is connected to the USB OTG HS Wakeup event */ +# define EXTI_RTC_TAMPER (1 << 21) /* EXTI line 21 is connected to the RTC Tamper and TimeStamp events */ +# define EXTI_RTC_TIMESTAMP (1 << 22) /* EXTI line 21 is connected to the RTC Tamper and TimeStamp events */ +# define EXTI_RTC_WAKEUP (1 << 23) /* EXTI line 22 is connected to the RTC Wakeup event +#endif + /* Interrupt mask register */ #define EXTI_IMR_BIT(n) STM32_EXTI_BIT(n) /* 1=Interrupt request from line x is not masked */ diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h index eea94b92f..c12698f7f 100644 --- a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h +++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h @@ -133,7 +133,7 @@ #define RTC_TR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format */ #define RTC_TR_SU_MASK (15 << RTC_TR_SU_SHIFT) #define RTC_TR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format */ -#define RTC_TR_ST_MASK (7 << RTC_TR_ST_SHIFT)* +#define RTC_TR_ST_MASK (7 << RTC_TR_ST_SHIFT) #define RTC_TR_MNU_SHIFT (8) /* Bit 8-11: Minute units in BCD format */ #define RTC_TR_MNU_MASK (15 << RTC_TR_MNU_SHIFT) #define RTC_TR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format */ @@ -143,10 +143,11 @@ #define RTC_TR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format */ #define RTC_TR_HT_MASK (3 << RTC_TR_HT_SHIFT) #define RTC_TR_PM (1 << 22) /* Bit 22: AM/PM notation */ +#define RTC_TR_RESERVED_BITS (0xff808080) /* RTC date register */ -#define RTC_DR_DU_SHIFT (0) /* Bits 0-3]: Date units in BCD format */ +#define RTC_DR_DU_SHIFT (0) /* Bits 0-3: Date units in BCD format */ #define RTC_DR_DU_MASK (15 << RTC_DR_DU_SHIFT) #define RTC_DR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */ #define RTC_DR_DT_MASK (3 << RTC_DR_DT_SHIFT) @@ -166,6 +167,7 @@ #define RTC_DR_YU_MASK (15 << RTC_DR_YU_SHIFT) #define RTC_DR_YT_SHIFT (20) /* Bits 20-23: Year tens in BCD format */ #define RTC_DR_YT_MASK (15 << RTC_DR_YT_SHIFT) +#define RTC_DR_RESERVED_BITS (0xff0000c0) /* RTC control register */ @@ -220,13 +222,14 @@ #define RTC_ISR_TSOVF (1 << 12) /* Bit 12: Timestamp overflow flag */ #define RTC_ISR_TAMP1F (1 << 13) /* Bit 13: Tamper detection flag */ #define RTC_ISR_TAMP2F (1 << 14) /* Bit 14: TAMPER2 detection flag */ -#define RTC_ISR_RECALPF (1 << 15) /* Bit 16: Recalibration pending Flag */ +#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending Flag */ +#define RTC_ISR_ALLFLAGS (0x00017fff) /* RTC prescaler register */ #define RTC_PRER_PREDIV_S_SHIFT (0) /* Bits 0-14: Synchronous prescaler factor */ #define RTC_PRER_PREDIV_S_MASK (0x7fff << RTC_PRER_PREDIV_S_SHIFT) -#define RTC_PRER_PREDIV_A_SHIFT (22) /* Bits 16-22: Asynchronous prescaler factor */ +#define RTC_PRER_PREDIV_A_SHIFT (16) /* Bits 16-22: Asynchronous prescaler factor */ #define RTC_PRER_PREDIV_A_MASK (0x7f << RTC_PRER_PREDIV_A_SHIFT) /* RTC wakeup timer register */ diff --git a/nuttx/arch/arm/src/stm32/stm32_lse.c b/nuttx/arch/arm/src/stm32/stm32_lse.c index bf9d6d6f2..931199efd 100644 --- a/nuttx/arch/arm/src/stm32/stm32_lse.c +++ b/nuttx/arch/arm/src/stm32/stm32_lse.c @@ -2,7 +2,7 @@ * arch/arm/src/stm32/stm32_lse.c * * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Author: Gregory Nutt <gnutt@nuttx.orgr> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -63,31 +63,43 @@ /**************************************************************************** * Name: stm32_rcc_enablelse * + * Description: + * Enable the External Low-Speed (LSE) Oscillator and, if the RTC is + * configured, setup the LSE as the RTC clock source, and enable the RTC. + * * Todo: * Check for LSE good timeout and return with -1, - * possible ISR optimization? or at least ISR should be cough in case of\ - * failure * ****************************************************************************/ void stm32_rcc_enablelse(void) { - /* Enable LSE */ + /* Enable the External Low-Speed (LSE) Oscillator by setting the LSEON bit + * the RCC BDCR register. + */ modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_LSEON); - /* We could wait for ISR here ... */ + /* Wait for the LSE clock to be ready */ while ((getreg16(STM32_RCC_BDCR) & RCC_BDCR_LSERDY) == 0) { up_waste(); } - /* Select LSE as RTC Clock Source */ + /* The primariy purpose of the LSE clock is to drive the RTC. The RTC could + * also be driven by the LSI (but that would be very inaccurate) or by the + * HSE (but that would prohibit low-power operation) + * + * Select LSE as RTC Clock Source by setting the RTCSEL field of the RCC BDCR + * register. + */ +#ifdef CONFIG_RTC modifyreg16(STM32_RCC_BDCR, RCC_BDCR_RTCSEL_MASK, RCC_BDCR_RTCSEL_LSE); - - /* Enable Clock */ + + /* Enable the RTC Clock by setting the RTCEN bit in the RCC BDCR register */ modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_RTCEN); +#endif } diff --git a/nuttx/arch/arm/src/stm32/stm32_pwr.c b/nuttx/arch/arm/src/stm32/stm32_pwr.c index 861d32b64..6a4e62d66 100644 --- a/nuttx/arch/arm/src/stm32/stm32_pwr.c +++ b/nuttx/arch/arm/src/stm32/stm32_pwr.c @@ -33,13 +33,9 @@ * ************************************************************************************/ -/** \file - * \author Uros Platise - * \brief STM32 Power - * - * \addtogroup STM32_PWR - * \{ - */ +/************************************************************************************ + * Included Files + ************************************************************************************/ #include <nuttx/config.h> #include <nuttx/arch.h> @@ -50,7 +46,6 @@ #include "up_arch.h" #include "stm32_pwr.h" - #if defined(CONFIG_STM32_PWR) /************************************************************************************ @@ -59,32 +54,41 @@ static inline uint16_t stm32_pwr_getreg(uint8_t offset) { - return getreg32(STM32_PWR_BASE + offset); + return getreg32(STM32_PWR_BASE + offset); } - static inline void stm32_pwr_putreg(uint8_t offset, uint16_t value) { - putreg32(value, STM32_PWR_BASE + offset); + putreg32(value, STM32_PWR_BASE + offset); } - static inline void stm32_pwr_modifyreg(uint8_t offset, uint16_t clearbits, uint16_t setbits) { - modifyreg32(STM32_PWR_BASE + offset, clearbits, setbits); + modifyreg32(STM32_PWR_BASE + offset, clearbits, setbits); } - +/************************************************************************************ + * Public Functions + ************************************************************************************/ /************************************************************************************ - * Public Function - Initialization + * Name: stm32_pwr_enablebkp + * + * Description: + * Enables access to the backup domain (RTC registers, RTC backup data registers + * and backup SRAM). + * + * Input Parameters: + * None + * + * Returned Values: + * None + * ************************************************************************************/ void stm32_pwr_enablebkp(void) { - stm32_pwr_modifyreg(STM32_PWR_CR_OFFSET, 0, PWR_CR_DBP); + stm32_pwr_modifyreg(STM32_PWR_CR_OFFSET, 0, PWR_CR_DBP); } - #endif // defined(CONFIG_STM32_PWR) -/** \} */ diff --git a/nuttx/arch/arm/src/stm32/stm32_pwr.h b/nuttx/arch/arm/src/stm32/stm32_pwr.h index 638d23640..56aee49b6 100644 --- a/nuttx/arch/arm/src/stm32/stm32_pwr.h +++ b/nuttx/arch/arm/src/stm32/stm32_pwr.h @@ -63,15 +63,27 @@ extern "C" { * Public Functions ************************************************************************************/ -/** Disables Write Protection to the Backup Area - **/ -EXTERN void stm32_pwr_enablebkp(void); +/************************************************************************************ + * Name: stm32_pwr_enablebkp + * + * Description: + * Enables access to the backup domain (RTC registers, RTC backup data registers + * and backup SRAM). + * + * Input Parameters: + * None + * + * Returned Values: + * None + * + ************************************************************************************/ +EXTERN void stm32_pwr_enablebkp(void); -/** \} */ #undef EXTERN #if defined(__cplusplus) } #endif + #endif /* __ASSEMBLY__ */ #endif /* __ARCH_ARM_SRC_STM32_STM32_PWR_H */ diff --git a/nuttx/arch/arm/src/stm32/stm32_rcc.h b/nuttx/arch/arm/src/stm32/stm32_rcc.h index b4a1500b7..1e05f9ecb 100644 --- a/nuttx/arch/arm/src/stm32/stm32_rcc.h +++ b/nuttx/arch/arm/src/stm32/stm32_rcc.h @@ -2,7 +2,7 @@ * arch/arm/src/stm32/stm32_rcc.h * * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Author: Gregory Nutt <gnutt@nuttx.orgr> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -170,7 +170,8 @@ EXTERN void stm32_clockconfig(void); * Name: stm32_rcc_enablelse * * Description: - * Enable LSE Clock + * Enable the External Low-Speed (LSE) Oscillator and, if the RTC is + * configured, setup the LSE as the RTC clock source, and enable the RTC. * * Input Parameters: * None diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c index 659039bf0..a0e616f04 100644 --- a/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c +++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c @@ -354,7 +354,8 @@ static int stm32_rtc_interrupt(int irq, void *context) int up_rtcinitialize(void) { /* Set access to the peripheral, enable the backup domain (BKP) and the lower power - * extern 32,768Hz (Low-Speed External, LSE) oscillator. + * extern 32,768Hz (Low-Speed External, LSE) oscillator. Configure the LSE to + * drive the RTC. */ stm32_pwr_enablebkp(); diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c index 91f362059..e06a84d65 100644 --- a/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c +++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c @@ -426,7 +426,7 @@ static inline void rcc_enableapb1(void) #endif /* Power interface clock enable. The PWR block is always enabled so that - * we can set the internal voltage regulator for maximum performanc. + * we can set the internal voltage regulator for maximum performance. */ regval |= RCC_APB1ENR_PWREN; diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c index c9d23d471..e249dc27b 100644 --- a/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c +++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c @@ -65,6 +65,14 @@ # error "CONFIG_RTC_HIRES must NOT be set with this driver" #endif +/* Constants ************************************************************************/ + +#define SYNCHRO_TIMEOUT (0x00020000) +#define INITMODE_TIMEOUT (0x00010000) +#define RTC_MAGIC (0xfacefeed) +#define RTC_PREDIV_S (0xff) +#define RTC_PREDIV_A (0x7f) + /************************************************************************************ * Private Types ************************************************************************************/ @@ -90,9 +98,338 @@ volatile bool g_rtc_enabled = false; /************************************************************************************ * Private Functions ************************************************************************************/ +/************************************************************************************ + * Name: rtc_wprunlock + * + * Description: + * Disable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void rtc_wprunlock(void) +{ + /* The following steps are required to unlock the write protection on all the + * RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR). + * + * 1. Write 0xCA into the RTC_WPR register. + * 2. Write 0x53 into the RTC_WPR register. + * + * Writing a wrong key reactivates the write protection. + */ + + putreg32(0xca, STM32_RTC_WPR); + putreg32(0x53, STM32_RTC_WPR); +} + +/************************************************************************************ + * Name: rtc_wprunlock + * + * Description: + * Enable RTC write protection + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void rtc_wprlock(void) +{ + /* Writing any wrong key reactivates the write protection. */ + + putreg32(0xff, STM32_RTC_WPR); +} + +/************************************************************************************ + * Name: rtc_synchwait + * + * Description: + * Waits until the RTC Time and Date registers (RTC_TR and RTC_DR) are + * synchronized with RTC APB clock. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_synchwait(void) +{ + volatile uint32_t timeout; + uint32_t regval; + int ret; + + /* Disable the write protection for RTC registers */ + + rtc_wprunlock(); + + /* Clear Registers synchronization flag (RSF) */ + + regval = getreg32(STM32_RTC_ISR); + regval &= ~RTC_ISR_RSF; + putreg32(regval, STM32_RTC_ISR); + + /* Now wait the registers to become synchronised */ + + ret = -ETIMEDOUT; + for (timeout = 0; timeout < SYNCHRO_TIMEOUT; timeout++) + { + regval = getreg32(STM32_RTC_ISR); + if ((regval & RTC_ISR_RSF) != 0) + { + /* Synchronized */ + + ret = OK; + break; + } + } + + /* Re-enable the write protection for RTC registers */ + + rtc_wprlock(); + return ret; +} + +/************************************************************************************ + * Name: rtc_enterinit + * + * Description: + * Enter RTC initialization mode. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_enterinit(void) +{ + volatile uint32_t timeout; + uint32_t regval; + int ret; + + /* Check if the Initialization mode is already set */ + + regval = getreg32(STM32_RTC_ISR); + + ret = OK; + if ((regval & RTC_ISR_INITF) == 0) + { + /* Set the Initialization mode */ + + putreg32(RTC_ISR_INIT, STM32_RTC_ISR); + + /* Wait until the RTC is in the INIT state (or a timeout occurs) */ + + ret = -ETIMEDOUT; + for (timeout = 0; timeout < INITMODE_TIMEOUT; timeout++) + { + regval = getreg32(STM32_RTC_ISR); + if ((regval & RTC_ISR_INITF) != 0) + { + ret = OK; + break; + } + } + + return ret; +} + +/************************************************************************************ + * Name: rtc_exitinit + * + * Description: + * Exit RTC initialization mode. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static void rtc_exitinit(void) +{ + uint32_t regval; + + regval = getreg32(STM32_RTC_ISR); + regval &= ~(RTC_ISR_INIT); + putreg32(regval, STM32_RTC_ISR); +} + +/************************************************************************************ + * Name: rtc_bin2bcd + * + * Description: + * Converts a 2 digit binary to BCD format + * + * Input Parameters: + * value - The byte to be converted. + * + * Returned Value: + * The value in BCD representation + * + ************************************************************************************/ + +static uint32_t rtc_bin2bcd(int value) +{ + uint32_t msbcd = 0; + + while (value >= 10) + { + msbcd++; + value -= 10; + } + + return (msbcd << 4) | value; +} + +/************************************************************************************ + * Name: rtc_bin2bcd + * + * Description: + * Convert from 2 digit BCD to binary. + * + * Input Parameters: + * value - The BCD value to be converted. + * + * Returned Value: + * The value in binary representation + * + ************************************************************************************/ + +static int rtc_bcd2bin(uint32_t value) +{ + uint32_t tens = (value >> 4) * 10; + return (int)(tens + (value & 0x0f)); +} /************************************************************************************ - * Name: stm32_rtc_interrupt + * Name: rtc_setup + * + * Description: + * Performs first time configuration of the RTC. A special value written into + * back-up register 0 will prevent this function from being called on sub-sequent + * resets or power up. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_setup(void) +{ + uint32_t regval; + int ret; + + /* Enable the External Low-Speed (LSE) Oscillator setup the LSE as the RTC clock\ + * source, and enable the RTC. + */ + + stm32_rcc_enablelse(); + + /* Wait for the RTC Time and Date registers to be synchronized with RTC APB + * clock. + */ + + ret = rtc_synchwait(); + if (ret == OK) + { + /* Disable the write protection for RTC registers */ + + rtc_wprunlock(); + + /* Set Initialization mode */ + + ret = rtc_enterinit() + if (ret == OK) + { + /* Set the 24 hour format by clearing the FMT bit in the RTC + * control register + */ + + regval = getreg32(STM32_RTC_CR); + regval &= ~RTC_CR_FMT + putreg32(regval, STM32_RTC_CR); + + /* Configure RTC pre-scaler to the required, default values for + * use with the 32.768 KHz LSE clock: + */ + + putreg32(((uint32_t)0xff << RTC_PRER_PREDIV_S_SHIFT) | + ((uint32_t)0x7f << RTC_PRER_PREDIV_A_SHIFT), + STM32_RTC_PRER); + + /* Exit RTC initialization mode */ + + rtc_exitinit(); + } + + /* Re-enable the write protection for RTC registers */ + + rtc_wprlock(); + } + return ret; +} + +/************************************************************************************ + * Name: rtc_resume + * + * Description: + * Called when the RTC was already initialized on a previous power cycle. This + * just brings the RTC back into full operation. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +static int rtc_resume(void) +{ + uint32_t regval; + int ret; + + /* Wait for the RTC Time and Date registers to be syncrhonized with RTC APB + * clock. + */ + + ret = rtc_synchwait(); + + /* Clear the RTC alarm flags */ + +#ifdef CONFIG_RTC_ALARM + regval = getreg32(STM32_RTC_ISR); + regval &= ~(RTC_ISR_ALRAF|RTC_ISR_ALRBF); + putreg32(regval, STM32_RTC_ISR); + + /* Clear the EXTI Line 17 Pending bit (Connected internally to RTC Alarm) */ + + putreg32((1 << 17), STM32_EXTI_PR); +#endif + return ret; +} + +/************************************************************************************ + * Name: rtc_interrupt * * Description: * RTC interrupt service routine @@ -107,7 +444,7 @@ volatile bool g_rtc_enabled = false; ************************************************************************************/ #if CONFIG_RTC_ALARM -static int stm32_rtc_interrupt(int irq, void *context) +static int rtc_interrupt(int irq, void *context) { #warning "Missing logic" return OK; @@ -135,13 +472,55 @@ static int stm32_rtc_interrupt(int irq, void *context) int up_rtcinitialize(void) { - /* Initialize the RTC */ -#warning "Missing logic" + uint32_t regval; + + /* Clocking for the PWR block must be provided. However, this is done + * unconditionally in stm32f40xxx_rcc.c on power up. This done unconditionally + * because the PWR block is also needed to set the internal voltage regulator for + * maximum performance. + */ + + /* Enable access to the backup domain (RTC registers, RTC backup data registers + * and backup SRAM). + */ + + stm32_pwr_enablebkp(); - /* Configure RTC interrupt to catch alarm interrupts. */ + /* Check if the one-time initialization of the RTC has already been performed. + * We can determine this by checking if the magic number has been writing to + * to back-up date register DR0. + */ + + regval = getreg32(STM32_RTC_BK0R); + if (regval != RTC_MAGIC) + { + /* Perform the one-time setup of the LSE clocking to the RTC */ + + ret = rtc_setup(); + } + else + { + /* RTC already set-up, just resume normal operation */ + + ret = rtc_resume(); + } + + /* Configure RTC interrupt to catch alarm interrupts. All RTC interrupts are + * connected to the EXTI controller. To enable the RTC Alarm interrupt, the + * following sequence is required: + * + * 1. Configure and enable the EXTI Line 17 in interrupt mode and select the + * rising edge sensitivity. + * 2. Configure and enable the RTC_Alarm IRQ channel in the NVIC. + * 3. Configure the RTC to generate RTC alarms (Alarm A or Alarm B). + */ #ifdef CONFIG_RTC_ALARM - irq_attach(STM32_IRQ_RTC, stm32_rtc_interrupt); +# warning "Missing logic" + + /* Then attach the ALARM interrupt handler */ + + irq_attach(STM32_IRQ_RTC, rtc_interrupt); up_enable_irq(STM32_IRQ_RTC); #endif @@ -174,7 +553,54 @@ int up_rtcinitialize(void) int up_rtc_getdatetime(FAR const struct tm *tp) { -#warning "Missing logic" + uint32_t dr; + uint32_t tr; + uint32_t tmp; + + /* Sample the data time registers. There is a race condition here... If we sample + * the time just before midnight on December 31, the date could be wrong because + * the day rolled over while were sampling. + */ + + do + { + dr = getreg32(STM32_RTC_DR); + tr = getreg32(STM32_RTC_TR); + tmp = getreg32(STM32_RTC_DR); + } + while (tmp != dr); + + /* Convert the RTC time to fields in struct tm format. All of the STM32 + * All of the ranges of values correspond between struct tm and the time + * register. + */ + + tmp = (uint8_t)(tr & (RTC_TR_SU_MASK|RTC_TR_ST_MASK)) >> RTC_TR_SU_SHIFT; + tp->tm_sec = rtc_bcd2bin(tmp); + + tmp = (tr & RTC_TR_MNU_MASK|RTC_TR_MNT_MASK) >> RTC_TR_MNU_SHIFT; + tp->tm_min = rtc_bcd2bin(tmp); + + tmp = (tr & RTC_TR_HU_MASK|RTC_TR_HT_MASK) >> RTC_TR_HU_SHIFT; + tp->tm_hour = rtc_bcd2bin(tmp); + + /* Now convert the RTC date to fields in struct tm format: + * Days: 1-31 match in both cases. + * Month: STM32 is 1-12, struct tm is 0-11. + * Years: STM32 is 00-99, struct tm is years since 1900. + * + * Issue: I am not sure what the STM32 years mean. Are these the + * years 2000-2099? I'll assume so. + */ + + tmp = (dr & RTC_DR_DU_MASK|RTC_DR_DT_MASK) >> RTC_DR_DU_SHIFT; + tp->tm_mday = rtc_bcd2bin(tmp); + + tmp = (dr & RTC_DR_MU_MASK|RTC_DR_MT) >> RTC_DR_MU_SHIFT; + tp->tm_mon = rtc_bcd2bin(tmp) - 1; + + tmp = (dr & RTC_DR_YU_MASK|RTC_DR_YT_MASK) >> RTC_DR_YU_SHIFT; /* Year units, BCD 0-99 */ + tp->tm_year = rtc_bcd2bin(tmp) + 100; return OK; } @@ -195,20 +621,74 @@ int up_rtc_getdatetime(FAR const struct tm *tp) int up_rtc_settime(FAR const struct timespec *tp) { - /* Break out the time values */ -#warning "Missing logic" + FAR struct tm newtime; + uint32_t tr; + uint32_t dr; + int ret; + + /* Break out the time values (not that the time is set only to units of seconds) */ + + (void)gmtime_r(&tp->tv_sec, &newtime); /* Then write the broken out values to the RTC */ -#warning "Missing logic" - return OK; + /* Convert the struct tm format to RTC time register fields. All of the STM32 + * All of the ranges of values correspond between struct tm and the time + * register. + */ + + tr = (rtc_bin2bcd(tp->tm_sec) << RTC_TR_SU_SHIFT) | + (rtc_bin2bcd(tp->tm_min) << RTC_TR_MNU_SHIFT) | + (rtc_bin2bcd(tp->tm_hour) << RTC_TR_HU_SHIFT); + tr &= ~RTC_TR_RESERVED_BITS; + + /* Now convert the fields in struct tm format to the RTC date register fields: + * Days: 1-31 match in both cases. + * Month: STM32 is 1-12, struct tm is 0-11. + * Years: STM32 is 00-99, struct tm is years since 1900. + * + * Issue: I am not sure what the STM32 years mean. Are these the + * years 2000-2099? I'll assume so. + */ + + dr = (rtc_bin2bcd(tp->tm_mday) << RTC_DR_DU_SHIFT) | + ((rtc_bin2bcd(tp->tm_mon) + 1) << RTC_DR_MU_SHIFT) | + ((rtc_bin2bcd(tp->tm_year) - 100) << RTC_DR_YU_SHIFT); + dr &= ~RTC_DR_RESERVED_BITS; + + /* Disable the write protection for RTC registers */ + + rtc_wprunlock(); + + /* Set Initialization mode */ + + ret = rtc_enterinit() + if (ret == OK) + { + /* Set the RTC TR and DR registers */ + + putreg32(tr, STM32_RTC_TR); + putreg32(dr, STM32_RTC_DR); + + /* Exit Initialization mode and wait for the RTC Time and Date + * registers to be synchronized with RTC APB clock. + */ + + rtc_enterinit() + ret = rtc_synchwait(); + } + + /* Re-enable the write protection for RTC registers */ + + rtc_wprlock(); + return ret; } /************************************************************************************ * Name: up_rtc_setalarm * * Description: - * Set up an alarm. + * Set up an alarm. Up to two alarms can be supported (ALARM A and ALARM B). * * Input Parameters: * tp - the time to set the alarm |