You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/03/02 17:35:45 UTC
[incubator-nuttx] 01/02: stm32h7:Add option to auto select LSE
CAPABILITY
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 9fbd7f9dc5649f7e71db3a06fe4b86a464f9b3ae
Author: David Sidrane <Da...@NscDg.com>
AuthorDate: Wed Feb 3 15:23:13 2021 -0800
stm32h7:Add option to auto select LSE CAPABILITY
This Knob will cycle through the correct*
values from low to high. To avoid damaging
the crystal. We want to use the lowest setting
that gets the OSC running. See app note AN2867
*It will take into account the rev of the silicon
and use the correct code points to achive the drive
strength. See Eratta ES0392 Rev 7 2.2.14 LSE oscillator
driving capability selection bits are swapped.
---
arch/arm/src/stm32h7/Kconfig | 34 +++++++++
arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h | 8 +-
arch/arm/src/stm32h7/stm32_lse.c | 97 ++++++++++++++++++++++---
3 files changed, 125 insertions(+), 14 deletions(-)
diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig
index f83ce52..65a4cdd 100644
--- a/arch/arm/src/stm32h7/Kconfig
+++ b/arch/arm/src/stm32h7/Kconfig
@@ -1493,26 +1493,60 @@ endchoice #"RTC clock source"
if STM32H7_RTC_LSECLOCK
+config STM32H7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+ bool "Automaticaly boost the LSE oscillator drive capability level until it starts-up"
+ default n
+ ---help---
+ This will cycle through the correct* values from low to high. To avoid
+ damaging the the crystal. We want to use the lowest setting that gets
+ the OSC running. See app note AN2867
+
+ 0 = Low drive capability (default)
+ 1 = Medium high drive capability
+ 2 = Medium low drive capability
+ 3 = High drive capability
+
+ *It will take into account the rev of the silicon and use
+ the correct code points to achive the drive strength.
+ See Eratta ES0392 Rev 7 2.2.14 LSE oscillator driving capability
+ selection bits are swapped.
+
config STM32H7_RTC_LSECLOCK_START_DRV_CAPABILITY
int "LSE oscillator drive capability level at LSE start-up"
default 0
range 0 3
+ depends on !STM32H7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
---help---
0 = Low drive capability (default)
1 = Medium high drive capability
2 = Medium low drive capability
3 = High drive capability
+ It will take into account the rev of the silicon and use
+ the correct code points tp achive the drive strength.
+ See Eratta ES0392 Rev 7 2.2.14 LSE oscillator driving capability
+ selection bits are swapped.
+
config STM32H7_RTC_LSECLOCK_RUN_DRV_CAPABILITY
int "LSE oscillator drive capability level after LSE start-up"
default 0
range 0 3
+ depends on !STM32H7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
---help---
0 = Low drive capability (default)
1 = Medium high drive capability
2 = Medium low drive capability
3 = High drive capability
+ It will take into account the rev of the silicon and use
+ the correct code points tp achive the drive strength.
+ See Eratta ES0392 Rev 7 2.2.14 LSE oscillator driving capability
+ selection bits are swapped.
+
+ WARNING this RUN setting does not apear to work!
+ it apears that the LSEDRV bits can not be changes once the OSC
+ is running.
+
endif # STM32H7_RTC_LSECLOCK
endmenu # RTC Configuration
diff --git a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h
index 15cdd86..0adfe8b 100644
--- a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h
+++ b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_rcc.h
@@ -1132,10 +1132,12 @@
#define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */
#define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */
#define RCC_BDCR_LSEDRV_SHIFT (3) /* Bits 4:3: LSE oscillator Drive selection */
-#define RCC_BDCR_LSEDRV_MASK (3 << RCC_BDCR_LSEDRV_SHIFT)
+#define RCC_BDCR_LSEDRV_MASK (3 << RCC_BDCR_LSEDRV_SHIFT) /* See errata ES0392 Rev 7. 2.2.14 */
# define RCC_BDCR_LSEDRV_LOW (0 << RCC_BDCR_LSEDRV_SHIFT) /* 00: Low driving capability */
-# define RCC_BDCR_LSEDRV_MEDHI (1 << RCC_BDCR_LSEDRV_SHIFT) /* 01: Medium high driving capability */
-# define RCC_BDCR_LSEDRV_MEDLO (2 << RCC_BDCR_LSEDRV_SHIFT) /* 10: Medium low driving capability */
+# define RCC_BDCR_LSEDRV_MEDHI_Y (1 << RCC_BDCR_LSEDRV_SHIFT) /* 01: Medium high driving capability rev y */
+# define RCC_BDCR_LSEDRV_MEDHI (2 << RCC_BDCR_LSEDRV_SHIFT) /* 10: Medium high driving capability */
+# define RCC_BDCR_LSEDRV_MEDLO_Y (2 << RCC_BDCR_LSEDRV_SHIFT) /* 10: Medium low driving capability rev y */
+# define RCC_BDCR_LSEDRV_MEDLO (1 << RCC_BDCR_LSEDRV_SHIFT) /* 01: Medium low driving capability */
# define RCC_BDCR_LSEDRV_HIGH (3 << RCC_BDCR_LSEDRV_SHIFT) /* 11: High driving capability */
#define RCC_BDCR_LSECSSON (1 << 5) /* Bit 5: LSE clock security system enable */
#define RCC_BDCR_LSECSSD (1 << 6) /* Bit 6: LSE clock security system failure detection */
diff --git a/arch/arm/src/stm32h7/stm32_lse.c b/arch/arm/src/stm32h7/stm32_lse.c
index 6952d35..06f8854 100644
--- a/arch/arm/src/stm32h7/stm32_lse.c
+++ b/arch/arm/src/stm32h7/stm32_lse.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/stm32h7/stm32_lse.c
*
- * Copyright (C) 2017, 2019 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2017, 2019, 2021 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gn...@nuttx.org>
* David Sidrane <da...@nscdg.com>
*
@@ -44,11 +44,14 @@
#include "stm32_rcc.h"
#include "stm32_pwr.h"
+#include "hardware/stm32h7xxx_dbgmcu.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+#define LSERDY_TIMEOUT (500 * CONFIG_BOARD_LOOPSPERMSEC)
+
#ifdef CONFIG_STM32H7_RTC_LSECLOCK_START_DRV_CAPABILITY
# if CONFIG_STM32H7_RTC_LSECLOCK_START_DRV_CAPABILITY < 0 || \
CONFIG_STM32H7_RTC_LSECLOCK_START_DRV_CAPABILITY > 3
@@ -64,6 +67,30 @@
#endif
/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* See errata ES0392 Rev 7. 2.2.14 LSE oscillator driving capability
+ * selection bits are swapped.
+ */
+
+static const uint32_t drives_rev_y[4] =
+{
+ RCC_BDCR_LSEDRV_LOW,
+ RCC_BDCR_LSEDRV_MEDLO_Y,
+ RCC_BDCR_LSEDRV_MEDHI_Y,
+ RCC_BDCR_LSEDRV_HIGH
+};
+
+const uint32_t drives_rev[4] =
+{
+ RCC_BDCR_LSEDRV_LOW,
+ RCC_BDCR_LSEDRV_MEDLO,
+ RCC_BDCR_LSEDRV_MEDHI,
+ RCC_BDCR_LSEDRV_HIGH
+};
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -77,7 +104,12 @@
void stm32_rcc_enablelse(void)
{
- uint32_t regval;
+ uint32_t regval;
+ volatile int32_t timeout;
+#ifdef CONFIG_STM32H7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+ volatile int32_t drive = 0;
+#endif
+ const uint32_t *drives = drives_rev_y;
/* Check if the External Low-Speed (LSE) oscillator is already running. */
@@ -86,6 +118,16 @@ void stm32_rcc_enablelse(void)
if ((regval & (RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) !=
(RCC_BDCR_LSEON | RCC_BDCR_LSERDY))
{
+ /* Check Silicon for LSE oscillator driving capability selection bits
+ * are swapped errata.
+ */
+
+ if ((getreg32(STM32_DEBUGMCU_BASE) & DBGMCU_IDCODE_REVID_MASK) !=
+ STM32_IDCODE_REVID_Y)
+ {
+ drives = drives_rev;
+ }
+
/* The LSE is in the RTC domain and write access is denied to this
* domain after reset, you have to enable write access using DBP bit
* in the PWR CR register before to configuring the LSE.
@@ -100,27 +142,60 @@ void stm32_rcc_enablelse(void)
regval |= RCC_BDCR_LSEON;
#ifdef CONFIG_STM32H7_RTC_LSECLOCK_START_DRV_CAPABILITY
- /* Set start-up drive capability for LSE oscillator. */
+ /* Set start-up drive capability for LSE oscillator. With the
+ * enable off
+ */
- regval &= ~RCC_BDCR_LSEDRV_MASK;
- regval |= CONFIG_STM32H7_RTC_LSECLOCK_START_DRV_CAPABILITY <<
- RCC_BDCR_LSEDRV_SHIFT;
+ regval &= ~(RCC_BDCR_LSEDRV_MASK | RCC_BDCR_LSEON);
+ regval |= drives[CONFIG_STM32H7_RTC_LSECLOCK_START_DRV_CAPABILITY];
+ putreg32(regval, STM32_RCC_BDCR);
+ regval |= RCC_BDCR_LSEON;
#endif
- putreg32(regval, STM32_RCC_BDCR);
+#ifdef CONFIG_STM32H7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+ do
+ {
+ regval &= ~(RCC_BDCR_LSEDRV_MASK | RCC_BDCR_LSEON);
+ regval |= drives[drive++];
+ putreg32(regval, STM32_RCC_BDCR);
+ regval |= RCC_BDCR_LSEON;
+#endif
- /* Wait for the LSE clock to be ready */
+ putreg32(regval, STM32_RCC_BDCR);
- while (((regval = getreg32(STM32_RCC_BDCR)) & RCC_BDCR_LSERDY) == 0);
+ /* Wait for the LSE clock to be ready (or until a timeout elapsed)
+ */
+ for (timeout = LSERDY_TIMEOUT; timeout > 0; timeout--)
+ {
+ /* Check if the LSERDY flag is the set in the BDCR */
+
+ regval = getreg32(STM32_RCC_BDCR);
+
+ if (regval & RCC_BDCR_LSERDY)
+ {
+ /* If so, then break-out with timeout > 0 */
+
+ break;
+ }
+ }
+
+#ifdef CONFIG_STM32H7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+ if (timeout != 0)
+ {
+ break;
+ }
+ }
+ while (drive < sizeof(drives_rev_y) / sizeof(drives_rev_y[0]));
+
+#endif
#if defined(CONFIG_STM32H7_RTC_LSECLOCK_RUN_DRV_CAPABILITY) && \
CONFIG_STM32H7_RTC_LSECLOCK_START_DRV_CAPABILITY != \
CONFIG_STM32H7_RTC_LSECLOCK_RUN_DRV_CAPABILITY
/* Set running drive capability for LSE oscillator. */
regval &= ~RCC_BDCR_LSEDRV_MASK;
- regval |= CONFIG_STM32H7_RTC_LSECLOCK_RUN_DRV_CAPABILITY <<
- RCC_BDCR_LSEDRV_SHIFT;
+ regval |= drives[CONFIG_STM32H7_RTC_LSECLOCK_RUN_DRV_CAPABILITY];
putreg32(regval, STM32_RCC_BDCR);
#endif