runtime: separate runtime initialization for STM32F4 boards

The STM32F469 can use the same initialization as the existing STM32F407
with a few frequency tweaks. This change splits the generic
initialization code into a separate runtime_stm32f4.go file, leaving
only the 407 board specific constants in the existing
runtime_stm32f407.go file.

Note that runtime_stm32f405.go initialization seems semantically similar
to the 407, but I don't have enough confidence in merging 405 with 407
in this change.
Этот коммит содержится в:
Elias Naur 2021-12-28 19:47:23 +01:00 коммит произвёл kenbell
родитель 11ee0969b6
коммит 55ca5287fe
2 изменённых файлов: 97 добавлений и 89 удалений

88
src/runtime/runtime_stm32f4.go Обычный файл
Просмотреть файл

@ -0,0 +1,88 @@
//go:build stm32f4 && (stm32f407 || stm32f469)
// +build stm32f4
// +build stm32f407 stm32f469
package runtime
import (
"device/stm32"
"machine"
)
func init() {
initCLK()
machine.Serial.Configure(machine.UARTConfig{})
initTickTimer(&machine.TIM2)
}
func putchar(c byte) {
machine.Serial.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, configure maximum system frequency.
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
stm32.RCC.PLLCFGR.Set(PLL_CFGR)
// 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)
}

Просмотреть файл

@ -1,11 +1,9 @@
// +build stm32,stm32f407 //go:build stm32f4 && stm32f407
// +build stm32f4,stm32f407
package runtime package runtime
import ( import "device/stm32"
"device/stm32"
"machine"
)
/* /*
clock settings clock settings
@ -20,88 +18,10 @@ import (
const ( const (
HSE_STARTUP_TIMEOUT = 0x0500 HSE_STARTUP_TIMEOUT = 0x0500
// PLL Options - See RM0090 Reference Manual pg. 95 // PLL Options - See RM0090 Reference Manual pg. 95
PLL_M = 8 // PLL_VCO = (HSE_VALUE or HSI_VLAUE / PLL_M) * PLL_N PLL_M = 8 // PLL_VCO = (HSE_VALUE or HSI_VLAUE / PLL_M) * PLL_N
PLL_N = 336 PLL_N = 336
PLL_P = 2 // SYSCLK = PLL_VCO / PLL_P PLL_P = 2 // SYSCLK = PLL_VCO / PLL_P
PLL_Q = 7 // USB OTS FS, SDIO and RNG Clock = PLL_VCO / PLL_Q PLL_Q = 7 // USB OTS FS, SDIO and RNG Clock = PLL_VCO / PLL_Q
PLL_CFGR = PLL_M | (PLL_N << stm32.RCC_PLLCFGR_PLLN_Pos) | (((PLL_P >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos) |
(1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | (PLL_Q << stm32.RCC_PLLCFGR_PLLQ_Pos)
) )
func init() {
initCLK()
machine.Serial.Configure(machine.UARTConfig{})
initTickTimer(&machine.TIM2)
}
func putchar(c byte) {
machine.Serial.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)
}