STM32 F4 RTC driver is fully coded (but not tested)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4176 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
760626f299
commit
3c4954545e
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
/** \} */
|
||||
|
@ -63,15 +63,27 @@ extern "C" {
|
||||
* Public Functions
|
||||
************************************************************************************/
|
||||
|
||||
/** Disables Write Protection to the Backup Area
|
||||
**/
|
||||
/************************************************************************************
|
||||
* 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 */
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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: stm32_rtc_interrupt
|
||||
* 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: 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;
|
||||
|
||||
/* Configure RTC interrupt to catch alarm interrupts. */
|
||||
/* 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();
|
||||
|
||||
/* 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
|
||||
|
Loading…
Reference in New Issue
Block a user