From dfae3d4bb3bf6e1467b0b8bdc347b24c4828e838 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 6 May 2026 18:44:17 +0200 Subject: [PATCH] stm32u5: configure system clock to 160 MHz - Uses PLL1 to boost the system clock from the 4 MHz MSIS default to 160 MHz. - Sets VOS to Range 1 (1.2V) and enables the EPOD booster for higher frequency support. - Configures flash latency (4 wait states) and enables prefetch for 160 MHz operation. - Updates CPU and APB timer frequencies in the machine package accordingly. - Fixes LPUART baud rate divisor computation by using 64-bit arithmetic to prevent overflow with the newly increased 160 MHz clock. Signed-off-by: deadprogram --- src/machine/machine_stm32u585.go | 12 ++++---- src/runtime/runtime_stm32u5.go | 48 +++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/machine/machine_stm32u585.go b/src/machine/machine_stm32u585.go index 78b03f83eb..865310bcbd 100644 --- a/src/machine/machine_stm32u585.go +++ b/src/machine/machine_stm32u585.go @@ -8,14 +8,14 @@ import ( ) func CPUFrequency() uint32 { - return 4_000_000 + return 160_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 = 4e6 // 4MHz (MSI default) -const APB2_TIM_FREQ = 4e6 // 4MHz (MSI default) +const APB1_TIM_FREQ = 160e6 // 160MHz (PLL1: MSIS 4MHz × 80 / 1 / 2) +const APB2_TIM_FREQ = 160e6 // 160MHz (PLL1: MSIS 4MHz × 80 / 1 / 2) //---------- UART related code @@ -55,8 +55,10 @@ func (uart *UART) isLPUART1() bool { // NOTE: keep this in sync with the runtime/runtime_stm32u5.go clock init code func (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 { if uart.isLPUART1() { - // LPUART uses BRR = 256 * fclk / baud - return (256 * CPUFrequency()) / baudRate + // LPUART uses BRR = 256 * fclk / baud. + // Use 64-bit arithmetic to avoid overflow: at 160 MHz, + // 256 * 160_000_000 = 40_960_000_000 which exceeds uint32 max. + return uint32(uint64(256) * uint64(CPUFrequency()) / uint64(baudRate)) } // USART requires BRR >= 16 for 16x oversampling (OVER8=0). // A divisor below 16 is invalid per the STM32 reference manual and causes diff --git a/src/runtime/runtime_stm32u5.go b/src/runtime/runtime_stm32u5.go index e54721f393..d66dbec2dc 100644 --- a/src/runtime/runtime_stm32u5.go +++ b/src/runtime/runtime_stm32u5.go @@ -24,18 +24,52 @@ func buffered() int { } func initCLK() { - // Use MSI at 4MHz — the reset default clock configuration. - // The MCU boots with MSI at 4MHz, VOS Range 4, and 0 flash wait states. + // Configure SYSCLK to 160 MHz via PLL1 using MSIS (4 MHz reset default) as the source. + // Formula: Fout = Fin × N / M / R = 4 × 80 / 1 / 2 = 160 MHz + // - M = 1 (Div1), N = 80 (stored as N-1 = 79), R = 2 (Div2) + // - VCO input = 4 MHz (PLL1RGE Range1: 4–8 MHz), VCO output = 320 MHz + // VOS Range 1 (1.2V) is required for SYSCLK > 100 MHz (RM0456 §6.3.6). // Enable PWR peripheral clock (required on STM32U5 before accessing PWR registers). stm32.RCC.AHB3ENR.SetBits(stm32.RCC_AHB3ENR_PWREN) _ = stm32.RCC.AHB3ENR.Get() // read-back for clock stabilization - // Switch from VOS Range 4 to Range 3. Range 4 doesn't support ADC (RM0456 §6.3.6). - // Range 3 supports up to 50 MHz HCLK and enables ADC. No flash wait-state change needed at 4 MHz. - // The EPOD booster must be enabled before changing VOS (RM0456 §10.5.4). + // Enable the EPOD booster before raising VOS (RM0456 §10.5.4). stm32.PWR.VOSR.SetBits(stm32.PWR_VOSR_BOOSTEN) - stm32.PWR.VOSR.ReplaceBits(stm32.PWR_VOSR_VOS_Range3<