summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-01-02 06:32:40 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-01-02 06:32:40 -0600
commit1923fed668f74aafc8edcb13cb9cab07e50ba97e (patch)
tree565b5744ccd3e244d34033e91e5bb2c54e20b4fa
parent5b04fbb70e0d4b34d98a43ad0545fe40f4b67a2f (diff)
downloadnuttx-1923fed668f74aafc8edcb13cb9cab07e50ba97e.tar.gz
nuttx-1923fed668f74aafc8edcb13cb9cab07e50ba97e.tar.bz2
nuttx-1923fed668f74aafc8edcb13cb9cab07e50ba97e.zip
stm32-rtc: Add support for the internal low speed clock (LSI)
Some boards do not have the external 32khz oscillator installed, for those boards we must fallback to the crummy to the crummy internal RC clock. Turn on by defining CONFIG_RTC_LSICLOCK. From Kevin Hester <kevinh@geeksville.com> via Lorenz Meier.
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h4
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h4
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_rtcc.c65
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c11
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c15
5 files changed, 84 insertions, 15 deletions
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h
index 6dbb7f1d7..bd8a05318 100644
--- a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h
@@ -176,8 +176,8 @@
# define RCC_CFGR_PPRE2_HCLKd8 (6 << RCC_CFGR_PPRE2_SHIFT) /* 110: HCLK divided by 8 */
# define RCC_CFGR_PPRE2_HCLKd16 (7 << RCC_CFGR_PPRE2_SHIFT) /* 111: HCLK divided by 16 */
#define RCC_CFGR_RTCPRE_SHIFT (16) /* Bits 16-20: APB High speed prescaler (APB2) */
-#define RCC_CFGR_RTCPRE_MASK (31 << RCC_CFGR_RTCPRE)
-# define RCC_CFGR_RTCPRE(n) ((n) << RCC_CFGR_RTCPRE) /* HSE/n, n=1..31 */
+#define RCC_CFGR_RTCPRE_MASK (31 << RCC_CFGR_RTCPRE_SHIFT)
+# define RCC_CFGR_RTCPRE(n) ((n) << RCC_CFGR_RTCPRE_SHIFT) /* HSE/n, n=1..31 */
#define RCC_CFGR_MCO1_SHIFT (21) /* Bits 21-22: Microcontroller Clock Output */
#define RCC_CFGR_MCO1_MASK (3 << RCC_CFGR_MCO1_SHIFT)
# define RCC_CFGR_MCO1_HSI (0 << RCC_CFGR_MCO1_SHIFT) /* 00: HSI clock selected */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h
index 6ec21964f..3b48f7a36 100644
--- a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h
@@ -186,8 +186,8 @@
# define RCC_CFGR_PPRE2_HCLKd8 (6 << RCC_CFGR_PPRE2_SHIFT) /* 110: HCLK divided by 8 */
# define RCC_CFGR_PPRE2_HCLKd16 (7 << RCC_CFGR_PPRE2_SHIFT) /* 111: HCLK divided by 16 */
#define RCC_CFGR_RTCPRE_SHIFT (16) /* Bits 16-20: APB High speed prescaler (APB2) */
-#define RCC_CFGR_RTCPRE_MASK (31 << RCC_CFGR_RTCPRE)
-# define RCC_CFGR_RTCPRE(n) ((n) << RCC_CFGR_RTCPRE) /* HSE/n, n=1..31 */
+#define RCC_CFGR_RTCPRE_MASK (31 << RCC_CFGR_RTCPRE_SHIFT)
+# define RCC_CFGR_RTCPRE(n) ((n) << RCC_CFGR_RTCPRE_SHIFT) /* HSE/n, n=1..31 */
#define RCC_CFGR_MCO1_SHIFT (21) /* Bits 21-22: Microcontroller Clock Output */
#define RCC_CFGR_MCO1_MASK (3 << RCC_CFGR_MCO1_SHIFT)
# define RCC_CFGR_MCO1_HSI (0 << RCC_CFGR_MCO1_SHIFT) /* 00: HSI clock selected */
diff --git a/nuttx/arch/arm/src/stm32/stm32_rtcc.c b/nuttx/arch/arm/src/stm32/stm32_rtcc.c
index 3c5eae20b..817111d58 100644
--- a/nuttx/arch/arm/src/stm32/stm32_rtcc.c
+++ b/nuttx/arch/arm/src/stm32/stm32_rtcc.c
@@ -81,9 +81,7 @@
#define SYNCHRO_TIMEOUT (0x00020000)
#define INITMODE_TIMEOUT (0x00010000)
-#define RTC_MAGIC (0xfacefeed)
-#define RTC_PREDIV_S (0xff)
-#define RTC_PREDIV_A (0x7f)
+#define RTC_MAGIC (0xfacefeee)
/* Debug ****************************************************************************/
@@ -437,12 +435,47 @@ 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.
+ /* We might be changing RTCSEL - to ensure such changes work, we must reset the
+ * backup domain
+ */
+
+ modifyreg32(STM32_RCC_BDCR, 0, RCC_BDCR_BDRST);
+ modifyreg32(STM32_RCC_BDCR, RCC_BDCR_BDRST, 0);
+
+ /* Some boards do not have the external 32khz oscillator installed, for those
+ * boards we must fallback to the crummy internal RC clock or the external high
+ * rate clock
*/
+#ifdef CONFIG_RTC_HSECLOCK
+ /* Use the HSE clock as the input to the RTC block */
+
+ modifyreg32(STM32_RCC_BDCR, RCC_BDCR_RTCSEL_MASK, RCC_BDCR_RTCSEL_HSE);
+
+ /* Enable the RTC Clock by setting the RTCEN bit in the RCC BDCR register */
+
+ modifyreg32(STM32_RCC_BDCR, 0, RCC_BDCR_RTCEN);
+
+#elif defined(CONFIG_RTC_LSICLOCK)
+ /* Enable the LSI clock */
+
+ stm32_rcc_enablelsi();
+
+ /* Use the LSI clock as the input to the RTC block */
+
+ modifyreg32(STM32_RCC_BDCR, RCC_BDCR_RTCSEL_MASK, RCC_BDCR_RTCSEL_LSI);
+
+ /* Enable the RTC Clock by setting the RTCEN bit in the RCC BDCR register */
+
+ modifyreg32(STM32_RCC_BDCR, 0, RCC_BDCR_RTCEN);
+
+#else
+ /* Enable the LSE clock */
+
stm32_rcc_enablelse();
+#endif
+
/* Wait for the RTC Time and Date registers to be synchronized with RTC APB
* clock.
*/
@@ -467,13 +500,23 @@ static int rtc_setup(void)
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:
+ /* Configure RTC pre-scaler with the required values */
+
+#ifdef CONFIG_RTC_HSECLOCK
+ /* For a 1 MHz clock this yields 0.9999360041 Hz on the second
+ * timer - which is pretty close.
*/
+ putreg32(((uint32_t)7182 << RTC_PRER_PREDIV_S_SHIFT) |
+ ((uint32_t)0x7f << RTC_PRER_PREDIV_A_SHIFT),
+ STM32_RTC_PRER);
+#else
+ /* Correct values for 1 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);
+#endif
/* Exit RTC initialization mode */
@@ -580,8 +623,6 @@ int up_rtcinitialize(void)
int maxretry = 10;
int nretry = 0;
- rtc_dumpregs("On reset");
-
/* 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
@@ -593,6 +634,11 @@ int up_rtcinitialize(void)
*/
stm32_pwr_enablebkp();
+ rtc_dumpregs("On reset");
+
+ /* Enable the External Low-Speed (LSE) Oscillator setup the LSE as the RTC clock
+ * source, and enable the RTC.
+ */
/* Loop, attempting to initialize/resume the RTC. This loop is necessary
* because it seems that occasionally it takes longer to initialize the RTC
@@ -626,6 +672,7 @@ int up_rtcinitialize(void)
/* RTC already set-up, just resume normal operation */
ret = rtc_resume();
+ rtc_dumpregs("Did resume");
}
/* Check that setup or resume returned successfully */
diff --git a/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c
index dd796f86c..da65dd7d6 100644
--- a/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c
+++ b/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c
@@ -613,7 +613,16 @@ static void stm32_stdclockconfig(void)
regval |= STM32_RCC_CFGR_PPRE1;
putreg32(regval, STM32_RCC_CFGR);
- /* Set the PLL dividers and multiplers to configure the main PLL */
+#ifdef CONFIG_RTC_HSECLOCK
+ /* Set the RTC clock divisor */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_RTCPRE_MASK;
+ regval |= RCC_CFGR_RTCPRE(HSE_DIVISOR);
+ putreg32(regval, STM32_RCC_CFGR);
+#endif
+
+ /* Set the PLL dividers and multipliers to configure the main PLL */
regval = (STM32_PLLCFG_PLLM | STM32_PLLCFG_PLLN |STM32_PLLCFG_PLLP |
RCC_PLLCFG_PLLSRC_HSE | STM32_PLLCFG_PLLQ);
diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c
index b15b383fc..37e2ad81e 100644
--- a/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c
+++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c
@@ -55,6 +55,10 @@
#define HSIRDY_TIMEOUT HSERDY_TIMEOUT
+/* HSE divisor to yield ~1MHz RTC clock */
+
+#define HSE_DIVISOR (STM32_HSE_FREQUENCY + 500000) / 1000000
+
/****************************************************************************
* Private Data
****************************************************************************/
@@ -684,7 +688,16 @@ static void stm32_stdclockconfig(void)
regval |= STM32_RCC_CFGR_PPRE1;
putreg32(regval, STM32_RCC_CFGR);
- /* Set the PLL dividers and multiplers to configure the main PLL */
+#ifdef CONFIG_RTC_HSECLOCK
+ /* Set the RTC clock divisor */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_RTCPRE_MASK;
+ regval |= RCC_CFGR_RTCPRE(HSE_DIVISOR);
+ putreg32(regval, STM32_RCC_CFGR);
+#endif
+
+ /* Set the PLL dividers and multipliers to configure the main PLL */
#ifdef STM32_BOARD_USEHSI
regval = (STM32_PLLCFG_PLLM | STM32_PLLCFG_PLLN |STM32_PLLCFG_PLLP |