github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/runtime_stm32f4.go (about)

     1  //go:build stm32f4 && (stm32f407 || stm32f469)
     2  
     3  package runtime
     4  
     5  import (
     6  	"device/stm32"
     7  	"machine"
     8  )
     9  
    10  func init() {
    11  	initCLK()
    12  
    13  	machine.InitSerial()
    14  
    15  	initTickTimer(&machine.TIM2)
    16  }
    17  
    18  func putchar(c byte) {
    19  	machine.Serial.WriteByte(c)
    20  }
    21  
    22  func getchar() byte {
    23  	for machine.Serial.Buffered() == 0 {
    24  		Gosched()
    25  	}
    26  	v, _ := machine.Serial.ReadByte()
    27  	return v
    28  }
    29  
    30  func buffered() int {
    31  	return machine.Serial.Buffered()
    32  }
    33  
    34  func initCLK() {
    35  	// Reset clock registers
    36  	// Set HSION
    37  	stm32.RCC.CR.SetBits(stm32.RCC_CR_HSION)
    38  	for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) {
    39  	}
    40  
    41  	// Reset CFGR
    42  	stm32.RCC.CFGR.Set(0x00000000)
    43  	// Reset HSEON, CSSON and PLLON
    44  	stm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEON | stm32.RCC_CR_CSSON | stm32.RCC_CR_PLLON)
    45  	// Reset PLLCFGR
    46  	stm32.RCC.PLLCFGR.Set(0x24003010)
    47  	// Reset HSEBYP
    48  	stm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEBYP)
    49  	// Disable all interrupts
    50  	stm32.RCC.CIR.Set(0x00000000)
    51  
    52  	// Set up the clock
    53  	var startupCounter uint32 = 0
    54  
    55  	// Enable HSE
    56  	stm32.RCC.CR.Set(stm32.RCC_CR_HSEON)
    57  
    58  	// Wait till HSE is ready and if timeout is reached exit
    59  	for {
    60  		startupCounter++
    61  		if stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) || (startupCounter == HSE_STARTUP_TIMEOUT) {
    62  			break
    63  		}
    64  	}
    65  	if stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {
    66  		// Enable high performance mode, configure maximum system frequency.
    67  		stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
    68  		stm32.PWR.CR.SetBits(0x4000) // PWR_CR_VOS
    69  		// HCLK = SYSCLK / 1
    70  		stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos)
    71  		// PCLK2 = HCLK / 2
    72  		stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos)
    73  		// PCLK1 = HCLK / 4
    74  		stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos)
    75  		// Configure the main PLL
    76  		stm32.RCC.PLLCFGR.Set(PLL_CFGR)
    77  		// Enable main PLL
    78  		stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)
    79  		// Wait till the main PLL is ready
    80  		for (stm32.RCC.CR.Get() & stm32.RCC_CR_PLLRDY) == 0 {
    81  		}
    82  		// Configure Flash prefetch, Instruction cache, Data cache and wait state
    83  		stm32.FLASH.ACR.Set(stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | (5 << stm32.FLASH_ACR_LATENCY_Pos))
    84  		// Select the main PLL as system clock source
    85  		stm32.RCC.CFGR.ClearBits(stm32.RCC_CFGR_SW_Msk)
    86  		stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos)
    87  		for (stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk) != (stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) {
    88  		}
    89  
    90  	} else {
    91  		// If HSE failed to start up, the application will have wrong clock configuration
    92  		for {
    93  		}
    94  	}
    95  
    96  	// Enable the CCM RAM clock
    97  	stm32.RCC.AHB1ENR.SetBits(1 << 20)
    98  }