This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 2dbfa541508f590e3a3018dcf1a281acdb82873d
Author: Michael Jung <[email protected]>
AuthorDate: Wed Mar 17 20:05:07 2021 +0100

    stm32l5: Optional LSE xtal drive strength ramp-up
    
    Ported from stm32f7/h7: If configured this way, ramp-up the LSE crystal
    oscillator driving strength until the LSE starts up.
    
    Signed-off-by: Michael Jung <[email protected]>
---
 arch/arm/src/stm32l5/Kconfig                       | 19 +++++
 arch/arm/src/stm32l5/stm32l5_lse.c                 | 87 ++++++++++++++++------
 .../stm32l5/nucleo-l552ze/configs/nsh/defconfig    |  2 +
 3 files changed, 86 insertions(+), 22 deletions(-)

diff --git a/arch/arm/src/stm32l5/Kconfig b/arch/arm/src/stm32l5/Kconfig
index 280f53d..741eb97 100644
--- a/arch/arm/src/stm32l5/Kconfig
+++ b/arch/arm/src/stm32l5/Kconfig
@@ -248,6 +248,10 @@ config STM32L5_PWR
        bool "PWR"
        default n
 
+config STM32L5_RTC
+       bool "RTC"
+       default n
+
 config STM32L5_LPUART1
        bool "LPUART1"
        default n
@@ -389,10 +393,24 @@ endchoice
 
 if STM32L5_RTC_LSECLOCK
 
+config STM32L5_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 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 low drive capability
+                       2 = Medium high drive capability
+                       3 = High drive capability
+
 config STM32L5_RTC_LSECLOCK_START_DRV_CAPABILITY
        int "LSE oscillator drive capability level at LSE start-up"
        default 0
        range 0 3
+       depends on !STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
        ---help---
                0 = Low drive capability (default)
                1 = Medium low drive capability
@@ -403,6 +421,7 @@ config STM32L5_RTC_LSECLOCK_RUN_DRV_CAPABILITY
        int "LSE oscillator drive capability level after LSE start-up"
        default 0
        range 0 3
+       depends on !STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
        ---help---
                0 = Low drive capability (default)
                1 = Medium low drive capability
diff --git a/arch/arm/src/stm32l5/stm32l5_lse.c 
b/arch/arm/src/stm32l5/stm32l5_lse.c
index b8f96dc..35ad78e 100644
--- a/arch/arm/src/stm32l5/stm32l5_lse.c
+++ b/arch/arm/src/stm32l5/stm32l5_lse.c
@@ -71,6 +71,20 @@
 #endif
 
 /****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+static const uint32_t drives[4] =
+{
+    RCC_BDCR_LSEDRV_LOW,
+    RCC_BDCR_LSEDRV_MEDLO,
+    RCC_BDCR_LSEDRV_MEDHI,
+    RCC_BDCR_LSEDRV_HIGH
+};
+#endif
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -87,6 +101,9 @@ void stm32l5_rcc_enablelse(void)
   bool writable;
   uint32_t regval;
   volatile int32_t timeout;
+#ifdef CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+  volatile int32_t drive = 0;
+#endif
 
   /* Check if both the External Low-Speed (LSE) oscillator and the LSE system
    * clock are already running.
@@ -113,46 +130,72 @@ void stm32l5_rcc_enablelse(void)
       regval |= RCC_BDCR_LSEON;
 
 #ifdef CONFIG_STM32L5_RTC_LSECLOCK_START_DRV_CAPABILITY
-      /* Set start-up drive capability for LSE oscillator. */
+      /* Set start-up drive capability for LSE oscillator.  LSE must be OFF
+       * to change drive strength.
+       */
 
-      regval &= ~RCC_BDCR_LSEDRV_MASK;
+      regval &= ~(RCC_BDCR_LSEDRV_MASK | RCC_BDCR_LSEON);
       regval |= CONFIG_STM32L5_RTC_LSECLOCK_START_DRV_CAPABILITY <<
                 RCC_BDCR_LSEDRV_SHIFT;
