github.com/aykevl/tinygo@v0.5.0/src/machine/machine_stm32f407.go (about) 1 // +build stm32,stm32f407 2 3 package machine 4 5 // Peripheral abstraction layer for the stm32. 6 7 import ( 8 "device/arm" 9 "device/stm32" 10 ) 11 12 const CPU_FREQUENCY = 168000000 13 14 const ( 15 // Mode Flag 16 GPIO_OUTPUT = 0 17 GPIO_INPUT = GPIO_INPUT_PULLDOWN 18 GPIO_INPUT_FLOATING = 1 19 GPIO_INPUT_PULLDOWN = 2 20 GPIO_INPUT_PULLUP = 3 21 22 // for UART 23 GPIO_UART_TX = 4 24 GPIO_UART_RX = 5 25 26 //GPIOx_MODER 27 GPIO_MODE_INPUT = 0 28 GPIO_MODE_GENERAL_OUTPUT = 1 29 GPIO_MODE_ALTERNABTIVE = 2 30 GPIO_MODE_ANALOG = 3 31 32 //GPIOx_OTYPER 33 GPIO_OUTPUT_MODE_PUSH_PULL = 0 34 GPIO_OUTPUT_MODE_OPEN_DRAIN = 1 35 36 // GPIOx_OSPEEDR 37 GPIO_SPEED_LOW = 0 38 GPIO_SPEED_MID = 1 39 GPIO_SPEED_HI = 2 40 GPIO_SPEED_VERY_HI = 3 41 42 // GPIOx_PUPDR 43 GPIO_FLOATING = 0 44 GPIO_PULL_UP = 1 45 GPIO_PULL_DOWN = 2 46 ) 47 48 func (p GPIO) getPort() *stm32.GPIO_Type { 49 switch p.Pin / 16 { 50 case 0: 51 return stm32.GPIOA 52 case 1: 53 return stm32.GPIOB 54 case 2: 55 return stm32.GPIOC 56 case 3: 57 return stm32.GPIOD 58 case 4: 59 return stm32.GPIOE 60 case 5: 61 return stm32.GPIOF 62 case 6: 63 return stm32.GPIOG 64 case 7: 65 return stm32.GPIOH 66 case 8: 67 return stm32.GPIOI 68 default: 69 panic("machine: unknown port") 70 } 71 } 72 73 // enableClock enables the clock for this desired GPIO port. 74 func (p GPIO) enableClock() { 75 switch p.Pin / 16 { 76 case 0: 77 stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOAEN 78 case 1: 79 stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOBEN 80 case 2: 81 stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOCEN 82 case 3: 83 stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIODEN 84 case 4: 85 stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOEEN 86 case 5: 87 stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOFEN 88 case 6: 89 stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOGEN 90 case 7: 91 stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOHEN 92 case 8: 93 stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOIEN 94 default: 95 panic("machine: unknown port") 96 } 97 } 98 99 // Configure this pin with the given configuration. 100 func (p GPIO) Configure(config GPIOConfig) { 101 // Configure the GPIO pin. 102 p.enableClock() 103 port := p.getPort() 104 pin := p.Pin % 16 105 pos := pin * 2 106 107 if config.Mode == GPIO_INPUT_FLOATING { 108 port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos))) 109 port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos))) 110 } else if config.Mode == GPIO_INPUT_PULLDOWN { 111 port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos))) 112 port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_DOWN) << pos))) 113 } else if config.Mode == GPIO_INPUT_PULLUP { 114 port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos))) 115 port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos))) 116 } else if config.Mode == GPIO_OUTPUT { 117 port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_GENERAL_OUTPUT) << pos))) 118 port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos))) 119 } else if config.Mode == GPIO_UART_TX { 120 port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos))) 121 port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos))) 122 port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos))) 123 p.setAltFunc(0x7) 124 } else if config.Mode == GPIO_UART_RX { 125 port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos))) 126 port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos))) 127 p.setAltFunc(0x7) 128 } 129 } 130 131 func (p GPIO) setAltFunc(af uint32) { 132 port := p.getPort() 133 pin := p.Pin % 16 134 pos := pin * 4 135 if pin >= 8 { 136 port.AFRH = stm32.RegValue(uint32(port.AFRH)&^(0xF<<pos) | ((af & 0xF) << pos)) 137 } else { 138 port.AFRL = stm32.RegValue(uint32(port.AFRL)&^(0xF<<pos) | ((af & 0xF) << pos)) 139 } 140 } 141 142 // Set the pin to high or low. 143 // Warning: only use this on an output pin! 144 func (p GPIO) Set(high bool) { 145 port := p.getPort() 146 pin := p.Pin % 16 147 if high { 148 port.BSRR = 1 << pin 149 } else { 150 port.BSRR = 1 << (pin + 16) 151 } 152 } 153 154 // UART 155 type UART struct { 156 Buffer *RingBuffer 157 } 158 159 var ( 160 // Both UART0 and UART1 refer to USART2. 161 UART0 = UART{Buffer: NewRingBuffer()} 162 UART1 = &UART0 163 ) 164 165 // Configure the UART. 166 func (uart UART) Configure(config UARTConfig) { 167 // Default baud rate to 115200. 168 if config.BaudRate == 0 { 169 config.BaudRate = 115200 170 } 171 172 // pins 173 switch config.TX { 174 default: 175 // use standard TX/RX pins PA2 and PA3 176 GPIO{UART_TX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_TX}) 177 GPIO{UART_RX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_RX}) 178 } 179 180 // Enable USART2 clock 181 stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_USART2EN 182 183 /* 184 Set baud rate(115200) 185 OVER8 = 0, APB2 = 42mhz 186 +----------+--------+ 187 | baudrate | BRR | 188 +----------+--------+ 189 | 1200 | 0x88B8 | 190 | 2400 | 0x445C | 191 | 9600 | 0x1117 | 192 | 19200 | 0x88C | 193 | 38400 | 0x446 | 194 | 57600 | 0x2D9 | 195 | 115200 | 0x16D | 196 +----------+--------+ 197 */ 198 stm32.USART2.BRR = 0x16c 199 200 // Enable USART2 port. 201 stm32.USART2.CR1 = stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE 202 203 // Enable RX IRQ. 204 arm.SetPriority(stm32.IRQ_USART2, 0xc0) 205 arm.EnableIRQ(stm32.IRQ_USART2) 206 } 207 208 // WriteByte writes a byte of data to the UART. 209 func (uart UART) WriteByte(c byte) error { 210 stm32.USART2.DR = stm32.RegValue(c) 211 212 for (stm32.USART2.SR & stm32.USART_SR_TXE) == 0 { 213 } 214 return nil 215 } 216 217 //go:export USART2_IRQHandler 218 func handleUSART2() { 219 UART1.Receive(byte((stm32.USART2.DR & 0xFF))) 220 }