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 }