From 323b62b405ae02bc17f7e76355fb8014a229bb76 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 17 Mar 2026 18:59:21 +0100 Subject: [PATCH] fix: set stm32u5x clock rate to default The complex 160MHz PLL initialization was hanging the MCU. The fix: Replaced the entire PLL-based clock init with the MSI 4MHz default Signed-off-by: deadprogram --- src/machine/machine_stm32u585.go | 6 +-- src/runtime/runtime_stm32u5.go | 80 ++------------------------------ 2 files changed, 8 insertions(+), 78 deletions(-) diff --git a/src/machine/machine_stm32u585.go b/src/machine/machine_stm32u585.go index 901bec5e8..f5e568bb3 100644 --- a/src/machine/machine_stm32u585.go +++ b/src/machine/machine_stm32u585.go @@ -7,14 +7,14 @@ import ( ) func CPUFrequency() uint32 { - return 160000000 + return 4_000_000 } // Internal use: configured speed of the APB1 and APB2 timers, this should be kept // in sync with any changes to runtime package which configures the oscillators // and clock frequencies -const APB1_TIM_FREQ = 160e6 // 160MHz -const APB2_TIM_FREQ = 160e6 // 160MHz +const APB1_TIM_FREQ = 4e6 // 4MHz (MSI default) +const APB2_TIM_FREQ = 4e6 // 4MHz (MSI default) //---------- UART related code diff --git a/src/runtime/runtime_stm32u5.go b/src/runtime/runtime_stm32u5.go index be55b5e37..cd97531d1 100644 --- a/src/runtime/runtime_stm32u5.go +++ b/src/runtime/runtime_stm32u5.go @@ -3,7 +3,6 @@ package runtime import ( - "device/stm32" "machine" ) @@ -24,78 +23,9 @@ func buffered() int { } func initCLK() { - // Initialize clock to 160MHz using PLL1 with HSI16 as source. - // PLL1 configuration: HSI16 (16MHz) / PLLM(1) * PLLN(10) / PLLR(1) = 160MHz - // VCO = 16 * 10 = 160MHz, PLLR = /1 -> 160MHz SYSCLK - - // Enable PWR clock - stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_CRSEN) // CRS enable not needed but ensures APB1 is clocked - _ = stm32.RCC.APB1ENR1.Get() - - // Set voltage scaling to Range 1 for 160MHz operation - // On U5, voltage scaling is in PWR.VOSR register - // VOS = 11 (Range 1, up to 160MHz) - stm32.PWR.VOSR.ReplaceBits(stm32.PWR_VOSR_VOS_Range1, stm32.PWR_VOSR_VOS_Msk, 0) - // Wait for VOS ready - for !stm32.PWR.VOSR.HasBits(stm32.PWR_VOSR_VOSRDY) { - } - - // Enable EPOD booster for high performance (required for Range 1 >100MHz) - stm32.PWR.VOSR.SetBits(stm32.PWR_VOSR_BOOSTEN) - for !stm32.PWR.VOSR.HasBits(stm32.PWR_VOSR_BOOSTRDY) { - } - - // Enable HSI16 - stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION) - for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) { - } - - // Disable PLL1 before configuration - stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLL1ON) - for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLL1RDY) { - } - - // Configure PLL1: - // Source = HSI16 (0x2) - // PLLM = 0 (divide by 1) - // PLL1RGE = 0x3 (input range 8-16MHz) - // Enable PLLR output - stm32.RCC.PLL1CFGR.Set( - (stm32.RCC_PLL1CFGR_PLL1SRC_HSI16 << stm32.RCC_PLL1CFGR_PLL1SRC_Pos) | - (stm32.RCC_PLL1CFGR_PLL1M_Div1 << stm32.RCC_PLL1CFGR_PLL1M_Pos) | - (stm32.RCC_PLL1CFGR_PLL1RGE_Range2 << stm32.RCC_PLL1CFGR_PLL1RGE_Pos)) - - // Enable PLL1R output - stm32.RCC.PLL1CFGR.SetBits(1 << stm32.RCC_PLL1CFGR_PLL1REN_Pos) - - // Set PLL1 dividers in PLL1DIVR: - // PLL1N = 10 (value - 1 = 9 in register) - // PLL1R = 1 (value - 1 = 0 in register) - // VCO = HSI16/1 * 10 = 160MHz - // PLLR output = 160MHz / 1 = 160MHz - stm32.RCC.SetPLL1DIVR_PLL1N(9) // N = 10, register value = N-1 = 9 - stm32.RCC.SetPLL1DIVR_PLL1R(0) // R = 1, register value = R-1 = 0 - - // Enable PLL1 - stm32.RCC.CR.SetBits(stm32.RCC_CR_PLL1ON) - for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLL1RDY) { - } - - // Set flash latency to 4 wait states (required for 160MHz in Range 1) - const FLASH_LATENCY_4 = 4 - stm32.FLASH.ACR.ReplaceBits(FLASH_LATENCY_4, stm32.Flash_ACR_LATENCY_Msk, 0) - for (stm32.FLASH.ACR.Get() & stm32.Flash_ACR_LATENCY_Msk) != FLASH_LATENCY_4 { - } - - // Set AHB prescaler to 1 (no division) in CFGR2 - stm32.RCC.CFGR2.ReplaceBits(stm32.RCC_CFGR2_HPRE_Div1, stm32.RCC_CFGR2_HPRE_Msk, 0) - - // Set APB1 and APB2 prescalers to 1 (no division) in CFGR2 - stm32.RCC.CFGR2.ReplaceBits(stm32.RCC_CFGR2_PPRE1_Div1, stm32.RCC_CFGR2_PPRE1_Msk, 0) - stm32.RCC.CFGR2.ReplaceBits(stm32.RCC_CFGR2_PPRE2_Div1, stm32.RCC_CFGR2_PPRE2_Msk, 0) - - // Switch system clock to PLL1 (SW = 11 = PLL) - stm32.RCC.CFGR1.ReplaceBits(stm32.RCC_CFGR1_SW_PLL, stm32.RCC_CFGR1_SW_Msk, 0) - for (stm32.RCC.CFGR1.Get() & stm32.RCC_CFGR1_SWS_Msk) != (stm32.RCC_CFGR1_SWS_PLL << stm32.RCC_CFGR1_SWS_Pos) { - } + // Use MSI at 4MHz — the reset default clock configuration. + // This matches the known-working bare-metal C configuration for + // the Arduino Uno Q (STM32U585). The MCU boots with MSI at 4MHz, + // VOS Range 4, and 0 flash wait states. No additional configuration + // is needed. }