-#endif
-
       putreg32(regval, STM32L5_RCC_BDCR);
+      regval |= RCC_BDCR_LSEON;
+#endif
 
-      /* Wait for the LSE clock to be ready (or until a timeout elapsed)
-       */
-
-      for (timeout = LSERDY_TIMEOUT; timeout > 0; timeout--)
+#ifdef CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+      do
         {
-          /* Check if the LSERDY flag is the set in the BDCR */
+          regval &= ~(RCC_BDCR_LSEDRV_MASK | RCC_BDCR_LSEON);
+          regval |= drives[drive++];
+          putreg32(regval, STM32L5_RCC_BDCR);
+          regval |= RCC_BDCR_LSEON;
+#endif
+
+          putreg32(regval, STM32L5_RCC_BDCR);
 
-          regval = getreg32(STM32L5_RCC_BDCR);
+          /* Wait for the LSE clock to be ready (or until a timeout elapsed)
+           */
 
-          if (regval & RCC_BDCR_LSERDY)
+          for (timeout = LSERDY_TIMEOUT; timeout > 0; timeout--)
             {
-              /* If so, then break-out with timeout > 0 */
+              /* Check if the LSERDY flag is the set in the BDCR */
+
+              regval = getreg32(STM32L5_RCC_BDCR);
+
+              if (regval & RCC_BDCR_LSERDY)
+                {
+                  /* If so, then break-out with timeout > 0 */
 
+                  break;
+                }
+            }
+
+#ifdef CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+          if (timeout != 0)
+            {
               break;
             }
         }
+      while (drive < sizeof(drives) / sizeof(drives[0]));
+#endif
 
-      /* Enable LSE system clock.  The LSE system clock seems to provide a
-       * means to gate the LSE clock distribution to peripherals.  It must be
-       * enabled for MSI PLL mode (syncing the MSI to the LSE).
-       */
+      if (timeout != 0)
+        {
+          /* Enable LSE system clock.  The LSE system clock seems to provide
+           * a means to gate the LSE clock distribution to peripherals.  It
+           * must be enabled for MSI PLL mode (syncing the MSI to the LSE).
+           */
 
-      regval |= RCC_BDCR_LSESYSEN;
+          regval |= RCC_BDCR_LSESYSEN;
 
-      putreg32(regval, STM32L5_RCC_BDCR);
+          putreg32(regval, STM32L5_RCC_BDCR);
 
-      /* Wait for the LSE system clock to be ready */
+          /* Wait for the LSE system clock to be ready */
 
-      while (!((regval = getreg32(STM32L5_RCC_BDCR)) & RCC_BDCR_LSESYSRDY))
-        {
-          up_waste();
+          while (!((regval = getreg32(STM32L5_RCC_BDCR)) &
+                   RCC_BDCR_LSESYSRDY))
+            {
+              up_waste();
+            }
         }
 
 #if defined(CONFIG_STM32L5_RTC_LSECLOCK_RUN_DRV_CAPABILITY) && \
diff --git a/boards/arm/stm32l5/nucleo-l552ze/configs/nsh/defconfig 
b/boards/arm/stm32l5/nucleo-l552ze/configs/nsh/defconfig
index 6cbb531..db231f0 100644
--- a/boards/arm/stm32l5/nucleo-l552ze/configs/nsh/defconfig
+++ b/boards/arm/stm32l5/nucleo-l552ze/configs/nsh/defconfig
@@ -54,6 +54,8 @@ CONFIG_RR_INTERVAL=200
 CONFIG_SCHED_WAITPID=y
 CONFIG_SDCLONE_DISABLE=y
 CONFIG_STACK_COLORATION=y
+CONFIG_STM32L5_RTC=y
+CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY=y
 CONFIG_STM32L5_USART3=y
 CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_STACKMONITOR=y

Reply via email to