machine/stm32: add STM32U585 target definition and runtime

Add processor target (cortex-m33), linker script (2048K flash, 768K RAM),
and arduino-uno-q board target. Runtime initializes 160MHz clock via PLL1
from HSI16, with PWR Range 1 and EPOD booster.

Also add psctype abstraction for timer PSC register width, needed because
the U5 SVD defines PSC as a 16-bit register.
This commit is contained in:
deadprogram
2026-03-15 15:43:56 +01:00
parent 1f00425eb3
commit 47115f0380
15 changed files with 159 additions and 1 deletions
+1 -1
View File
@@ -150,7 +150,7 @@ func (t *TIM) setPeriod(period uint64, updatePrescaler bool) error {
psc = ceil(top, ARR_MAX)
top = top / psc
t.Device.PSC.Set(uint32(psc - 1))
t.Device.PSC.Set(psctype(psc - 1))
} else {
psc = uint64(t.Device.PSC.Get()) + 1
top = top / psc
+1
View File
@@ -731,6 +731,7 @@ func (t *TIM) enableMainOutput() {
}
type arrtype = uint32
type psctype = uint32
type arrRegType = volatile.Register32
const (
+1
View File
@@ -607,6 +607,7 @@ func (t *TIM) enableMainOutput() {
}
type arrtype = uint32
type psctype = uint32
type arrRegType = volatile.Register32
const (
+1
View File
@@ -712,6 +712,7 @@ func (t *TIM) enableMainOutput() {
}
type arrtype = uint32
type psctype = uint32
type arrRegType = volatile.Register32
const (
+1
View File
@@ -554,6 +554,7 @@ func (t *TIM) enableMainOutput() {
}
type arrtype = uint32
type psctype = uint32
type arrRegType = volatile.Register32
const (
+1
View File
@@ -189,6 +189,7 @@ func (t *TIM) enableMainOutput() {
}
type arrtype = uint32
type psctype = uint32
type arrRegType = volatile.Register32
const (
+1
View File
@@ -246,6 +246,7 @@ func (t *TIM) enableMainOutput() {
}
type arrtype = uint32
type psctype = uint32
type arrRegType = volatile.Register32
const (
+1
View File
@@ -532,6 +532,7 @@ func (t *TIM) enableMainOutput() {
}
type arrtype = uint32
type psctype = uint32
type arrRegType = volatile.Register32
const (
+1
View File
@@ -542,6 +542,7 @@ func (t *TIM) enableMainOutput() {
}
type arrtype = uint32
type psctype = uint32
type arrRegType = volatile.Register32
const (
+1
View File
@@ -433,6 +433,7 @@ func initRNG() {
//----------
type arrtype = uint32
type psctype = uint32
type arrRegType = volatile.Register32
const (
+101
View File
@@ -0,0 +1,101 @@
//go:build stm32u5
package runtime
import (
"device/stm32"
"machine"
)
func putchar(c byte) {
machine.Serial.WriteByte(c)
}
func getchar() byte {
for machine.Serial.Buffered() == 0 {
Gosched()
}
v, _ := machine.Serial.ReadByte()
return v
}
func buffered() int {
return machine.Serial.Buffered()
}
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) {
}
}
+15
View File
@@ -0,0 +1,15 @@
//go:build stm32u585
package runtime
import (
"machine"
)
func init() {
initCLK()
machine.InitSerial()
initTickTimer(&machine.TIM16)
}
+7
View File
@@ -0,0 +1,7 @@
{
"inherits": ["stm32u585"],
"build-tags": ["arduino_uno_q"],
"serial": "uart",
"openocd-interface": "stlink",
"openocd-target": "stm32u5x"
}
+16
View File
@@ -0,0 +1,16 @@
{
"inherits": [
"cortex-m33"
],
"build-tags": [
"stm32u585",
"stm32u5",
"stm32"
],
"extra-files": [
"src/device/stm32/stm32u585.s"
],
"linkerscript": "targets/stm32u585.ld",
"flash-method": "openocd",
"openocd-target": "stm32u5x"
}
+10
View File
@@ -0,0 +1,10 @@
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 2048K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 768K
}
_stack_size = 4K;
INCLUDE "targets/arm.ld"