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:46 UTC

[incubator-nuttx] 02/02: stm32f7: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 1e5754232ae8edf936cee441885de44ca251ee9e
Author: David Sidrane <Da...@NscDg.com>
AuthorDate: Thu Feb 4 06:35:24 2021 -0800

    stm32f7:Add option to auto select LSE CAPABILITY
    
       This Knob will cycle through the 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
---
 arch/arm/src/stm32f7/Kconfig     | 15 +++++++++
 arch/arm/src/stm32f7/stm32_lse.c | 70 +++++++++++++++++++++++++++++++++-------
 2 files changed, 73 insertions(+), 12 deletions(-)

diff --git a/arch/arm/src/stm32f7/Kconfig b/arch/arm/src/stm32f7/Kconfig
index 3af3678..3d5be60 100644
--- a/arch/arm/src/stm32f7/Kconfig
+++ b/arch/arm/src/stm32f7/Kconfig
@@ -2582,10 +2582,24 @@ endchoice #"RTC clock source"
 
 if STM32F7_RTC_LSECLOCK
 
+config STM32F7_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 high drive capability
+			2 = Medium low drive capability
+			3 = High drive capability
+
 config STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY
 	int "LSE oscillator drive capability level at LSE start-up"
 	default 0
 	range 0 3
+	depends on !STM32F7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
 	---help---
 		0 = Low drive capability (default)
 		1 = Medium high drive capability
@@ -2596,6 +2610,7 @@ config STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY
 	int "LSE oscillator drive capability level after LSE start-up"
 	default 0
 	range 0 3
+	depends on !STM32F7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
 	---help---
 		0 = Low drive capability (default)
 		1 = Medium high drive capability
diff --git a/arch/arm/src/stm32f7/stm32_lse.c b/arch/arm/src/stm32f7/stm32_lse.c
index ee5cb95..3ed6a12 100644
--- a/arch/arm/src/stm32f7/stm32_lse.c
+++ b/arch/arm/src/stm32f7/stm32_lse.c
@@ -1,9 +1,9 @@
 /****************************************************************************
  * arch/arm/src/stm32f7/stm32_lse.c
  *
- *   Copyright (C) 2017 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 2017, 2021 Gregory Nutt. All rights reserved.
  *   Authors: Gregory Nutt <gn...@nuttx.org>
- *            David Sidrane <da...@nscdg.com>
+ *            David Sidrane <da...@nscdg.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -49,6 +49,8 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+#define LSERDY_TIMEOUT (500 * CONFIG_BOARD_LOOPSPERMSEC)
+
 #ifdef CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY
 # if CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY < 0 || \
      CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY > 3
@@ -64,6 +66,18 @@
 #endif
 
 /****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const uint32_t drives[4] =
+{
+    RCC_BDCR_LSEDRV_LOW,
+    RCC_BDCR_LSEDRV_MEDLO,
+    RCC_BDCR_LSEDRV_MEDHI,
+    RCC_BDCR_LSEDRV_HIGH
+};
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -77,7 +91,11 @@
 
 void stm32_rcc_enablelse(void)
 {
-  uint32_t regval;
+  uint32_t         regval;
+  volatile int32_t timeout;
+#ifdef CONFIG_STM32F7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+  volatile int32_t drive = 0;
+#endif
 
   /* Check if the External Low-Speed (LSE) oscillator is already running. */
 
@@ -100,27 +118,55 @@ void stm32_rcc_enablelse(void)
       regval |= RCC_BDCR_LSEON;
 
 #ifdef CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY
-      /* Set start-up drive capability for LSE oscillator. */
+      /* Set start-up drive capability for LSE oscillator. With the
+       * enable on.
+       */
 
-      regval &= ~RCC_BDCR_LSEDRV_MASK;
-      regval |= CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY <<
-                RCC_BDCR_LSEDRV_SHIFT;
+      regval &= ~(RCC_BDCR_LSEDRV_MASK);
+      regval |= drives[CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY];
 #endif
 
-      putreg32(regval, STM32_RCC_BDCR);
+#ifdef CONFIG_STM32F7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+      do
+        {
+          regval &= ~(RCC_BDCR_LSEDRV_MASK);
+          regval |= drives[drive++];
+#endif
+
+          putreg32(regval, STM32_RCC_BDCR);
 
-      /* Wait for the LSE clock to be ready */
+          /* Wait for the LSE clock to be ready (or until a timeout elapsed)
+           */
 
-      while (((regval = getreg32(STM32_RCC_BDCR)) & RCC_BDCR_LSERDY) == 0);
+          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_STM32F7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
+          if (timeout != 0)
+            {
+              break;
+            }
+        }
+      while (drive < sizeof(drives) / sizeof(drives[0]));
+#endif
 #if defined(CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY) && \
     CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY != \
     CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY
       /* Set running drive capability for LSE oscillator. */
 
       regval &= ~RCC_BDCR_LSEDRV_MASK;
-      regval |= CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY <<
-                RCC_BDCR_LSEDRV_SHIFT;
+      regval |= drives[CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY];
       putreg32(regval, STM32_RCC_BDCR);
 #endif