From acc296ef092b29e48b5d7e844e7fb31a2ad4abee Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Sat, 19 Sep 2026 11:40:13 +0200 Subject: [PATCH] arm/stm32n6: configure board clocks after ROM boot In the nominal ROM clock configuration, flash boot leaves PLL1 driving the CPU at 400 MHz. Skipping clock setup when PLL1 is already selected makes SysTick run twice as fast as the board's 200 MHz configuration expects. Switch CPU and system clocks to HSI before reconfiguring PLL1, then apply the board clock tree. Remove the incorrect comments claiming CFGR1 and CFGR2 lock after the first clock switch. Assisted-by: Codex:GPT-6 Signed-off-by: raiden00pl --- arch/arm/src/stm32n6/stm32n6xx_rcc.c | 40 ++++++++++++++++------------ 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/arch/arm/src/stm32n6/stm32n6xx_rcc.c b/arch/arm/src/stm32n6/stm32n6xx_rcc.c index e6ec3cad067..a121aa0548e 100644 --- a/arch/arm/src/stm32n6/stm32n6xx_rcc.c +++ b/arch/arm/src/stm32n6/stm32n6xx_rcc.c @@ -135,9 +135,8 @@ void stm32_rcc_enableperipherals(void) * clock tree is laid out in the board header; see board.h for the full * diagram. * - * IMPORTANT: CFGR1 locks after the first write -- CPUSW and SYSSW must - * be written together in a single putreg32(). CFGR2 (bus prescalers) - * also locks after CFGR1 is written, so it must be set first. + * Switch CPU and system clocks to HSI before changing PLL1, since the + * boot ROM may already be using PLL1 with a different clock tree. * ****************************************************************************/ @@ -146,18 +145,9 @@ void stm32_stdclockconfig(void) volatile int32_t timeout; uint32_t regval; - /* If clocks are already configured (e.g. FSBL set up PLL1 and switched - * CPUSW to IC1), skip PLL1/CFGR1 reconfiguration. CFGR1 locks after - * the first write - a second write crashes the system (SRAM goes - * offline). - */ + /* Keep HSI running while PLL1 and the IC dividers are reconfigured. */ - regval = getreg32(STM32_RCC_CFGR1); - if ((regval & RCC_CFGR1_CPUSWS_MASK) == RCC_CFGR1_CPUSWS_IC1 && - (regval & RCC_CFGR1_SYSSWS_MASK) == RCC_CFGR1_SYSSWS_IC2_IC6_IC11) - { - return; - } + putreg32(RCC_CR_HSION, STM32_RCC_CSR); for (timeout = HSIRDY_TIMEOUT; timeout > 0; timeout--) { @@ -167,6 +157,23 @@ void stm32_stdclockconfig(void) } } + /* The flash boot ROM leaves CPUCLK at 400 MHz. Move both CPU and + * system clocks off PLL1 before disabling it, then establish the + * board clock tree instead of inheriting the ROM's configuration. + */ + + modifyreg32(STM32_RCC_CFGR1, + RCC_CFGR1_CPUSW_MASK | RCC_CFGR1_SYSSW_MASK, 0); + + for (timeout = HSIRDY_TIMEOUT; timeout > 0; timeout--) + { + if ((getreg32(STM32_RCC_CFGR1) & + (RCC_CFGR1_CPUSWS_MASK | RCC_CFGR1_SYSSWS_MASK)) == 0) + { + break; + } + } + putreg32(RCC_CR_PLL1ON, STM32_RCC_CCR); for (timeout = PLL1RDY_TIMEOUT; timeout > 0; timeout--) @@ -229,9 +236,8 @@ void stm32_stdclockconfig(void) | RCC_DIVENR_IC6EN | RCC_DIVENR_IC11EN, STM32_RCC_DIVENSR); - /* CFGR2 (bus prescalers) and CFGR1 (clock-source switch) both lock - * after CFGR1 is written, so CFGR2 must be set first and CFGR1 must - * be written exactly once with both CPUSW and SYSSW in place. + /* Set the bus prescalers before switching CPU and system clocks to + * the configured PLL1 outputs. */ putreg32(RCC_CFGR2_HPRE_SYSCLKd2, STM32_RCC_CFGR2);