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

     1  //go:build stm32f405
     2  
     3  package runtime
     4  
     5  import (
     6  	"device/stm32"
     7  	"machine"
     8  )
     9  
    10  const (
    11  	// +----------------------+
    12  	// |    Clock Settings    |
    13  	// +-------------+--------+
    14  	// | HSE         | 12mhz  |
    15  	// | SYSCLK      | 168mhz |
    16  	// | HCLK        | 168mhz |
    17  	// | APB1(PCLK1) | 42mhz  |
    18  	// | APB2(PCLK2) | 84mhz  |
    19  	// +-------------+--------+
    20  	HCLK_FREQ_HZ  = 168000000
    21  	PCLK1_FREQ_HZ = HCLK_FREQ_HZ / 4
    22  	PCLK2_FREQ_HZ = HCLK_FREQ_HZ / 2
    23  )
    24  
    25  const (
    26  	PWR_SCALE1 = 1 << stm32.PWR_CSR_VOSRDY_Pos // max value of HCLK = 168 MHz
    27  	PWR_SCALE2 = 0                             // max value of HCLK = 144 MHz
    28  
    29  	PLL_SRC_HSE = 1 << stm32.RCC_PLLCFGR_PLLSRC_Pos // use HSE for PLL and PLLI2S
    30  	PLL_SRC_HSI = 0                                 // use HSI for PLL and PLLI2S
    31  
    32  	PLL_DIV_M = 6 << stm32.RCC_PLLCFGR_PLLM_Pos
    33  	PLL_MLT_N = 168 << stm32.RCC_PLLCFGR_PLLN_Pos
    34  	PLL_DIV_P = ((2 >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos
    35  	PLL_DIV_Q = 7 << stm32.RCC_PLLCFGR_PLLQ_Pos
    36  
    37  	SYSCLK_SRC_PLL  = stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos
    38  	SYSCLK_STAT_PLL = stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos
    39  
    40  	RCC_DIV_PCLK1 = stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos // HCLK / 4
    41  	RCC_DIV_PCLK2 = stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos // HCLK / 2
    42  	RCC_DIV_HCLK  = stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos   // SYSCLK / 1
    43  
    44  	CLK_CCM_RAM = 1 << 20
    45  )
    46  
    47  const (
    48  	// +-----------------------------------+
    49  	// |    Voltage range = 2.7V - 3.6V    |
    50  	// +----------------+------------------+
    51  	// |   Wait states  |    System Bus    |
    52  	// |  (WS, LATENCY) |    HCLK (MHz)    |
    53  	// +----------------+------------------+
    54  	// | 0 WS, 1 cycle  |   0 < HCLK ≤ 30  |
    55  	// | 1 WS, 2 cycles |  30 < HCLK ≤ 60  |
    56  	// | 2 WS, 3 cycles |  60 < HCLK ≤ 90  |
    57  	// | 3 WS, 4 cycles |  90 < HCLK ≤ 120 |
    58  	// | 4 WS, 5 cycles | 120 < HCLK ≤ 150 |
    59  	// | 5 WS, 6 cycles | 150 < HCLK ≤ 168 |
    60  	// +----------------+------------------+
    61  	FLASH_LATENCY = 5 << stm32.FLASH_ACR_LATENCY_Pos // 5 WS (6 CPU cycles)
    62  
    63  	// instruction cache, data cache, and prefetch
    64  	FLASH_OPTIONS = stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | stm32.FLASH_ACR_PRFTEN
    65  )
    66  
    67  func init() {
    68  	initOSC() // configure oscillators
    69  	initCLK()
    70  
    71  	initCOM()
    72  
    73  	initTickTimer(&machine.TIM3)
    74  }
    75  
    76  func initOSC() {
    77  	// enable voltage regulator
    78  	stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
    79  	stm32.PWR.CR.SetBits(PWR_SCALE1)
    80  
    81  	// enable HSE
    82  	stm32.RCC.CR.Set(stm32.RCC_CR_HSEON)
    83  	for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {
    84  	}
    85  
    86  	// Since the main-PLL configuration parameters cannot be changed once PLL is
    87  	// enabled, it is recommended to configure PLL before enabling it (selection
    88  	// of the HSI or HSE oscillator as PLL clock source, and configuration of
    89  	// division factors M, N, P, and Q).
    90  
    91  	// disable PLL and wait for it to reset
    92  	stm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)
    93  	for stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
    94  	}
    95  
    96  	// set HSE as PLL source and configure clock divisors
    97  	stm32.RCC.PLLCFGR.Set(PLL_SRC_HSE | PLL_DIV_M | PLL_MLT_N | PLL_DIV_P | PLL_DIV_Q)
    98  
    99  	// enable PLL and wait for it to sync
   100  	stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)
   101  	for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
   102  	}
   103  }
   104  
   105  func initCLK() {
   106  	// After reset, the CPU clock frequency is 16 MHz and 0 wait state (WS) is
   107  	// configured in the FLASH_ACR register.
   108  	//
   109  	// It is highly recommended to use the following software sequences to tune
   110  	// the number of wait states needed to access the Flash memory with the CPU
   111  	// frequency.
   112  	//
   113  	// 1. Program the new number of wait states to the LATENCY bits in the
   114  	//    FLASH_ACR register
   115  	// 2. Check that the new number of wait states is taken into account to access
   116  	//    the Flash memory by reading the FLASH_ACR register
   117  	// 3. Modify the CPU clock source by writing the SW bits in the RCC_CFGR
   118  	//    register
   119  	// 4. If needed, modify the CPU clock prescaler by writing the HPRE bits in
   120  	//    RCC_CFGR
   121  	// 5. Check that the new CPU clock source or/and the new CPU clock prescaler
   122  	//    value is/are taken into account by reading the clock source status (SWS
   123  	//    bits) or/and the AHB prescaler value (HPRE bits), respectively, in the
   124  	//    RCC_CFGR register.
   125  
   126  	// configure instruction/data caching, prefetch, and flash access wait states
   127  	stm32.FLASH.ACR.Set(FLASH_OPTIONS | FLASH_LATENCY)
   128  	for !stm32.FLASH.ACR.HasBits(FLASH_LATENCY) { // verify new wait states
   129  	}
   130  
   131  	// After a system reset, the HSI oscillator is selected as the system clock.
   132  	// When a clock source is used directly or through PLL as the system clock, it
   133  	// is not possible to stop it.
   134  	//
   135  	// A switch from one clock source to another occurs only if the target clock
   136  	// source is ready (clock stable after startup delay or PLL locked). If a
   137  	// clock source that is not yet ready is selected, the switch occurs when the
   138  	// clock source is ready. Status bits in the RCC clock control register
   139  	// (RCC_CR) indicate which clock(s) is (are) ready and which clock is
   140  	// currently used as the system clock.
   141  
   142  	// set CPU clock source to PLL
   143  	stm32.RCC.CFGR.SetBits(SYSCLK_SRC_PLL)
   144  
   145  	// update PCKL1/2 and HCLK divisors
   146  	stm32.RCC.CFGR.SetBits(RCC_DIV_PCLK1 | RCC_DIV_PCLK2 | RCC_DIV_HCLK)
   147  
   148  	// verify system clock source is ready
   149  	for !stm32.RCC.CFGR.HasBits(SYSCLK_STAT_PLL) {
   150  	}
   151  
   152  	// enable the CCM RAM clock
   153  	stm32.RCC.AHB1ENR.SetBits(CLK_CCM_RAM)
   154  }
   155  
   156  func initCOM() {
   157  	if machine.NUM_UART_INTERFACES > 0 {
   158  		machine.InitSerial()
   159  	}
   160  }
   161  
   162  func putchar(c byte) {
   163  	machine.Serial.WriteByte(c)
   164  }
   165  
   166  func getchar() byte {
   167  	for machine.Serial.Buffered() == 0 {
   168  		Gosched()
   169  	}
   170  	v, _ := machine.Serial.ReadByte()
   171  	return v
   172  }
   173  
   174  func buffered() int {
   175  	return machine.Serial.Buffered()
   176  }