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
This commit is contained in:
David Sidrane 2021-02-04 06:35:24 -08:00 committed by Alan Carvalho de Assis
parent 9fbd7f9dc5
commit 1e5754232a
2 changed files with 73 additions and 12 deletions

View file

@ -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

View file

@ -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 <gnutt@nuttx.org>
* David Sidrane <david_s5@nscdg.com>
* David Sidrane <david.sidrane@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
@ -63,6 +65,18 @@
#endif
#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
/* 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_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