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.
This commit is contained in:
parent
9d370fc363
commit
9fbd7f9dc5
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 <gnutt@nuttx.org>
|
||||
* David Sidrane <david.sidrane@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
|
||||
@ -63,6 +66,30 @@
|
||||
#endif
|
||||
#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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user