This is an automated email from the ASF dual-hosted git repository. pkarashchenko pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit e3926ecb16a5a777315782bab362fa0cab0dda55 Author: Michael Jung <[email protected]> AuthorDate: Sun Apr 3 11:55:00 2022 +0200 stm32u5: stm32_stdclockconfig fixes Fix stm32_stdclockconfig for stm32u585xx to the extend that the B-U585I-IOT02A board's clock tree can be configured. This board uses the MSIS as PLL1's input clock and the LSE to autotrim the MSIS. --- arch/arm/src/stm32u5/hardware/stm32u585xx_rcc.h | 49 ++++ arch/arm/src/stm32u5/stm32u585xx_rcc.c | 293 ++++++++---------------- 2 files changed, 142 insertions(+), 200 deletions(-) diff --git a/arch/arm/src/stm32u5/hardware/stm32u585xx_rcc.h b/arch/arm/src/stm32u5/hardware/stm32u585xx_rcc.h index 7f7c200ad1..d299821624 100644 --- a/arch/arm/src/stm32u5/hardware/stm32u585xx_rcc.h +++ b/arch/arm/src/stm32u5/hardware/stm32u585xx_rcc.h @@ -278,6 +278,55 @@ # define RCC_CFGR1_MCOPRE_DIV8 (3 << RCC_CFGR1_MCOPRE_SHIFT) /* 011: division by 8 */ # define RCC_CFGR1_MCOPRE_DIV16 (4 << RCC_CFGR1_MCOPRE_SHIFT) /* 100: division by 16 */ +/* RCC clock configuration register 2 */ + +#define RCC_CFGR2_HPRE_SHIFT (0) /* Bits 0-3: AHB prescaler */ +#define RCC_CFGR2_HPRE_MASK (0xf << RCC_CFGR2_HPRE_SHIFT) +# define RCC_CFGR2_HPRE_SYSCLK ( 0 << RCC_CFGR2_HPRE_SHIFT) /* 0xxx: SYSCLK not divided */ +# define RCC_CFGR2_HPRE_SYSCLK_DIV2 ( 8 << RCC_CFGR2_HPRE_SHIFT) /* 1000: SYSCLK divided by 2 */ +# define RCC_CFGR2_HPRE_SYSCLK_DIV4 ( 9 << RCC_CFGR2_HPRE_SHIFT) /* 1001: SYSCLK divided by 4 */ +# define RCC_CFGR2_HPRE_SYSCLK_DIV8 (10 << RCC_CFGR2_HPRE_SHIFT) /* 1010: SYSCLK divided by 8 */ +# define RCC_CFGR2_HPRE_SYSCLK_DIV16 (11 << RCC_CFGR2_HPRE_SHIFT) /* 1011: SYSCLK divided by 16 */ +# define RCC_CFGR2_HPRE_SYSCLK_DIV64 (12 << RCC_CFGR2_HPRE_SHIFT) /* 1100: SYSCLK divided by 64 */ +# define RCC_CFGR2_HPRE_SYSCLK_DIV128 (13 << RCC_CFGR2_HPRE_SHIFT) /* 1101: SYSCLK divided by 128 */ +# define RCC_CFGR2_HPRE_SYSCLK_DIV256 (14 << RCC_CFGR2_HPRE_SHIFT) /* 1110: SYSCLK divided by 256 */ +# define RCC_CFGR2_HPRE_SYSCLK_DIV512 (15 << RCC_CFGR2_HPRE_SHIFT) /* 1111: SYSCLK divided by 512 */ + +#define RCC_CFGR2_PPRE1_SHIFT (4) /* Bits 4-6: APB1 prescaler */ +#define RCC_CFGR2_PPRE1_MASK (0x7 << RCC_CFGR2_HPRE_SHIFT) +# define RCC_CFGR2_PPRE1_HCLK (0 << RCC_CFGR2_HPRE_SHIFT) /* 0xxx: HCLK not divided */ +# define RCC_CFGR2_PPRE1_HCLK_DIV2 (4 << RCC_CFGR2_HPRE_SHIFT) /* 1000: HCLK divided by 2 */ +# define RCC_CFGR2_PPRE1_HCLK_DIV4 (5 << RCC_CFGR2_HPRE_SHIFT) /* 1001: HCLK divided by 4 */ +# define RCC_CFGR2_PPRE1_HCLK_DIV8 (6 << RCC_CFGR2_HPRE_SHIFT) /* 1010: HCLK divided by 8 */ +# define RCC_CFGR2_PPRE1_HCLK_DIV16 (7 << RCC_CFGR2_HPRE_SHIFT) /* 1011: HCLK divided by 16 */ + +#define RCC_CFGR2_PPRE2_SHIFT (8) /* Bits 8-10: APB2 prescaler */ +#define RCC_CFGR2_PPRE2_MASK (0x7 << RCC_CFGR2_PPRE2_SHIFT) +# define RCC_CFGR2_PPRE2_HCLK (0 << RCC_CFGR2_PPRE2_SHIFT) /* 0xxx: HCLK not divided */ +# define RCC_CFGR2_PPRE2_HCLK_DIV2 (4 << RCC_CFGR2_PPRE2_SHIFT) /* 1000: HCLK divided by 2 */ +# define RCC_CFGR2_PPRE2_HCLK_DIV4 (5 << RCC_CFGR2_PPRE2_SHIFT) /* 1001: HCLK divided by 4 */ +# define RCC_CFGR2_PPRE2_HCLK_DIV8 (6 << RCC_CFGR2_PPRE2_SHIFT) /* 1010: HCLK divided by 8 */ +# define RCC_CFGR2_PPRE2_HCLK_DIV16 (7 << RCC_CFGR2_PPRE2_SHIFT) /* 1011: HCLK divided by 16 */ + +#define RCC_CFGR2_AHB1DIS (1 << 16) /* Bit 16: AHB1 clock disable */ +#define RCC_CFGR2_AHB2DIS1 (1 << 17) /* Bit 17: AHB2_1 clock disable */ +#define RCC_CFGR2_AHB2DIS2 (1 << 18) /* Bit 18: AHB2_2 clock disable */ +#define RCC_CFGR2_APB1DIS (1 << 19) /* Bit 19: APB1 clock disable */ +#define RCC_CFGR2_APB2DIS (1 << 20) /* Bit 20: APB2 clock disable */ + +/* RCC clock configuration register 3 */ + +#define RCC_CFGR3_PPRE3_SHIFT (4) /* Bits 4-6: APB3 prescaler */ +#define RCC_CFGR3_PPRE3_MASK (0x7 << RCC_CFGR3_PPRE3_SHIFT) +# define RCC_CFGR3_PPRE3_HCLK (0 << RCC_CFGR3_PPRE3_SHIFT) /* 0xxx: HCLK not divided */ +# define RCC_CFGR3_PPRE3_HCLK_DIV2 (4 << RCC_CFGR3_PPRE3_SHIFT) /* 1000: HCLK divided by 2 */ +# define RCC_CFGR3_PPRE3_HCLK_DIV4 (5 << RCC_CFGR3_PPRE3_SHIFT) /* 1001: HCLK divided by 4 */ +# define RCC_CFGR3_PPRE3_HCLK_DIV8 (6 << RCC_CFGR3_PPRE3_SHIFT) /* 1010: HCLK divided by 8 */ +# define RCC_CFGR3_PPRE3_HCLK_DIV16 (7 << RCC_CFGR3_PPRE3_SHIFT) /* 1011: HCLK divided by 16 */ + +#define RCC_CFGR3_AHB3DIS (1 << 16) /* Bit 16: AHB3 clock disable */ +#define RCC_CFGR3_APB3DIS (1 << 17) /* Bit 17: APB3 clock disable */ + /* RCC PLL1 configuration register */ #define RCC_PLL1CFGR_PLL1SRC_SHIFT (0) /* Bits 0-1: PLL1 entry clock source */ diff --git a/arch/arm/src/stm32u5/stm32u585xx_rcc.c b/arch/arm/src/stm32u5/stm32u585xx_rcc.c index 68a25ceec2..ea988b07e0 100644 --- a/arch/arm/src/stm32u5/stm32u585xx_rcc.c +++ b/arch/arm/src/stm32u5/stm32u585xx_rcc.c @@ -45,7 +45,7 @@ /* Same for HSI and MSI */ #define HSIRDY_TIMEOUT HSERDY_TIMEOUT -#define MSIRDY_TIMEOUT HSERDY_TIMEOUT +#define MSISRDY_TIMEOUT HSERDY_TIMEOUT /* HSE divisor to yield ~1MHz RTC clock */ @@ -595,42 +595,15 @@ void stm32_stdclockconfig(void) uint32_t regval; volatile int32_t timeout; - /* Enable Internal Multi-Speed System (MSIS) and Kernel (MSIK) Clock */ +#if defined(STM32_BOARD_USEMSIS) + /* Enable Internal Multi-Speed Clock (MSIS) */ -#if defined(STM32_BOARD_USEHSI) || defined(STM32_I2C_USE_HSI16) - /* Enable Internal High-Speed Clock (HSI) */ + /* Wait until the MSIS is either off or ready (or until timeout elapses) */ - regval = getreg32(STM32_RCC_CR); - regval |= RCC_CR_HSION; /* Enable HSI */ - putreg32(regval, STM32_RCC_CR); - - /* Wait until the HSI is ready (or until a timeout elapsed) */ - - for (timeout = HSIRDY_TIMEOUT; timeout > 0; timeout--) - { - /* Check if the HSIRDY flag is the set in the CR */ - - if ((getreg32(STM32_RCC_CR) & RCC_CR_HSIRDY) != 0) - { - /* If so, then break-out with timeout > 0 */ - - break; - } - } -#endif - -#if defined(STM32_BOARD_USEHSI) - /* Already set above */ - -#elif defined(STM32_BOARD_USEMSI) - /* Enable Internal Multi-Speed Clock (MSI) */ - - /* Wait until the MSI is either off or ready (or until a timeout elapsed) */ - - for (timeout = MSIRDY_TIMEOUT; timeout > 0; timeout--) + for (timeout = MSISRDY_TIMEOUT; timeout > 0; timeout--) { if ((regval = getreg32(STM32_RCC_CR)), - (regval & RCC_CR_MSIRDY) || ~(regval & RCC_CR_MSION)) + (regval & RCC_CR_MSISRDY) || ~(regval & RCC_CR_MSISON)) { /* If so, then break-out with timeout > 0 */ @@ -638,19 +611,24 @@ void stm32_stdclockconfig(void) } } - /* setting MSIRANGE */ + /* setting MSISRANGE */ + + putreg32((STM32_BOARD_MSISRANGE | + STM32_BOARD_MSIKRANGE | + RCC_ICSCR1_MSIRGSEL_ICSCR1), + STM32_RCC_ICSCR1); regval = getreg32(STM32_RCC_CR); - regval |= (STM32_BOARD_MSIRANGE | RCC_CR_MSION); /* Enable MSI and frequency */ + regval |= RCC_CR_MSISON; putreg32(regval, STM32_RCC_CR); /* Wait until the MSI is ready (or until a timeout elapsed) */ - for (timeout = MSIRDY_TIMEOUT; timeout > 0; timeout--) + for (timeout = MSISRDY_TIMEOUT; timeout > 0; timeout--) { /* Check if the MSIRDY flag is the set in the CR */ - if ((getreg32(STM32_RCC_CR) & RCC_CR_MSIRDY) != 0) + if ((getreg32(STM32_RCC_CR) & RCC_CR_MSISRDY) != 0) { /* If so, then break-out with timeout > 0 */ @@ -658,29 +636,9 @@ void stm32_stdclockconfig(void) } } -#elif defined(STM32_BOARD_USEHSE) - /* Enable External High-Speed Clock (HSE) */ - - regval = getreg32(STM32_RCC_CR); - regval |= RCC_CR_HSEON; /* Enable HSE */ - putreg32(regval, STM32_RCC_CR); - - /* Wait until the HSE is ready (or until a timeout elapsed) */ - - for (timeout = HSERDY_TIMEOUT; timeout > 0; timeout--) - { - /* Check if the HSERDY flag is the set in the CR */ - - if ((getreg32(STM32_RCC_CR) & RCC_CR_HSERDY) != 0) - { - /* If so, then break-out with timeout > 0 */ - - break; - } - } #else -# error stm32_stdclockconfig(), must have one of STM32_BOARD_USEHSI, STM32_BOARD_USEMSI, STM32_BOARD_USEHSE defined +# error stm32_stdclockconfig() currently only supports STM32_BOARD_USEMSIS #endif @@ -699,195 +657,130 @@ void stm32_stdclockconfig(void) stm32_pwr_enableclk(true); + /* Generate an EPOD booster clock frequency of 4 MHz. FIXME: This must + * be computed based on the MSIS clock to yield a frequency between 4 + * and 16 MHz. Also, the EPOD booster clock is required only for + * SYSCLK frequencies greater than 55MHz. + */ + + regval = getreg32(STM32_RCC_PLL1CFGR); + regval &= ~(RCC_PLL1CFGR_PLL1SRC_MASK | RCC_PLL1CFGR_PLL1MBOOST_MASK); + regval |= RCC_PLL1CFGR_PLL1SRC_MSIS | RCC_PLL1CFGR_PLL1MBOOST_DIV_1; + putreg32(regval, STM32_RCC_PLL1CFGR); + /* Select correct main regulator range */ - regval = getreg32(STM32_PWR_CR1); - regval &= ~PWR_CR1_VOS_MASK; + regval = getreg32(STM32_PWR_VOSR); + regval &= ~PWR_VOSR_VOS_MASK; - if (STM32_SYSCLK_FREQUENCY > 80000000) + if (STM32_SYSCLK_FREQUENCY > 110000000) + { + regval |= PWR_VOSR_VOS_RANGE1; + } + else if (STM32_SYSCLK_FREQUENCY > 55000000) { - regval |= PWR_CR1_VOS_RANGE0; + regval |= PWR_VOSR_VOS_RANGE2; } - else if (STM32_SYSCLK_FREQUENCY > 26000000) + else if (STM32_SYSCLK_FREQUENCY > 25000000) { - regval |= PWR_CR1_VOS_RANGE1; + regval |= PWR_VOSR_VOS_RANGE3; } else { - regval |= PWR_CR1_VOS_RANGE0; + regval |= PWR_VOSR_VOS_RANGE4; } - putreg32(regval, STM32_PWR_CR1); + regval |= PWR_VOSR_BOOSTEN; + + putreg32(regval, STM32_PWR_VOSR); /* Wait for voltage regulator to stabilize */ - while (getreg32(STM32_PWR_SR2) & PWR_SR2_VOSF) + while ((getreg32(STM32_PWR_VOSR) & + (PWR_VOSR_VOSRDY | PWR_VOSR_BOOSTRDY)) != + (PWR_VOSR_VOSRDY | PWR_VOSR_BOOSTRDY)) { } - /* Set the HCLK source/divider */ - - regval = getreg32(STM32_RCC_CFGR); - regval &= ~RCC_CFGR_HPRE_MASK; - regval |= STM32_RCC_CFGR_HPRE; - putreg32(regval, STM32_RCC_CFGR); - - /* Set the PCLK2 divider */ - - regval = getreg32(STM32_RCC_CFGR); - regval &= ~RCC_CFGR_PPRE2_MASK; - regval |= STM32_RCC_CFGR_PPRE2; - putreg32(regval, STM32_RCC_CFGR); - - /* Set the PCLK1 divider */ - - regval = getreg32(STM32_RCC_CFGR); - regval &= ~RCC_CFGR_PPRE1_MASK; - regval |= STM32_RCC_CFGR_PPRE1; - putreg32(regval, STM32_RCC_CFGR); - -#ifdef CONFIG_STM32U5_RTC_HSECLOCK - /* Set the RTC clock divisor */ - - regval = getreg32(STM32_RCC_CFGR); - regval &= ~RCC_CFGR_RTCPRE_MASK; - regval |= RCC_CFGR_RTCPRE(HSE_DIVISOR); - putreg32(regval, STM32_RCC_CFGR); -#endif - - /* Set the PLL source and main divider */ - - regval = getreg32(STM32_RCC_PLLCFG); - - /* Configure Main PLL */ - - /* Set the PLL dividers and multipliers to configure the main PLL */ - - regval = (STM32_PLLCFG_PLLM | STM32_PLLCFG_PLLN | - STM32_PLLCFG_PLLP | STM32_PLLCFG_PLLQ | - STM32_PLLCFG_PLLR); - -#ifdef STM32_PLLCFG_PLLP_ENABLED - regval |= RCC_PLLCFG_PLLPEN; -#endif -#ifdef STM32_PLLCFG_PLLQ_ENABLED - regval |= RCC_PLLCFG_PLLQEN; -#endif -#ifdef STM32_PLLCFG_PLLR_ENABLED - regval |= RCC_PLLCFG_PLLREN; -#endif - - /* XXX The choice of clock source to PLL (all three) is independent - * of the sys clock source choice, review the STM32_BOARD_USEHSI - * name; probably split it into two, one for PLL source and one - * for sys clock source. + /* Configure 4 wait states and prefetch for FLASH access. FIXME: Flash + * wait states must be computed based on SYSCLK frequency. */ -#ifdef STM32_BOARD_USEHSI - regval |= RCC_PLLCFG_PLLSRC_HSI16; -#elif defined(STM32_BOARD_USEMSI) - regval |= RCC_PLLCFG_PLLSRC_MSI; -#else /* if STM32_BOARD_USEHSE */ - regval |= RCC_PLLCFG_PLLSRC_HSE; -#endif - - putreg32(regval, STM32_RCC_PLLCFG); - - /* Enable the main PLL */ - - regval = getreg32(STM32_RCC_CR); - regval |= RCC_CR_PLLON; - putreg32(regval, STM32_RCC_CR); + regval = FLASH_ACR_LATENCY_4 | FLASH_ACR_PRFTEN; + putreg32(regval, STM32_FLASH_ACR); - /* Wait until the PLL is ready */ + /* Set the HCLK, PCLK1 and PCLK2 dividers */ - while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLRDY) == 0) - { - } + regval = getreg32(STM32_RCC_CFGR2); + regval &= ~(RCC_CFGR2_HPRE_MASK | + RCC_CFGR2_PPRE1_MASK | + RCC_CFGR2_PPRE2_MASK); + regval |= STM32_RCC_CFGR2_HPRE | + STM32_RCC_CFGR2_PPRE1 | + STM32_RCC_CFGR2_PPRE2; + putreg32(regval, STM32_RCC_CFGR2); -#ifdef CONFIG_STM32U5_SAI1PLL - /* Configure SAI1 PLL */ + /* Set the PCLK3 divider */ - regval = getreg32(STM32_RCC_PLLSAI1CFG); + regval = getreg32(STM32_RCC_CFGR3); + regval &= ~RCC_CFGR3_PPRE3_MASK; + regval |= STM32_RCC_CFGR3_PPRE3; + putreg32(regval, STM32_RCC_CFGR3); - /* Set the PLL dividers and multipliers to configure the SAI1 PLL */ +#ifdef CONFIG_STM32U5_RTC_HSECLOCK - regval = (STM32_PLLSAI1CFG_PLLN | STM32_PLLSAI1CFG_PLLP - | STM32_PLLSAI1CFG_PLLQ | STM32_PLLSAI1CFG_PLLR); +# error stm32_stdclockconfig() currently doesn not support CONFIG_STM32U5_RTC_HSECLOCK -#ifdef STM32_PLLSAI1CFG_PLLP_ENABLED - regval |= RCC_PLLSAI1CFG_PLLPEN; -#endif -#ifdef STM32_PLLSAI1CFG_PLLQ_ENABLED - regval |= RCC_PLLSAI1CFG_PLLQEN; -#endif -#ifdef STM32_PLLSAI1CFG_PLLR_ENABLED - regval |= RCC_PLLSAI1CFG_PLLREN; #endif - putreg32(regval, STM32_RCC_PLLSAI1CFG); + /* Set the PLL1 source, dividers and multipliers */ - /* Enable the SAI1 PLL */ + regval = STM32_RCC_PLL1DIVR_PLL1N | + STM32_RCC_PLL1DIVR_PLL1P | + STM32_RCC_PLL1DIVR_PLL1Q | + STM32_RCC_PLL1DIVR_PLL1R; - regval = getreg32(STM32_RCC_CR); - regval |= RCC_CR_PLLSAI1ON; - putreg32(regval, STM32_RCC_CR); + putreg32(regval, STM32_RCC_PLL1DIVR); - /* Wait until the PLL is ready */ - - while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLSAI1RDY) == 0) - { - } + regval = RCC_PLL1CFGR_PLL1SRC_MSIS | + RCC_PLL1CFGR_PLL1RGE_4_TO_8MHZ | + STM32_RCC_PLL1CFGR_PLL1M | + RCC_PLL1CFGR_PLL1MBOOST_DIV_1; +#ifdef STM32_RCC_PLL1CFGR_PLL1P_ENABLED + regval |= RCC_PLL1CFGR_PLL1PEN; #endif - -#ifdef CONFIG_STM32U5_SAI2PLL - /* Configure SAI2 PLL */ - - regval = getreg32(STM32_RCC_PLLSAI2CFG); - - /* Set the PLL dividers and multipliers to configure the SAI2 PLL */ - - regval = (STM32_PLLSAI2CFG_PLLN | STM32_PLLSAI2CFG_PLLP | - STM32_PLLSAI2CFG_PLLR); - -#ifdef STM32_PLLSAI2CFG_PLLP_ENABLED - regval |= RCC_PLLSAI2CFG_PLLPEN; +#ifdef STM32_RCC_PLL1CFGR_PLL1Q_ENABLED + regval |= RCC_PLL1CFGR_PLL1QEN; #endif -#ifdef STM32_PLLSAI2CFG_PLLR_ENABLED - regval |= RCC_PLLSAI2CFG_PLLREN; +#ifdef STM32_RCC_PLL1CFGR_PLL1R_ENABLED + regval |= RCC_PLL1CFGR_PLL1REN; #endif - putreg32(regval, STM32_RCC_PLLSAI2CFG); + putreg32(regval, STM32_RCC_PLL1CFGR); - /* Enable the SAI2 PLL */ + /* Enable PLL1 */ regval = getreg32(STM32_RCC_CR); - regval |= RCC_CR_PLLSAI2ON; + regval |= RCC_CR_PLL1ON; putreg32(regval, STM32_RCC_CR); - /* Wait until the PLL is ready */ + /* Wait until PLL1 is ready */ - while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLSAI2RDY) == 0) + while ((getreg32(STM32_RCC_CR) & RCC_CR_PLL1RDY) == 0) { } -#endif - - /* Enable FLASH 5 wait states */ - - regval = FLASH_ACR_LATENCY_5; - putreg32(regval, STM32_FLASH_ACR); - /* Select the main PLL as system clock source */ + /* Select the PLL1 as system clock source */ - regval = getreg32(STM32_RCC_CFGR); - regval &= ~RCC_CFGR_SW_MASK; - regval |= RCC_CFGR_SW_PLL; - putreg32(regval, STM32_RCC_CFGR); + regval = getreg32(STM32_RCC_CFGR1); + regval &= ~RCC_CFGR1_SW_MASK; + regval |= RCC_CFGR1_SW_PLL; + putreg32(regval, STM32_RCC_CFGR1); - /* Wait until the PLL source is used as the system clock source */ + /* Wait until PLL1 source is used as the system clock source */ - while ((getreg32(STM32_RCC_CFGR) & RCC_CFGR_SWS_MASK) != - RCC_CFGR_SWS_PLL) + while ((getreg32(STM32_RCC_CFGR1) & RCC_CFGR1_SWS_MASK) != + RCC_CFGR1_SWS_PLL) { }
