github.com/aykevl/tinygo@v0.5.0/src/runtime/runtime_stm32f407.go (about)

     1  // +build stm32,stm32f407
     2  
     3  package runtime
     4  
     5  import (
     6  	"device/arm"
     7  	"device/stm32"
     8  	"machine"
     9  )
    10  
    11  func init() {
    12  	initCLK()
    13  	initTIM3()
    14  	machine.UART0.Configure(machine.UARTConfig{})
    15  	initTIM7()
    16  }
    17  
    18  func putchar(c byte) {
    19  	machine.UART0.WriteByte(c)
    20  }
    21  
    22  const (
    23  	HSE_STARTUP_TIMEOUT = 0x0500
    24  	/* PLL Options - See RM0090 Reference Manual pg. 95 */
    25  	PLL_M = 8 /* PLL_VCO = (HSE_VALUE or HSI_VLAUE / PLL_M) * PLL_N */
    26  	PLL_N = 336
    27  	PLL_P = 2 /* SYSCLK = PLL_VCO / PLL_P */
    28  	PLL_Q = 7 /* USB OTS FS, SDIO and RNG Clock = PLL_VCO / PLL_Q */
    29  )
    30  
    31  /*
    32     clock settings
    33     +-------------+--------+
    34     | HSE         | 8mhz   |
    35     | SYSCLK      | 168mhz |
    36     | HCLK        | 168mhz |
    37     | APB2(PCLK2) | 84mhz  |
    38     | APB1(PCLK1) | 42mhz  |
    39     +-------------+--------+
    40  */
    41  func initCLK() {
    42  
    43  	// Reset clock registers
    44  	// Set HSION
    45  	stm32.RCC.CR |= stm32.RCC_CR_HSION
    46  	for (stm32.RCC.CR & stm32.RCC_CR_HSIRDY) == 0 {
    47  	}
    48  
    49  	// Reset CFGR
    50  	stm32.RCC.CFGR = 0x00000000
    51  	// Reset HSEON, CSSON and PLLON
    52  	stm32.RCC.CR &= 0xFEF6FFFF
    53  	// Reset PLLCFGR
    54  	stm32.RCC.PLLCFGR = 0x24003010
    55  	// Reset HSEBYP
    56  	stm32.RCC.CR &= 0xFFFBFFFF
    57  	// Disable all interrupts
    58  	stm32.RCC.CIR = 0x00000000
    59  
    60  	// Set up the clock
    61  	var startupCounter uint32 = 0
    62  
    63  	// Enable HSE
    64  	stm32.RCC.CR = stm32.RCC_CR_HSEON
    65  	// Wait till HSE is ready and if timeout is reached exit
    66  	for {
    67  		startupCounter++
    68  		if (stm32.RCC.CR&stm32.RCC_CR_HSERDY != 0) || (startupCounter == HSE_STARTUP_TIMEOUT) {
    69  			break
    70  		}
    71  	}
    72  	if (stm32.RCC.CR & stm32.RCC_CR_HSERDY) != 0 {
    73  		// Enable high performance mode, System frequency up to 168MHz
    74  		stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_PWREN
    75  		stm32.PWR.CR |= 0x4000 // PWR_CR_VOS
    76  		// HCLK = SYSCLK / 1
    77  		stm32.RCC.CFGR |= (0x0 << stm32.RCC_CFGR_HPRE_Pos)
    78  		// PCLK2 = HCLK / 2
    79  		stm32.RCC.CFGR |= (0x4 << stm32.RCC_CFGR_PPRE2_Pos)
    80  		// PCLK1 = HCLK / 4
    81  		stm32.RCC.CFGR |= (0x5 << stm32.RCC_CFGR_PPRE1_Pos)
    82  		// Configure the main PLL
    83  		// PLL Options - See RM0090 Reference Manual pg. 95
    84  		stm32.RCC.PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) - 1) << 16) |
    85  			(1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | (PLL_Q << 24)
    86  		// Enable main PLL
    87  		stm32.RCC.CR |= stm32.RCC_CR_PLLON
    88  		// Wait till the main PLL is ready
    89  		for (stm32.RCC.CR & stm32.RCC_CR_PLLRDY) == 0 {
    90  		}
    91  		// Configure Flash prefetch, Instruction cache, Data cache and wait state
    92  		stm32.FLASH.ACR = stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | (5 << stm32.FLASH_ACR_LATENCY_Pos)
    93  		// Select the main PLL as system clock source
    94  		stm32.RCC.CFGR &^= stm32.RCC_CFGR_SW0 | stm32.RCC_CFGR_SW1
    95  		stm32.RCC.CFGR |= (0x2 << stm32.RCC_CFGR_SW0_Pos)
    96  		for (stm32.RCC.CFGR & (0x3 << stm32.RCC_CFGR_SWS0_Pos)) != (0x2 << stm32.RCC_CFGR_SWS0_Pos) {
    97  		}
    98  
    99  	} else {
   100  		// If HSE failed to start up, the application will have wrong clock configuration
   101  		for {
   102  		}
   103  	}
   104  	// Enable the CCM RAM clock
   105  	stm32.RCC.AHB1ENR |= (1 << 20)
   106  
   107  }
   108  
   109  const tickMicros = 1000
   110  
   111  var (
   112  	// tick in milliseconds
   113  	tickCount timeUnit
   114  )
   115  
   116  //go:volatile
   117  type isrFlag bool
   118  
   119  var timerWakeup isrFlag
   120  
   121  // Enable the TIM3 clock.(sleep count)
   122  func initTIM3() {
   123  	stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_TIM3EN
   124  
   125  	arm.SetPriority(stm32.IRQ_TIM3, 0xc3)
   126  	arm.EnableIRQ(stm32.IRQ_TIM3)
   127  }
   128  
   129  // Enable the TIM7 clock.(tick count)
   130  func initTIM7() {
   131  	stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_TIM7EN
   132  
   133  	// CK_INT = APB1 x2 = 84mhz
   134  	stm32.TIM7.PSC = 84000000/10000 - 1     // 84mhz to 10khz(0.1ms)
   135  	stm32.TIM7.ARR = stm32.RegValue(10) - 1 // interrupt per 1ms
   136  
   137  	// Enable the hardware interrupt.
   138  	stm32.TIM7.DIER |= stm32.TIM_DIER_UIE
   139  
   140  	// Enable the timer.
   141  	stm32.TIM7.CR1 |= stm32.TIM_CR1_CEN
   142  
   143  	arm.SetPriority(stm32.IRQ_TIM7, 0xc1)
   144  	arm.EnableIRQ(stm32.IRQ_TIM7)
   145  }
   146  
   147  const asyncScheduler = false
   148  
   149  // sleepTicks should sleep for specific number of microseconds.
   150  func sleepTicks(d timeUnit) {
   151  	timerSleep(uint32(d))
   152  }
   153  
   154  // number of ticks (microseconds) since start.
   155  func ticks() timeUnit {
   156  	// milliseconds to microseconds
   157  	return tickCount * 1000
   158  }
   159  
   160  // ticks are in microseconds
   161  func timerSleep(ticks uint32) {
   162  	timerWakeup = false
   163  
   164  	// CK_INT = APB1 x2 = 84mhz
   165  	// prescale counter down from 84mhz to 10khz aka 0.1 ms frequency.
   166  	stm32.TIM3.PSC = 84000000/10000 - 1 // 8399
   167  
   168  	// set duty aka duration
   169  	arr := (ticks / 100) - 1 // convert from microseconds to 0.1 ms
   170  	if arr == 0 {
   171  		arr = 1 // avoid blocking
   172  	}
   173  	stm32.TIM3.ARR = stm32.RegValue(arr)
   174  
   175  	// Enable the hardware interrupt.
   176  	stm32.TIM3.DIER |= stm32.TIM_DIER_UIE
   177  
   178  	// Enable the timer.
   179  	stm32.TIM3.CR1 |= stm32.TIM_CR1_CEN
   180  
   181  	// wait till timer wakes up
   182  	for !timerWakeup {
   183  		arm.Asm("wfi")
   184  	}
   185  }
   186  
   187  //go:export TIM3_IRQHandler
   188  func handleTIM3() {
   189  	if (stm32.TIM3.SR & stm32.TIM_SR_UIF) > 0 {
   190  		// Disable the timer.
   191  		stm32.TIM3.CR1 &^= stm32.TIM_CR1_CEN
   192  
   193  		// clear the update flag
   194  		stm32.TIM3.SR &^= stm32.TIM_SR_UIF
   195  
   196  		// timer was triggered
   197  		timerWakeup = true
   198  	}
   199  }
   200  
   201  //go:export TIM7_IRQHandler
   202  func handleTIM7() {
   203  	if (stm32.TIM7.SR & stm32.TIM_SR_UIF) > 0 {
   204  		// clear the update flag
   205  		stm32.TIM7.SR &^= stm32.TIM_SR_UIF
   206  		tickCount++
   207  	}
   208  }