diff --git a/src/machine/machine_stm32.go b/src/machine/machine_stm32.go index 8ef5fed7e7..87091a7a3d 100644 --- a/src/machine/machine_stm32.go +++ b/src/machine/machine_stm32.go @@ -2,6 +2,10 @@ package machine +import ( + "device/arm" +) + // Peripheral abstraction layer for the stm32. const ( @@ -53,3 +57,8 @@ func (p Pin) Get() bool { val := port.IDR.Get() & (1 << pin) return (val > 0) } + +// Wait for interrupt or event +func waitForEvents() { + arm.Asm("wfe") +} diff --git a/src/machine/machine_stm32_i2c_revb.go b/src/machine/machine_stm32_i2c_revb.go index aca962400c..d70b8a7e31 100644 --- a/src/machine/machine_stm32_i2c_revb.go +++ b/src/machine/machine_stm32_i2c_revb.go @@ -7,9 +7,6 @@ import ( "unsafe" ) -//go:linkname ticks runtime.ticks -func ticks() int64 - // I2C implementation for 'newer' STM32 MCUs, including the F7, L5 and L4 // series of MCUs. // @@ -103,7 +100,7 @@ func (i2c *I2C) configurePins(config I2CConfig) { } func (i2c *I2C) controllerTransmit(addr uint16, w []byte) error { - start := ticks() + start := Ticks() if !i2c.waitOnFlagUntilTimeout(flagBUSY, false, start) { return errI2CBusReadyTimeout @@ -162,7 +159,7 @@ func (i2c *I2C) controllerTransmit(addr uint16, w []byte) error { } func (i2c *I2C) controllerReceive(addr uint16, r []byte) error { - start := ticks() + start := Ticks() if !i2c.waitOnFlagUntilTimeout(flagBUSY, false, start) { return errI2CBusReadyTimeout @@ -220,16 +217,16 @@ func (i2c *I2C) controllerReceive(addr uint16, r []byte) error { return nil } -func (i2c *I2C) waitOnFlagUntilTimeout(flag uint32, set bool, startTicks int64) bool { +func (i2c *I2C) waitOnFlagUntilTimeout(flag uint32, set bool, startTicks uint64) bool { for i2c.hasFlag(flag) != set { - if (ticks() - startTicks) > TIMEOUT_TICKS { + if (Ticks() - startTicks) > TIMEOUT_TICKS { return false } } return true } -func (i2c *I2C) waitOnRXNEFlagUntilTimeout(startTicks int64) bool { +func (i2c *I2C) waitOnRXNEFlagUntilTimeout(startTicks uint64) bool { for !i2c.hasFlag(flagRXNE) { if i2c.isAcknowledgeFailed(startTicks) { return false @@ -241,7 +238,7 @@ func (i2c *I2C) waitOnRXNEFlagUntilTimeout(startTicks int64) bool { return false } - if (ticks() - startTicks) > TIMEOUT_TICKS { + if (Ticks() - startTicks) > TIMEOUT_TICKS { return false } } @@ -249,13 +246,13 @@ func (i2c *I2C) waitOnRXNEFlagUntilTimeout(startTicks int64) bool { return true } -func (i2c *I2C) waitOnTXISFlagUntilTimeout(startTicks int64) bool { +func (i2c *I2C) waitOnTXISFlagUntilTimeout(startTicks uint64) bool { for !i2c.hasFlag(flagTXIS) { if i2c.isAcknowledgeFailed(startTicks) { return false } - if (ticks() - startTicks) > TIMEOUT_TICKS { + if (Ticks() - startTicks) > TIMEOUT_TICKS { return false } } @@ -263,13 +260,13 @@ func (i2c *I2C) waitOnTXISFlagUntilTimeout(startTicks int64) bool { return true } -func (i2c *I2C) waitOnStopFlagUntilTimeout(startTicks int64) bool { +func (i2c *I2C) waitOnStopFlagUntilTimeout(startTicks uint64) bool { for !i2c.hasFlag(flagSTOPF) { if i2c.isAcknowledgeFailed(startTicks) { return false } - if (ticks() - startTicks) > TIMEOUT_TICKS { + if (Ticks() - startTicks) > TIMEOUT_TICKS { return false } } @@ -277,12 +274,12 @@ func (i2c *I2C) waitOnStopFlagUntilTimeout(startTicks int64) bool { return true } -func (i2c *I2C) isAcknowledgeFailed(startTicks int64) bool { +func (i2c *I2C) isAcknowledgeFailed(startTicks uint64) bool { if i2c.hasFlag(flagAF) { // Wait until STOP Flag is reset // AutoEnd should be initiate after AF for !i2c.hasFlag(flagSTOPF) { - if (ticks() - startTicks) > TIMEOUT_TICKS { + if (Ticks() - startTicks) > TIMEOUT_TICKS { return true } } diff --git a/src/runtime/runtime_stm32_timers.go b/src/machine/machine_stm32_timers.go similarity index 83% rename from src/runtime/runtime_stm32_timers.go rename to src/machine/machine_stm32_timers.go index 589995d7fe..97026536c5 100644 --- a/src/runtime/runtime_stm32_timers.go +++ b/src/machine/machine_stm32_timers.go @@ -1,6 +1,6 @@ // +build stm32 -package runtime +package machine // This file implements a common implementation of implementing 'ticks' and 'sleep' for STM32 devices. The // implementation uses two 'basic' timers, so should be compatible with a broad range of STM32 MCUs. @@ -47,24 +47,14 @@ var ( sleepTimer *timerInfo ) -func ticksToNanoseconds(ticks timeUnit) int64 { - return int64(ticks) * TICKS_PER_NS -} - -func nanosecondsToTicks(ns int64) timeUnit { - return timeUnit(ns / TICKS_PER_NS) -} - -// number of ticks (microseconds) since start. -//go:linkname ticks runtime.ticks -func ticks() timeUnit { - return timeUnit(tickCount.Get()) -} - // // -- Ticks --- // +func Ticks() uint64 { + return tickCount.Get() +} + // Enable the timer used to count ticks func initTickTimer(ti *timerInfo) { tickTimer = ti @@ -120,25 +110,6 @@ func handleTick(interrupt.Interrupt) { // --- Sleep --- // -func sleepTicks(d timeUnit) { - // If there is a scheduler, we sleep until any kind of CPU event up to - // a maximum of the requested sleep duration. - // - // The scheduler will call again if there is nothing to do and a further - // sleep is required. - if hasScheduler { - timerSleep(ticksToNanoseconds(d)) - return - } - - // There's no scheduler, so we sleep until at least the requested number - // of ticks has passed. - end := ticks() + d - for ticks() < end { - timerSleep(ticksToNanoseconds(d)) - } -} - // Enable the Sleep clock func initSleepTimer(ti *timerInfo) { sleepTimer = ti @@ -157,7 +128,7 @@ func initSleepTimer(ti *timerInfo) { } // timerSleep sleeps for 'at most' ns nanoseconds, but possibly less. -func timerSleep(ns int64) { +func TimerSleep(ns int64) { // Calculate initial pre-scale value. // delay (in ns) and clock freq are both large values, so do the nanosecs // conversion (divide by 1G) by pre-dividing each by 1000 to avoid overflow diff --git a/src/machine/machine_stm32f103.go b/src/machine/machine_stm32f103.go index e1c91ca03b..e05bf0d306 100644 --- a/src/machine/machine_stm32f103.go +++ b/src/machine/machine_stm32f103.go @@ -102,6 +102,66 @@ func enableAltFuncClock(bus unsafe.Pointer) { } } +//---------- Clock and Oscillator related code + +const ( + TICK_RATE = 1000 // 1 KHz + SLEEP_TIMER_IRQ = stm32.IRQ_TIM3 + SLEEP_TIMER_FREQ = 72000000 // 72 MHz + TICK_TIMER_IRQ = stm32.IRQ_TIM4 + TICK_TIMER_FREQ = 72000000 // 72 MHz +) + +type arrtype = uint32 + +func InitializeClocks() { + initPLL() + + initSleepTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM3EN, + Device: stm32.TIM3, + }) + + initTickTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM4EN, + Device: stm32.TIM4, + }) +} + +// InitializeClocks sets clock to 72MHz using HSE 8MHz crystal w/ PLL X 9 (8MHz x 9 = 72MHz). +func initPLL() { + stm32.FLASH.ACR.SetBits(stm32.FLASH_ACR_LATENCY_WS2) // Two wait states, per datasheet + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos) // prescale PCLK1 = HCLK/2 + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div1 << stm32.RCC_CFGR_PPRE2_Pos) // prescale PCLK2 = HCLK/1 + stm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON) // enable HSE clock + + // wait for the HSEREADY flag + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) { + } + + stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION) // enable HSI clock + + // wait for the HSIREADY flag + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) { + } + + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLSRC) // set PLL source to HSE + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLMUL_Mul9 << stm32.RCC_CFGR_PLLMUL_Pos) // multiply by 9 + stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) // enable the PLL + + // wait for the PLLRDY flag + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { + } + + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_SW_PLL) // set clock source to pll + + // wait for PLL to be CLK + for !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) { + } +} + //---------- UART related code // Configure the TX and RX pins diff --git a/src/machine/machine_stm32f405.go b/src/machine/machine_stm32f405.go index d70b6a712d..42c11dca86 100644 --- a/src/machine/machine_stm32f405.go +++ b/src/machine/machine_stm32f405.go @@ -33,6 +33,180 @@ const ( AF15_EVENTOUT = 15 ) +//---------- Clock and Oscillator related code + +const ( + // +----------------------+ + // | Clock Settings | + // +-------------+--------+ + // | HSE | 12mhz | + // | SYSCLK | 168mhz | + // | HCLK | 168mhz | + // | APB1(PCLK1) | 42mhz | + // | APB2(PCLK2) | 84mhz | + // +-------------+--------+ + HCLK_FREQ_HZ = 168000000 + PCLK1_FREQ_HZ = HCLK_FREQ_HZ / 4 + PCLK2_FREQ_HZ = HCLK_FREQ_HZ / 2 +) + +const ( + PWR_SCALE1 = 1 << stm32.PWR_CSR_VOSRDY_Pos // max value of HCLK = 168 MHz + PWR_SCALE2 = 0 // max value of HCLK = 144 MHz + + PLL_SRC_HSE = 1 << stm32.RCC_PLLCFGR_PLLSRC_Pos // use HSE for PLL and PLLI2S + PLL_SRC_HSI = 0 // use HSI for PLL and PLLI2S + + PLL_DIV_M = 6 << stm32.RCC_PLLCFGR_PLLM_Pos + PLL_MLT_N = 168 << stm32.RCC_PLLCFGR_PLLN_Pos + PLL_DIV_P = ((2 >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos + PLL_DIV_Q = 7 << stm32.RCC_PLLCFGR_PLLQ_Pos + + SYSCLK_SRC_PLL = stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos + SYSCLK_STAT_PLL = stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos + + RCC_DIV_PCLK1 = stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos // HCLK / 4 + RCC_DIV_PCLK2 = stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos // HCLK / 2 + RCC_DIV_HCLK = stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos // SYSCLK / 1 + + CLK_CCM_RAM = 1 << 20 +) + +const ( + // +-----------------------------------+ + // | Voltage range = 2.7V - 3.6V | + // +----------------+------------------+ + // | Wait states | System Bus | + // | (WS, LATENCY) | HCLK (MHz) | + // +----------------+------------------+ + // | 0 WS, 1 cycle | 0 < HCLK ≤ 30 | + // | 1 WS, 2 cycles | 30 < HCLK ≤ 60 | + // | 2 WS, 3 cycles | 60 < HCLK ≤ 90 | + // | 3 WS, 4 cycles | 90 < HCLK ≤ 120 | + // | 4 WS, 5 cycles | 120 < HCLK ≤ 150 | + // | 5 WS, 6 cycles | 150 < HCLK ≤ 168 | + // +----------------+------------------+ + FLASH_LATENCY = 5 << stm32.FLASH_ACR_LATENCY_Pos // 5 WS (6 CPU cycles) + + // instruction cache, data cache, and prefetch + FLASH_OPTIONS = stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | stm32.FLASH_ACR_PRFTEN +) + +/* + timer settings used for tick and sleep. + + note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock + settings above, so must be kept in sync if the clock settings are changed. +*/ +const ( + TICK_RATE = 1000 // 1 KHz + SLEEP_TIMER_IRQ = stm32.IRQ_TIM3 + SLEEP_TIMER_FREQ = PCLK1_FREQ_HZ * 2 + TICK_TIMER_IRQ = stm32.IRQ_TIM7 + TICK_TIMER_FREQ = PCLK1_FREQ_HZ * 2 +) + +type arrtype = uint32 + +const asyncScheduler = false + +func InitializeClocks() { + initOSC() // configure oscillators + initPLL() + + initSleepTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM3EN, + Device: stm32.TIM3, + }) + + initTickTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM7EN, + Device: stm32.TIM7, + }) +} + +func initOSC() { + // enable voltage regulator + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) + stm32.PWR.CR.SetBits(PWR_SCALE1) + + // enable HSE + stm32.RCC.CR.Set(stm32.RCC_CR_HSEON) + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) { + } + + // Since the main-PLL configuration parameters cannot be changed once PLL is + // enabled, it is recommended to configure PLL before enabling it (selection + // of the HSI or HSE oscillator as PLL clock source, and configuration of + // division factors M, N, P, and Q). + + // disable PLL and wait for it to reset + stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON) + for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { + } + + // set HSE as PLL source and configure clock divisors + stm32.RCC.PLLCFGR.Set(PLL_SRC_HSE | PLL_DIV_M | PLL_MLT_N | PLL_DIV_P | PLL_DIV_Q) + + // enable PLL and wait for it to sync + stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { + } +} + +func initPLL() { + // After reset, the CPU clock frequency is 16 MHz and 0 wait state (WS) is + // configured in the FLASH_ACR register. + // + // It is highly recommended to use the following software sequences to tune + // the number of wait states needed to access the Flash memory with the CPU + // frequency. + // + // 1. Program the new number of wait states to the LATENCY bits in the + // FLASH_ACR register + // 2. Check that the new number of wait states is taken into account to access + // the Flash memory by reading the FLASH_ACR register + // 3. Modify the CPU clock source by writing the SW bits in the RCC_CFGR + // register + // 4. If needed, modify the CPU clock prescaler by writing the HPRE bits in + // RCC_CFGR + // 5. Check that the new CPU clock source or/and the new CPU clock prescaler + // value is/are taken into account by reading the clock source status (SWS + // bits) or/and the AHB prescaler value (HPRE bits), respectively, in the + // RCC_CFGR register. + + // configure instruction/data caching, prefetch, and flash access wait states + stm32.FLASH.ACR.Set(FLASH_OPTIONS | FLASH_LATENCY) + for !stm32.FLASH.ACR.HasBits(FLASH_LATENCY) { // verify new wait states + } + + // After a system reset, the HSI oscillator is selected as the system clock. + // When a clock source is used directly or through PLL as the system clock, it + // is not possible to stop it. + // + // A switch from one clock source to another occurs only if the target clock + // source is ready (clock stable after startup delay or PLL locked). If a + // clock source that is not yet ready is selected, the switch occurs when the + // clock source is ready. Status bits in the RCC clock control register + // (RCC_CR) indicate which clock(s) is (are) ready and which clock is + // currently used as the system clock. + + // set CPU clock source to PLL + stm32.RCC.CFGR.SetBits(SYSCLK_SRC_PLL) + + // update PCKL1/2 and HCLK divisors + stm32.RCC.CFGR.SetBits(RCC_DIV_PCLK1 | RCC_DIV_PCLK2 | RCC_DIV_HCLK) + + // verify system clock source is ready + for !stm32.RCC.CFGR.HasBits(SYSCLK_STAT_PLL) { + } + + // enable the CCM RAM clock + stm32.RCC.AHB1ENR.SetBits(CLK_CCM_RAM) +} + // -- UART --------------------------------------------------------------------- func (uart *UART) configurePins(config UARTConfig) { diff --git a/src/machine/machine_stm32f407.go b/src/machine/machine_stm32f407.go index 72c157ccbc..33c3724e0d 100644 --- a/src/machine/machine_stm32f407.go +++ b/src/machine/machine_stm32f407.go @@ -32,6 +32,127 @@ const ( AF15_EVENTOUT = 15 ) +//---------- Clock and Oscillator related code + +/* + clock settings + +-------------+--------+ + | HSE | 8mhz | + | SYSCLK | 168mhz | + | HCLK | 168mhz | + | APB2(PCLK2) | 84mhz | + | APB1(PCLK1) | 42mhz | + +-------------+--------+ +*/ +const ( + HSE_STARTUP_TIMEOUT = 0x0500 + // PLL Options - See RM0090 Reference Manual pg. 95 + PLL_M = 8 // PLL_VCO = (HSE_VALUE or HSI_VLAUE / PLL_M) * PLL_N + PLL_N = 336 + PLL_P = 2 // SYSCLK = PLL_VCO / PLL_P + PLL_Q = 7 // USB OTS FS, SDIO and RNG Clock = PLL_VCO / PLL_Q +) + +/* + timer settings used for tick and sleep. + + note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock + settings above, so must be kept in sync if the clock settings are changed. +*/ +const ( + TICK_RATE = 1000 // 1 KHz + TICK_TIMER_IRQ = stm32.IRQ_TIM7 + TICK_TIMER_FREQ = 84000000 // 84 MHz + SLEEP_TIMER_IRQ = stm32.IRQ_TIM3 + SLEEP_TIMER_FREQ = 84000000 // 84 MHz +) + +type arrtype = uint32 + +func InitializeClocks() { + initPLL() + + initSleepTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM3EN, + Device: stm32.TIM3, + }) + + initTickTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM7EN, + Device: stm32.TIM7, + }) +} + +func initPLL() { + // Reset clock registers + // Set HSION + stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION) + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) { + } + + // Reset CFGR + stm32.RCC.CFGR.Set(0x00000000) + // Reset HSEON, CSSON and PLLON + stm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEON | stm32.RCC_CR_CSSON | stm32.RCC_CR_PLLON) + // Reset PLLCFGR + stm32.RCC.PLLCFGR.Set(0x24003010) + // Reset HSEBYP + stm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEBYP) + // Disable all interrupts + stm32.RCC.CIR.Set(0x00000000) + + // Set up the clock + var startupCounter uint32 = 0 + + // Enable HSE + stm32.RCC.CR.Set(stm32.RCC_CR_HSEON) + + // Wait till HSE is ready and if timeout is reached exit + for { + startupCounter++ + if stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) || (startupCounter == HSE_STARTUP_TIMEOUT) { + break + } + } + if stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) { + // Enable high performance mode, System frequency up to 168MHz + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) + stm32.PWR.CR.SetBits(0x4000) // PWR_CR_VOS + // HCLK = SYSCLK / 1 + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos) + // PCLK2 = HCLK / 2 + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos) + // PCLK1 = HCLK / 4 + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos) + // Configure the main PLL + // PLL Options - See RM0090 Reference Manual pg. 95 + stm32.RCC.PLLCFGR.Set(PLL_M | (PLL_N << 6) | (((PLL_P >> 1) - 1) << 16) | + (1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | (PLL_Q << 24)) + // Enable main PLL + stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) + // Wait till the main PLL is ready + for (stm32.RCC.CR.Get() & stm32.RCC_CR_PLLRDY) == 0 { + } + // Configure Flash prefetch, Instruction cache, Data cache and wait state + stm32.FLASH.ACR.Set(stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | (5 << stm32.FLASH_ACR_LATENCY_Pos)) + // Select the main PLL as system clock source + stm32.RCC.CFGR.ClearBits(stm32.RCC_CFGR_SW_Msk) + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos) + for (stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk) != (stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) { + } + + } else { + // If HSE failed to start up, the application will have wrong clock configuration + for { + } + } + + // Enable the CCM RAM clock + stm32.RCC.AHB1ENR.SetBits(1 << 20) +} + //---------- UART related code // Configure the UART. diff --git a/src/machine/machine_stm32f7x2.go b/src/machine/machine_stm32f7x2.go index 376161bba6..ee8a0d8413 100644 --- a/src/machine/machine_stm32f7x2.go +++ b/src/machine/machine_stm32f7x2.go @@ -12,6 +12,122 @@ func CPUFrequency() uint32 { return 216000000 } +//---------- Clock and Oscillator related code + +/* + clock settings + +-------------+--------+ + | HSE | 8mhz | + | SYSCLK | 216mhz | + | HCLK | 216mhz | + | APB1(PCLK1) | 27mhz | + | APB2(PCLK2) | 108mhz | + +-------------+--------+ +*/ +const ( + HSE_STARTUP_TIMEOUT = 0x0500 + PLL_M = 4 + PLL_N = 216 + PLL_P = 2 + PLL_Q = 2 +) + +/* + timer settings used for tick and sleep. + + note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock + settings above, so must be kept in sync if the clock settings are changed. +*/ +const ( + TICK_RATE = 1000 // 1 KHz + SLEEP_TIMER_IRQ = stm32.IRQ_TIM3 + SLEEP_TIMER_FREQ = 54000000 // 54 MHz (2x APB1) + TICK_TIMER_IRQ = stm32.IRQ_TIM7 + TICK_TIMER_FREQ = 54000000 // 54 MHz (2x APB1) +) + +type arrtype = uint32 + +func InitializeClocks() { + initPLL() + + initSleepTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM3EN, + Device: stm32.TIM3, + }) + + initTickTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM7EN, + Device: stm32.TIM7, + }) +} + +func initPLL() { + // PWR_CLK_ENABLE + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) + _ = stm32.RCC.APB1ENR.Get() + + // PWR_VOLTAGESCALING_CONFIG + stm32.PWR.CR1.ReplaceBits(0x3< 7 { + stm32.FLASH.ACR.ReplaceBits(7, stm32.FLASH_ACR_LATENCY_Msk, 0) + } + + // Set APB1 and APB2 clocks (0x1800 = DIV8, 0x1000 = DIV2) + stm32.RCC.CFGR.ReplaceBits(0x1800, stm32.RCC_CFGR_PPRE1_Msk, 0) + stm32.RCC.CFGR.ReplaceBits(0x1000<<3, stm32.RCC_CFGR_PPRE2_Msk, 0) +} + +func initOsc() { + // Enable HSE, wait until ready + stm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON) + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) { + } + + // Disable the PLL, wait until disabled + stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON) + for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { + } + + // Configure the PLL + stm32.RCC.PLLCFGR.Set(0x20000000 | + (1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | // 1 = HSE + PLL_M | + (PLL_N << stm32.RCC_PLLCFGR_PLLN_Pos) | + (((PLL_P >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos) | + (PLL_Q << stm32.RCC_PLLCFGR_PLLQ_Pos)) + + // Enable the PLL, wait until ready + stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { + } +} + //---------- UART related code // Configure the UART. diff --git a/src/machine/machine_stm32l0.go b/src/machine/machine_stm32l0.go index 886c3985a0..4f951ff7d1 100644 --- a/src/machine/machine_stm32l0.go +++ b/src/machine/machine_stm32l0.go @@ -141,6 +141,80 @@ func (p Pin) enableClock() { } } +//---------- Clock and Oscillator related code + +const ( + RCC_SYSCLK_DIV1 = 0 // Needs SVD update (should be stm32.RCC_SYSCLK_DIV1) +) + +type arrtype = uint16 + +func initPLL() { + // Set Power Regulator to enable max performance (1.8V) + stm32.PWR.CR.ReplaceBits(1< getFlashLatency() { + setFlashLatency(FlashLatency) + for getFlashLatency() != FlashLatency { + } + } + + // HCLK + stm32.RCC.CFGR.ReplaceBits(RCC_SYSCLK_DIV1, stm32.RCC_CFGR_HPRE_Msk, 0) + + // Use PLL As System clock + stm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_SWS_PLL, stm32.RCC_CFGR_SW_Msk, 0) + for stm32.RCC.CFGR.Get()&stm32.RCC_CFGR_SW_Msk != stm32.RCC_CFGR_SWS_PLL { + } + + // Set prescalers so half system clock (PCLKx = HCLK/2) + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos) + stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos) +} + +func getFlashLatency() uint32 { + return stm32.FLASH.ACR.Get() & stm32.Flash_ACR_LATENCY_Msk +} + +func setFlashLatency(l uint32) { + stm32.FLASH.ACR.ReplaceBits(l, stm32.Flash_ACR_LATENCY_Msk, 0) +} + //---------- UART related types and code // Configure the UART. diff --git a/src/machine/machine_stm32l0x1.go b/src/machine/machine_stm32l0x1.go index 3fad050a67..900240cdd1 100644 --- a/src/machine/machine_stm32l0x1.go +++ b/src/machine/machine_stm32l0x1.go @@ -50,3 +50,37 @@ func enableAltFuncClock(bus unsafe.Pointer) { stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN) } } + +/* + timer settings used for tick and sleep. + + note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock + settings, so must be kept in sync if the clock settings are changed. +*/ +const ( + TICK_RATE = 1000 // 1 KHz + TICK_TIMER_IRQ = stm32.IRQ_TIM21 + TICK_TIMER_FREQ = 32000000 // 32 MHz + SLEEP_TIMER_IRQ = stm32.IRQ_TIM22 + SLEEP_TIMER_FREQ = 32000000 // 32 MHz +) + +const ( + FlashLatency = stm32.Flash_ACR_LATENCY_WS1 +) + +func InitializeClocks() { + initPLL() + + initSleepTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM22EN, + Device: stm32.TIM22, + }) + + initTickTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM21EN, + Device: stm32.TIM21, + }) +} diff --git a/src/machine/machine_stm32l0x2.go b/src/machine/machine_stm32l0x2.go index 71c7cd4a01..6f0048e258 100644 --- a/src/machine/machine_stm32l0x2.go +++ b/src/machine/machine_stm32l0x2.go @@ -52,3 +52,37 @@ func enableAltFuncClock(bus unsafe.Pointer) { stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN) } } + +/* + timer settings used for tick and sleep. + + note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock + settings, so must be kept in sync if the clock settings are changed. +*/ +const ( + TICK_RATE = 1000 // 1 KHz + TICK_TIMER_IRQ = stm32.IRQ_TIM7 + TICK_TIMER_FREQ = 32000000 // 32 MHz + SLEEP_TIMER_IRQ = stm32.IRQ_TIM3 + SLEEP_TIMER_FREQ = 32000000 // 32 MHz +) + +const ( + FlashLatency = stm32.Flash_ACR_LATENCY_WS1 +) + +func InitializeClocks() { + initPLL() + + initSleepTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM3EN, + Device: stm32.TIM3, + }) + + initTickTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB1ENR, + EnableFlag: stm32.RCC_APB1ENR_TIM7EN, + Device: stm32.TIM7, + }) +} diff --git a/src/machine/machine_stm32l4x2.go b/src/machine/machine_stm32l4x2.go index 3e307b211b..fa3fa59c4b 100644 --- a/src/machine/machine_stm32l4x2.go +++ b/src/machine/machine_stm32l4x2.go @@ -12,6 +12,253 @@ func CPUFrequency() uint32 { return 80000000 } +//---------- Clock and Oscillator related code +/* + clock settings + +-------------+-----------+ + | LSE | 32.768khz | + | SYSCLK | 80mhz | + | HCLK | 80mhz | + | APB1(PCLK1) | 80mhz | + | APB2(PCLK2) | 80mhz | + +-------------+-----------+ +*/ +const ( + HSE_STARTUP_TIMEOUT = 0x0500 + PLL_M = 1 + PLL_N = 40 + PLL_P = RCC_PLLP_DIV7 + PLL_Q = RCC_PLLQ_DIV2 + PLL_R = RCC_PLLR_DIV2 + + MSIRANGE = stm32.RCC_CR_MSIRANGE_Range4M + + PWR_CR1_VOS_0 = 1 << stm32.PWR_CR1_VOS_Pos + PWR_CR1_VOS_1 = 2 << stm32.PWR_CR1_VOS_Pos + PWR_REGULATOR_VOLTAGE_SCALE1 = PWR_CR1_VOS_0 + PWR_REGULATOR_VOLTAGE_SCALE2 = PWR_CR1_VOS_1 + + FLASH_LATENCY_0 = 0 + FLASH_LATENCY_1 = 1 + FLASH_LATENCY_2 = 2 + FLASH_LATENCY_3 = 3 + FLASH_LATENCY_4 = 4 + + RCC_PLLP_DIV7 = 7 + RCC_PLLQ_DIV2 = 2 + RCC_PLLR_DIV2 = 2 + + RCC_CFGR_SWS_MSI = 0x0 + RCC_CFGR_SWS_PLL = 0xC + + RCC_PLLSOURCE_MSI = 1 + + RCC_PLL_SYSCLK = stm32.RCC_PLLCFGR_PLLREN +) + +/* + timer settings used for tick and sleep. + + note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock + settings above, so must be kept in sync if the clock settings are changed. +*/ +const ( + TICK_RATE = 1000 // 1 KHz + TICK_TIMER_IRQ = stm32.IRQ_TIM1_UP_TIM16 + TICK_TIMER_FREQ = 80000000 // 80 MHz + SLEEP_TIMER_IRQ = stm32.IRQ_TIM1_BRK_TIM15 + SLEEP_TIMER_FREQ = 80000000 // 84 MHz +) + +type arrtype = uint32 + +func InitializeClocks() { + initPLL() + + initSleepTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM15EN, + Device: stm32.TIM15, + }) + + initTickTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM16EN, + Device: stm32.TIM16, + }) +} + +func initPLL() { + // PWR_CLK_ENABLE + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN) + _ = stm32.RCC.APB1ENR1.Get() + + // Disable Backup domain protection + if !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) { + stm32.PWR.CR1.SetBits(stm32.PWR_CR1_DBP) + for !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) { + } + } + + // Set LSE Drive to LOW + stm32.RCC.BDCR.ReplaceBits(0, stm32.RCC_BDCR_LSEDRV_Msk, 0) + + // Initialize the High-Speed External Oscillator + initOsc() + + // PWR_VOLTAGESCALING_CONFIG + stm32.PWR.CR1.ReplaceBits(0, stm32.PWR_CR1_VOS_Msk, 0) + _ = stm32.PWR.CR1.Get() + + // Set flash wait states (min 5 latency units) based on clock + if (stm32.FLASH.ACR.Get() & 0xF) < 5 { + stm32.FLASH.ACR.ReplaceBits(5, 0xF, 0) + } + + // Ensure HCLK does not exceed max during transition + stm32.RCC.CFGR.ReplaceBits(8< 5 { + stm32.FLASH.ACR.ReplaceBits(5, 0xF, 0) + } + + // Set APB1 and APB2 clocks (0 = DIV1) + stm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE1_Msk, 0) + stm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE2_Msk, 0) +} + +func initOsc() { + sysclkSource := stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk + pllConfig := stm32.RCC.PLLCFGR.Get() & stm32.RCC_PLLCFGR_PLLSRC_Msk + + // Enable MSI, adjusting flash latency + if sysclkSource == RCC_CFGR_SWS_MSI || + (sysclkSource == RCC_CFGR_SWS_PLL && pllConfig == RCC_PLLSOURCE_MSI) { + if MSIRANGE > getMSIRange() { + setFlashLatencyFromMSIRange(MSIRANGE) + + setMSIFreq(MSIRANGE, 0) + } else { + setMSIFreq(MSIRANGE, 0) + + if sysclkSource == RCC_CFGR_SWS_MSI { + setFlashLatencyFromMSIRange(MSIRANGE) + } + } + } else { + stm32.RCC.CR.SetBits(stm32.RCC_CR_MSION) + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_MSIRDY) { + } + + setMSIFreq(MSIRANGE, 0) + } + + // Enable LSE, wait until ready + stm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_LSEON) + for !stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSEON) { + } + + // Disable the PLL, wait until disabled + stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON) + for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { + } + + // Configure the PLL + stm32.RCC.PLLCFGR.ReplaceBits( + (1)| // 1 = RCC_PLLSOURCE_MSI + (PLL_M-1)<>1)-1)<>1)-1)<> stm32.RCC_CR_MSIRANGE_Pos + } + + return (stm32.RCC.CSR.Get() & stm32.RCC_CSR_MSISRANGE_Msk) >> stm32.RCC_CSR_MSISRANGE_Pos +} + +func setMSIFreq(r uint32, calibration uint32) { + stm32.RCC.CR.SetBits(stm32.RCC_CR_MSIRGSEL) + stm32.RCC.CR.ReplaceBits(r< stm32.RCC_CR_MSIRANGE_Range16M { + if r > stm32.RCC_CR_MSIRANGE_Range32M { + latency = FLASH_LATENCY_2 + } else { + latency = FLASH_LATENCY_1 + } + } + } else if r > stm32.RCC_CR_MSIRANGE_Range16M { + latency = FLASH_LATENCY_3 + } else { + if r == stm32.RCC_CR_MSIRANGE_Range16M { + latency = FLASH_LATENCY_2 + } else if r == stm32.RCC_CR_MSIRANGE_Range8M { + latency = FLASH_LATENCY_1 + } + } + + stm32.FLASH.ACR.ReplaceBits(latency, stm32.Flash_ACR_LATENCY_Msk, 0) +} + +func pwrIsClkEnabled() bool { + return stm32.RCC.APB1ENR1.HasBits(stm32.RCC_APB1ENR1_PWREN) +} + +func pwrClkEnable() { + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN) +} +func pwrClkDisable() { + stm32.RCC.APB1ENR1.ClearBits(stm32.RCC_APB1ENR1_PWREN) +} + +func pwrExGetVoltageRange() uint32 { + return stm32.PWR.CR1.Get() & stm32.PWR_CR1_VOS_Msk +} + //---------- UART related code // Configure the UART. diff --git a/src/machine/machine_stm32l5x2.go b/src/machine/machine_stm32l5x2.go index e00970f459..ea047137d3 100644 --- a/src/machine/machine_stm32l5x2.go +++ b/src/machine/machine_stm32l5x2.go @@ -12,6 +12,157 @@ func CPUFrequency() uint32 { return 110000000 } +//---------- Clock and Oscillator related code + +/* + clock settings + +-------------+-----------+ + | LSE | 32.768khz | + | SYSCLK | 110mhz | + | HCLK | 110mhz | + | APB1(PCLK1) | 110mhz | + | APB2(PCLK2) | 110mhz | + +-------------+-----------+ +*/ +const ( + HSE_STARTUP_TIMEOUT = 0x0500 + PLL_M = 1 + PLL_N = 55 + PLL_P = 7 // RCC_PLLP_DIV7 + PLL_Q = 2 // RCC_PLLQ_DIV2 + PLL_R = 2 // RCC_PLLR_DIV2 +) + +/* + timer settings used for tick and sleep. + + note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock + settings above, so must be kept in sync if the clock settings are changed. +*/ +const ( + TICK_RATE = 1000 // 1 KHz + SLEEP_TIMER_IRQ = stm32.IRQ_TIM15 + SLEEP_TIMER_FREQ = 110000000 // 110 MHz + TICK_TIMER_IRQ = stm32.IRQ_TIM16 + TICK_TIMER_FREQ = 110000000 // 110 MHz +) + +type arrtype = uint32 + +func InitializeClocks() { + initPLL() + + initSleepTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM15EN, + Device: stm32.TIM15, + }) + + initTickTimer(&timerInfo{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM16EN, + Device: stm32.TIM16, + }) +} + +func initPLL() { + + // PWR_CLK_ENABLE + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN) + _ = stm32.RCC.APB1ENR1.Get() + + // PWR_VOLTAGESCALING_CONFIG + stm32.PWR.CR1.ReplaceBits(0, stm32.PWR_CR1_VOS_Msk, 0) + _ = stm32.PWR.CR1.Get() + + // Initialize the High-Speed External Oscillator + initOsc() + + // Set flash wait states (min 5 latency units) based on clock + if (stm32.FLASH.ACR.Get() & 0xF) < 5 { + stm32.FLASH.ACR.ReplaceBits(5, 0xF, 0) + } + + // Ensure HCLK does not exceed max during transition + stm32.RCC.CFGR.ReplaceBits(8< 5 { + stm32.FLASH.ACR.ReplaceBits(5, 0xF, 0) + } + + // Set APB1 and APB2 clocks (0 = DIV1) + stm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE1_Msk, 0) + stm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE2_Msk, 0) +} + +func initOsc() { + // Enable HSI, wait until ready + stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION) + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) { + } + + // Disable Backup domain protection + if !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) { + stm32.PWR.CR1.SetBits(stm32.PWR_CR1_DBP) + for !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) { + } + } + + // Set LSE Drive to LOW + stm32.RCC.BDCR.ReplaceBits(0, stm32.RCC_BDCR_LSEDRV_Msk, 0) + + // Enable LSE, wait until ready + stm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_LSEON) + for !stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSEON) { + } + + // Ensure LSESYS disabled + stm32.RCC.BDCR.ClearBits(stm32.RCC_BDCR_LSESYSEN) + for stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSESYSEN) { + } + + // Enable HSI48, wait until ready + stm32.RCC.CRRCR.SetBits(stm32.RCC_CRRCR_HSI48ON) + for !stm32.RCC.CRRCR.HasBits(stm32.RCC_CRRCR_HSI48ON) { + } + + // Disable the PLL, wait until disabled + stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON) + for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { + } + + // Configure the PLL + stm32.RCC.PLLCFGR.ReplaceBits( + (1)| // 1 = RCC_PLLSOURCE_MSI + (PLL_M-1)<>1)-1)<>1)-1)<> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos - PLL_DIV_Q = 7 << stm32.RCC_PLLCFGR_PLLQ_Pos - - SYSCLK_SRC_PLL = stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos - SYSCLK_STAT_PLL = stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos - - RCC_DIV_PCLK1 = stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos // HCLK / 4 - RCC_DIV_PCLK2 = stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos // HCLK / 2 - RCC_DIV_HCLK = stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos // SYSCLK / 1 - - CLK_CCM_RAM = 1 << 20 -) - -const ( - // +-----------------------------------+ - // | Voltage range = 2.7V - 3.6V | - // +----------------+------------------+ - // | Wait states | System Bus | - // | (WS, LATENCY) | HCLK (MHz) | - // +----------------+------------------+ - // | 0 WS, 1 cycle | 0 < HCLK ≤ 30 | - // | 1 WS, 2 cycles | 30 < HCLK ≤ 60 | - // | 2 WS, 3 cycles | 60 < HCLK ≤ 90 | - // | 3 WS, 4 cycles | 90 < HCLK ≤ 120 | - // | 4 WS, 5 cycles | 120 < HCLK ≤ 150 | - // | 5 WS, 6 cycles | 150 < HCLK ≤ 168 | - // +----------------+------------------+ - FLASH_LATENCY = 5 << stm32.FLASH_ACR_LATENCY_Pos // 5 WS (6 CPU cycles) - - // instruction cache, data cache, and prefetch - FLASH_OPTIONS = stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | stm32.FLASH_ACR_PRFTEN -) - -/* - timer settings used for tick and sleep. - - note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock - settings above, so must be kept in sync if the clock settings are changed. -*/ -const ( - TICK_RATE = 1000 // 1 KHz - SLEEP_TIMER_IRQ = stm32.IRQ_TIM3 - SLEEP_TIMER_FREQ = PCLK1_FREQ_HZ * 2 - TICK_TIMER_IRQ = stm32.IRQ_TIM7 - TICK_TIMER_FREQ = PCLK1_FREQ_HZ * 2 -) - -type arrtype = uint32 - -const asyncScheduler = false - -func init() { - initOSC() // configure oscillators - initCLK() - - initSleepTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB1ENR, - EnableFlag: stm32.RCC_APB1ENR_TIM3EN, - Device: stm32.TIM3, - }) - - initCOM() - - initTickTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB1ENR, - EnableFlag: stm32.RCC_APB1ENR_TIM7EN, - Device: stm32.TIM7, - }) -} - -func initOSC() { - // enable voltage regulator - stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) - stm32.PWR.CR.SetBits(PWR_SCALE1) - - // enable HSE - stm32.RCC.CR.Set(stm32.RCC_CR_HSEON) - for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) { - } - - // Since the main-PLL configuration parameters cannot be changed once PLL is - // enabled, it is recommended to configure PLL before enabling it (selection - // of the HSI or HSE oscillator as PLL clock source, and configuration of - // division factors M, N, P, and Q). - - // disable PLL and wait for it to reset - stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON) - for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { - } - - // set HSE as PLL source and configure clock divisors - stm32.RCC.PLLCFGR.Set(PLL_SRC_HSE | PLL_DIV_M | PLL_MLT_N | PLL_DIV_P | PLL_DIV_Q) - - // enable PLL and wait for it to sync - stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) - for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { - } -} - -func initCLK() { - // After reset, the CPU clock frequency is 16 MHz and 0 wait state (WS) is - // configured in the FLASH_ACR register. - // - // It is highly recommended to use the following software sequences to tune - // the number of wait states needed to access the Flash memory with the CPU - // frequency. - // - // 1. Program the new number of wait states to the LATENCY bits in the - // FLASH_ACR register - // 2. Check that the new number of wait states is taken into account to access - // the Flash memory by reading the FLASH_ACR register - // 3. Modify the CPU clock source by writing the SW bits in the RCC_CFGR - // register - // 4. If needed, modify the CPU clock prescaler by writing the HPRE bits in - // RCC_CFGR - // 5. Check that the new CPU clock source or/and the new CPU clock prescaler - // value is/are taken into account by reading the clock source status (SWS - // bits) or/and the AHB prescaler value (HPRE bits), respectively, in the - // RCC_CFGR register. - - // configure instruction/data caching, prefetch, and flash access wait states - stm32.FLASH.ACR.Set(FLASH_OPTIONS | FLASH_LATENCY) - for !stm32.FLASH.ACR.HasBits(FLASH_LATENCY) { // verify new wait states - } - - // After a system reset, the HSI oscillator is selected as the system clock. - // When a clock source is used directly or through PLL as the system clock, it - // is not possible to stop it. - // - // A switch from one clock source to another occurs only if the target clock - // source is ready (clock stable after startup delay or PLL locked). If a - // clock source that is not yet ready is selected, the switch occurs when the - // clock source is ready. Status bits in the RCC clock control register - // (RCC_CR) indicate which clock(s) is (are) ready and which clock is - // currently used as the system clock. - - // set CPU clock source to PLL - stm32.RCC.CFGR.SetBits(SYSCLK_SRC_PLL) - - // update PCKL1/2 and HCLK divisors - stm32.RCC.CFGR.SetBits(RCC_DIV_PCLK1 | RCC_DIV_PCLK2 | RCC_DIV_HCLK) - - // verify system clock source is ready - for !stm32.RCC.CFGR.HasBits(SYSCLK_STAT_PLL) { - } - - // enable the CCM RAM clock - stm32.RCC.AHB1ENR.SetBits(CLK_CCM_RAM) -} - -func initCOM() { - if machine.NUM_UART_INTERFACES > 0 { - machine.UART0.Configure(machine.UARTConfig{}) - } -} - -func putchar(c byte) { - machine.UART0.WriteByte(c) -} diff --git a/src/runtime/runtime_stm32f407.go b/src/runtime/runtime_stm32f407.go deleted file mode 100644 index 5a30a81c29..0000000000 --- a/src/runtime/runtime_stm32f407.go +++ /dev/null @@ -1,135 +0,0 @@ -// +build stm32,stm32f407 - -package runtime - -import ( - "device/stm32" - "machine" -) - -/* - clock settings - +-------------+--------+ - | HSE | 8mhz | - | SYSCLK | 168mhz | - | HCLK | 168mhz | - | APB2(PCLK2) | 84mhz | - | APB1(PCLK1) | 42mhz | - +-------------+--------+ -*/ -const ( - HSE_STARTUP_TIMEOUT = 0x0500 - // PLL Options - See RM0090 Reference Manual pg. 95 - PLL_M = 8 // PLL_VCO = (HSE_VALUE or HSI_VLAUE / PLL_M) * PLL_N - PLL_N = 336 - PLL_P = 2 // SYSCLK = PLL_VCO / PLL_P - PLL_Q = 7 // USB OTS FS, SDIO and RNG Clock = PLL_VCO / PLL_Q -) - -/* - timer settings used for tick and sleep. - - note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock - settings above, so must be kept in sync if the clock settings are changed. -*/ -const ( - TICK_RATE = 1000 // 1 KHz - TICK_TIMER_IRQ = stm32.IRQ_TIM7 - TICK_TIMER_FREQ = 84000000 // 84 MHz - SLEEP_TIMER_IRQ = stm32.IRQ_TIM3 - SLEEP_TIMER_FREQ = 84000000 // 84 MHz -) - -type arrtype = uint32 - -const asyncScheduler = false - -func init() { - initCLK() - - initSleepTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB1ENR, - EnableFlag: stm32.RCC_APB1ENR_TIM3EN, - Device: stm32.TIM3, - }) - - machine.UART0.Configure(machine.UARTConfig{}) - - initTickTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB1ENR, - EnableFlag: stm32.RCC_APB1ENR_TIM7EN, - Device: stm32.TIM7, - }) -} - -func putchar(c byte) { - machine.UART0.WriteByte(c) -} - -func initCLK() { - // Reset clock registers - // Set HSION - stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION) - for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) { - } - - // Reset CFGR - stm32.RCC.CFGR.Set(0x00000000) - // Reset HSEON, CSSON and PLLON - stm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEON | stm32.RCC_CR_CSSON | stm32.RCC_CR_PLLON) - // Reset PLLCFGR - stm32.RCC.PLLCFGR.Set(0x24003010) - // Reset HSEBYP - stm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEBYP) - // Disable all interrupts - stm32.RCC.CIR.Set(0x00000000) - - // Set up the clock - var startupCounter uint32 = 0 - - // Enable HSE - stm32.RCC.CR.Set(stm32.RCC_CR_HSEON) - - // Wait till HSE is ready and if timeout is reached exit - for { - startupCounter++ - if stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) || (startupCounter == HSE_STARTUP_TIMEOUT) { - break - } - } - if stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) { - // Enable high performance mode, System frequency up to 168MHz - stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) - stm32.PWR.CR.SetBits(0x4000) // PWR_CR_VOS - // HCLK = SYSCLK / 1 - stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos) - // PCLK2 = HCLK / 2 - stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos) - // PCLK1 = HCLK / 4 - stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos) - // Configure the main PLL - // PLL Options - See RM0090 Reference Manual pg. 95 - stm32.RCC.PLLCFGR.Set(PLL_M | (PLL_N << 6) | (((PLL_P >> 1) - 1) << 16) | - (1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | (PLL_Q << 24)) - // Enable main PLL - stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) - // Wait till the main PLL is ready - for (stm32.RCC.CR.Get() & stm32.RCC_CR_PLLRDY) == 0 { - } - // Configure Flash prefetch, Instruction cache, Data cache and wait state - stm32.FLASH.ACR.Set(stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | (5 << stm32.FLASH_ACR_LATENCY_Pos)) - // Select the main PLL as system clock source - stm32.RCC.CFGR.ClearBits(stm32.RCC_CFGR_SW_Msk) - stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos) - for (stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk) != (stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) { - } - - } else { - // If HSE failed to start up, the application will have wrong clock configuration - for { - } - } - - // Enable the CCM RAM clock - stm32.RCC.AHB1ENR.SetBits(1 << 20) -} diff --git a/src/runtime/runtime_stm32f7x2.go b/src/runtime/runtime_stm32f7x2.go deleted file mode 100644 index a80c7e9217..0000000000 --- a/src/runtime/runtime_stm32f7x2.go +++ /dev/null @@ -1,130 +0,0 @@ -// +build stm32,stm32f7x2 - -package runtime - -import ( - "device/stm32" - "machine" -) - -/* - clock settings - +-------------+--------+ - | HSE | 8mhz | - | SYSCLK | 216mhz | - | HCLK | 216mhz | - | APB1(PCLK1) | 27mhz | - | APB2(PCLK2) | 108mhz | - +-------------+--------+ -*/ -const ( - HSE_STARTUP_TIMEOUT = 0x0500 - PLL_M = 4 - PLL_N = 216 - PLL_P = 2 - PLL_Q = 2 -) - -/* - timer settings used for tick and sleep. - - note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock - settings above, so must be kept in sync if the clock settings are changed. -*/ -const ( - TICK_RATE = 1000 // 1 KHz - SLEEP_TIMER_IRQ = stm32.IRQ_TIM3 - SLEEP_TIMER_FREQ = 54000000 // 54 MHz (2x APB1) - TICK_TIMER_IRQ = stm32.IRQ_TIM7 - TICK_TIMER_FREQ = 54000000 // 54 MHz (2x APB1) -) - -type arrtype = uint32 - -const asyncScheduler = false - -func init() { - initCLK() - - initSleepTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB1ENR, - EnableFlag: stm32.RCC_APB1ENR_TIM3EN, - Device: stm32.TIM3, - }) - - machine.UART0.Configure(machine.UARTConfig{}) - - initTickTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB1ENR, - EnableFlag: stm32.RCC_APB1ENR_TIM7EN, - Device: stm32.TIM7, - }) -} - -func putchar(c byte) { - machine.UART0.WriteByte(c) -} - -func initCLK() { - // PWR_CLK_ENABLE - stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) - _ = stm32.RCC.APB1ENR.Get() - - // PWR_VOLTAGESCALING_CONFIG - stm32.PWR.CR1.ReplaceBits(0x3< 7 { - stm32.FLASH.ACR.ReplaceBits(7, stm32.FLASH_ACR_LATENCY_Msk, 0) - } - - // Set APB1 and APB2 clocks (0x1800 = DIV8, 0x1000 = DIV2) - stm32.RCC.CFGR.ReplaceBits(0x1800, stm32.RCC_CFGR_PPRE1_Msk, 0) - stm32.RCC.CFGR.ReplaceBits(0x1000<<3, stm32.RCC_CFGR_PPRE2_Msk, 0) -} - -func initOsc() { - // Enable HSE, wait until ready - stm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON) - for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) { - } - - // Disable the PLL, wait until disabled - stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON) - for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { - } - - // Configure the PLL - stm32.RCC.PLLCFGR.Set(0x20000000 | - (1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | // 1 = HSE - PLL_M | - (PLL_N << stm32.RCC_PLLCFGR_PLLN_Pos) | - (((PLL_P >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos) | - (PLL_Q << stm32.RCC_PLLCFGR_PLLQ_Pos)) - - // Enable the PLL, wait until ready - stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) - for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { - } -} diff --git a/src/runtime/runtime_stm32l0.go b/src/runtime/runtime_stm32l0.go deleted file mode 100644 index c7045087bb..0000000000 --- a/src/runtime/runtime_stm32l0.go +++ /dev/null @@ -1,86 +0,0 @@ -// +build stm32l0 - -package runtime - -import ( - "device/stm32" - "machine" -) - -const ( - RCC_SYSCLK_DIV1 = 0 // Needs SVD update (should be stm32.RCC_SYSCLK_DIV1) -) - -type arrtype = uint16 - -const asyncScheduler = false - -func putchar(c byte) { - machine.UART0.WriteByte(c) -} - -func initCLK() { - // Set Power Regulator to enable max performance (1.8V) - stm32.PWR.CR.ReplaceBits(1< getFlashLatency() { - setFlashLatency(FlashLatency) - for getFlashLatency() != FlashLatency { - } - } - - // HCLK - stm32.RCC.CFGR.ReplaceBits(RCC_SYSCLK_DIV1, stm32.RCC_CFGR_HPRE_Msk, 0) - - // Use PLL As System clock - stm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_SWS_PLL, stm32.RCC_CFGR_SW_Msk, 0) - for stm32.RCC.CFGR.Get()&stm32.RCC_CFGR_SW_Msk != stm32.RCC_CFGR_SWS_PLL { - } - - // Set prescalers so half system clock (PCLKx = HCLK/2) - stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos) - stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos) -} - -func getFlashLatency() uint32 { - return stm32.FLASH.ACR.Get() & stm32.Flash_ACR_LATENCY_Msk -} - -func setFlashLatency(l uint32) { - stm32.FLASH.ACR.ReplaceBits(l, stm32.Flash_ACR_LATENCY_Msk, 0) -} diff --git a/src/runtime/runtime_stm32l0x1.go b/src/runtime/runtime_stm32l0x1.go deleted file mode 100644 index 1d48388e8d..0000000000 --- a/src/runtime/runtime_stm32l0x1.go +++ /dev/null @@ -1,44 +0,0 @@ -// +build stm32l0x1 - -package runtime - -import ( - "device/stm32" - "machine" -) - -/* - timer settings used for tick and sleep. - - note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock - settings, so must be kept in sync if the clock settings are changed. -*/ -const ( - TICK_RATE = 1000 // 1 KHz - TICK_TIMER_IRQ = stm32.IRQ_TIM21 - TICK_TIMER_FREQ = 32000000 // 32 MHz - SLEEP_TIMER_IRQ = stm32.IRQ_TIM22 - SLEEP_TIMER_FREQ = 32000000 // 32 MHz -) - -const ( - FlashLatency = stm32.Flash_ACR_LATENCY_WS1 -) - -func init() { - initCLK() - - initSleepTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB2ENR, - EnableFlag: stm32.RCC_APB2ENR_TIM22EN, - Device: stm32.TIM22, - }) - - machine.UART0.Configure(machine.UARTConfig{}) - - initTickTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB2ENR, - EnableFlag: stm32.RCC_APB2ENR_TIM21EN, - Device: stm32.TIM21, - }) -} diff --git a/src/runtime/runtime_stm32l0x2.go b/src/runtime/runtime_stm32l0x2.go deleted file mode 100644 index 6eccf0eb6c..0000000000 --- a/src/runtime/runtime_stm32l0x2.go +++ /dev/null @@ -1,44 +0,0 @@ -// +build stm32l0x2 - -package runtime - -import ( - "device/stm32" - "machine" -) - -/* - timer settings used for tick and sleep. - - note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock - settings, so must be kept in sync if the clock settings are changed. -*/ -const ( - TICK_RATE = 1000 // 1 KHz - TICK_TIMER_IRQ = stm32.IRQ_TIM7 - TICK_TIMER_FREQ = 32000000 // 32 MHz - SLEEP_TIMER_IRQ = stm32.IRQ_TIM3 - SLEEP_TIMER_FREQ = 32000000 // 32 MHz -) - -const ( - FlashLatency = stm32.Flash_ACR_LATENCY_WS1 -) - -func init() { - initCLK() - - initSleepTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB1ENR, - EnableFlag: stm32.RCC_APB1ENR_TIM3EN, - Device: stm32.TIM3, - }) - - machine.UART0.Configure(machine.UARTConfig{}) - - initTickTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB1ENR, - EnableFlag: stm32.RCC_APB1ENR_TIM7EN, - Device: stm32.TIM7, - }) -} diff --git a/src/runtime/runtime_stm32l4x2.go b/src/runtime/runtime_stm32l4x2.go deleted file mode 100644 index 5a6eb1ad94..0000000000 --- a/src/runtime/runtime_stm32l4x2.go +++ /dev/null @@ -1,262 +0,0 @@ -// +build stm32,stm32l4x2 - -package runtime - -import ( - "device/stm32" - "machine" -) - -/* - clock settings - +-------------+-----------+ - | LSE | 32.768khz | - | SYSCLK | 80mhz | - | HCLK | 80mhz | - | APB1(PCLK1) | 80mhz | - | APB2(PCLK2) | 80mhz | - +-------------+-----------+ -*/ -const ( - HSE_STARTUP_TIMEOUT = 0x0500 - PLL_M = 1 - PLL_N = 40 - PLL_P = RCC_PLLP_DIV7 - PLL_Q = RCC_PLLQ_DIV2 - PLL_R = RCC_PLLR_DIV2 - - MSIRANGE = stm32.RCC_CR_MSIRANGE_Range4M - - PWR_CR1_VOS_0 = 1 << stm32.PWR_CR1_VOS_Pos - PWR_CR1_VOS_1 = 2 << stm32.PWR_CR1_VOS_Pos - PWR_REGULATOR_VOLTAGE_SCALE1 = PWR_CR1_VOS_0 - PWR_REGULATOR_VOLTAGE_SCALE2 = PWR_CR1_VOS_1 - - FLASH_LATENCY_0 = 0 - FLASH_LATENCY_1 = 1 - FLASH_LATENCY_2 = 2 - FLASH_LATENCY_3 = 3 - FLASH_LATENCY_4 = 4 - - RCC_PLLP_DIV7 = 7 - RCC_PLLQ_DIV2 = 2 - RCC_PLLR_DIV2 = 2 - - RCC_CFGR_SWS_MSI = 0x0 - RCC_CFGR_SWS_PLL = 0xC - - RCC_PLLSOURCE_MSI = 1 - - RCC_PLL_SYSCLK = stm32.RCC_PLLCFGR_PLLREN -) - -/* - timer settings used for tick and sleep. - - note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock - settings above, so must be kept in sync if the clock settings are changed. -*/ -const ( - TICK_RATE = 1000 // 1 KHz - TICK_TIMER_IRQ = stm32.IRQ_TIM1_UP_TIM16 - TICK_TIMER_FREQ = 80000000 // 80 MHz - SLEEP_TIMER_IRQ = stm32.IRQ_TIM1_BRK_TIM15 - SLEEP_TIMER_FREQ = 80000000 // 84 MHz -) - -type arrtype = uint32 - -const asyncScheduler = false - -func init() { - initCLK() - - initSleepTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB2ENR, - EnableFlag: stm32.RCC_APB2ENR_TIM15EN, - Device: stm32.TIM15, - }) - - machine.UART0.Configure(machine.UARTConfig{}) - - initTickTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB2ENR, - EnableFlag: stm32.RCC_APB2ENR_TIM16EN, - Device: stm32.TIM16, - }) -} - -func putchar(c byte) { - machine.UART0.WriteByte(c) -} - -func initCLK() { - // PWR_CLK_ENABLE - stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN) - _ = stm32.RCC.APB1ENR1.Get() - - // Disable Backup domain protection - if !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) { - stm32.PWR.CR1.SetBits(stm32.PWR_CR1_DBP) - for !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) { - } - } - - // Set LSE Drive to LOW - stm32.RCC.BDCR.ReplaceBits(0, stm32.RCC_BDCR_LSEDRV_Msk, 0) - - // Initialize the High-Speed External Oscillator - initOsc() - - // PWR_VOLTAGESCALING_CONFIG - stm32.PWR.CR1.ReplaceBits(0, stm32.PWR_CR1_VOS_Msk, 0) - _ = stm32.PWR.CR1.Get() - - // Set flash wait states (min 5 latency units) based on clock - if (stm32.FLASH.ACR.Get() & 0xF) < 5 { - stm32.FLASH.ACR.ReplaceBits(5, 0xF, 0) - } - - // Ensure HCLK does not exceed max during transition - stm32.RCC.CFGR.ReplaceBits(8< 5 { - stm32.FLASH.ACR.ReplaceBits(5, 0xF, 0) - } - - // Set APB1 and APB2 clocks (0 = DIV1) - stm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE1_Msk, 0) - stm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE2_Msk, 0) -} - -func initOsc() { - sysclkSource := stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk - pllConfig := stm32.RCC.PLLCFGR.Get() & stm32.RCC_PLLCFGR_PLLSRC_Msk - - // Enable MSI, adjusting flash latency - if sysclkSource == RCC_CFGR_SWS_MSI || - (sysclkSource == RCC_CFGR_SWS_PLL && pllConfig == RCC_PLLSOURCE_MSI) { - if MSIRANGE > getMSIRange() { - setFlashLatencyFromMSIRange(MSIRANGE) - - setMSIFreq(MSIRANGE, 0) - } else { - setMSIFreq(MSIRANGE, 0) - - if sysclkSource == RCC_CFGR_SWS_MSI { - setFlashLatencyFromMSIRange(MSIRANGE) - } - } - } else { - stm32.RCC.CR.SetBits(stm32.RCC_CR_MSION) - for !stm32.RCC.CR.HasBits(stm32.RCC_CR_MSIRDY) { - } - - setMSIFreq(MSIRANGE, 0) - } - - // Enable LSE, wait until ready - stm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_LSEON) - for !stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSEON) { - } - - // Disable the PLL, wait until disabled - stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON) - for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { - } - - // Configure the PLL - stm32.RCC.PLLCFGR.ReplaceBits( - (1)| // 1 = RCC_PLLSOURCE_MSI - (PLL_M-1)<>1)-1)<>1)-1)<> stm32.RCC_CR_MSIRANGE_Pos - } - - return (stm32.RCC.CSR.Get() & stm32.RCC_CSR_MSISRANGE_Msk) >> stm32.RCC_CSR_MSISRANGE_Pos -} - -func setMSIFreq(r uint32, calibration uint32) { - stm32.RCC.CR.SetBits(stm32.RCC_CR_MSIRGSEL) - stm32.RCC.CR.ReplaceBits(r< stm32.RCC_CR_MSIRANGE_Range16M { - if r > stm32.RCC_CR_MSIRANGE_Range32M { - latency = FLASH_LATENCY_2 - } else { - latency = FLASH_LATENCY_1 - } - } - } else if r > stm32.RCC_CR_MSIRANGE_Range16M { - latency = FLASH_LATENCY_3 - } else { - if r == stm32.RCC_CR_MSIRANGE_Range16M { - latency = FLASH_LATENCY_2 - } else if r == stm32.RCC_CR_MSIRANGE_Range8M { - latency = FLASH_LATENCY_1 - } - } - - stm32.FLASH.ACR.ReplaceBits(latency, stm32.Flash_ACR_LATENCY_Msk, 0) -} - -func pwrIsClkEnabled() bool { - return stm32.RCC.APB1ENR1.HasBits(stm32.RCC_APB1ENR1_PWREN) -} - -func pwrClkEnable() { - stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN) -} -func pwrClkDisable() { - stm32.RCC.APB1ENR1.ClearBits(stm32.RCC_APB1ENR1_PWREN) -} - -func pwrExGetVoltageRange() uint32 { - return stm32.PWR.CR1.Get() & stm32.PWR_CR1_VOS_Msk -} diff --git a/src/runtime/runtime_stm32l5x2.go b/src/runtime/runtime_stm32l5x2.go deleted file mode 100644 index 1bf9c7ee92..0000000000 --- a/src/runtime/runtime_stm32l5x2.go +++ /dev/null @@ -1,165 +0,0 @@ -// +build stm32,stm32l5x2 - -package runtime - -import ( - "device/stm32" - "machine" -) - -/* - clock settings - +-------------+-----------+ - | LSE | 32.768khz | - | SYSCLK | 110mhz | - | HCLK | 110mhz | - | APB1(PCLK1) | 110mhz | - | APB2(PCLK2) | 110mhz | - +-------------+-----------+ -*/ -const ( - HSE_STARTUP_TIMEOUT = 0x0500 - PLL_M = 1 - PLL_N = 55 - PLL_P = 7 // RCC_PLLP_DIV7 - PLL_Q = 2 // RCC_PLLQ_DIV2 - PLL_R = 2 // RCC_PLLR_DIV2 -) - -/* - timer settings used for tick and sleep. - - note: TICK_TIMER_FREQ and SLEEP_TIMER_FREQ are controlled by PLL / clock - settings above, so must be kept in sync if the clock settings are changed. -*/ -const ( - TICK_RATE = 1000 // 1 KHz - SLEEP_TIMER_IRQ = stm32.IRQ_TIM15 - SLEEP_TIMER_FREQ = 110000000 // 110 MHz - TICK_TIMER_IRQ = stm32.IRQ_TIM16 - TICK_TIMER_FREQ = 110000000 // 110 MHz -) - -type arrtype = uint32 - -const asyncScheduler = false - -func init() { - initCLK() - - initSleepTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB2ENR, - EnableFlag: stm32.RCC_APB2ENR_TIM15EN, - Device: stm32.TIM15, - }) - - machine.UART0.Configure(machine.UARTConfig{}) - - initTickTimer(&timerInfo{ - EnableRegister: &stm32.RCC.APB2ENR, - EnableFlag: stm32.RCC_APB2ENR_TIM16EN, - Device: stm32.TIM16, - }) -} - -func putchar(c byte) { - machine.UART0.WriteByte(c) -} - -func initCLK() { - - // PWR_CLK_ENABLE - stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN) - _ = stm32.RCC.APB1ENR1.Get() - - // PWR_VOLTAGESCALING_CONFIG - stm32.PWR.CR1.ReplaceBits(0, stm32.PWR_CR1_VOS_Msk, 0) - _ = stm32.PWR.CR1.Get() - - // Initialize the High-Speed External Oscillator - initOsc() - - // Set flash wait states (min 5 latency units) based on clock - if (stm32.FLASH.ACR.Get() & 0xF) < 5 { - stm32.FLASH.ACR.ReplaceBits(5, 0xF, 0) - } - - // Ensure HCLK does not exceed max during transition - stm32.RCC.CFGR.ReplaceBits(8< 5 { - stm32.FLASH.ACR.ReplaceBits(5, 0xF, 0) - } - - // Set APB1 and APB2 clocks (0 = DIV1) - stm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE1_Msk, 0) - stm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE2_Msk, 0) -} - -func initOsc() { - // Enable HSI, wait until ready - stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION) - for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) { - } - - // Disable Backup domain protection - if !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) { - stm32.PWR.CR1.SetBits(stm32.PWR_CR1_DBP) - for !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) { - } - } - - // Set LSE Drive to LOW - stm32.RCC.BDCR.ReplaceBits(0, stm32.RCC_BDCR_LSEDRV_Msk, 0) - - // Enable LSE, wait until ready - stm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_LSEON) - for !stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSEON) { - } - - // Ensure LSESYS disabled - stm32.RCC.BDCR.ClearBits(stm32.RCC_BDCR_LSESYSEN) - for stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSESYSEN) { - } - - // Enable HSI48, wait until ready - stm32.RCC.CRRCR.SetBits(stm32.RCC_CRRCR_HSI48ON) - for !stm32.RCC.CRRCR.HasBits(stm32.RCC_CRRCR_HSI48ON) { - } - - // Disable the PLL, wait until disabled - stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON) - for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) { - } - - // Configure the PLL - stm32.RCC.PLLCFGR.ReplaceBits( - (1)| // 1 = RCC_PLLSOURCE_MSI - (PLL_M-1)<>1)-1)<>1)-1)<