stm32: add support for the STM32F4Discovery

Signed-off-by: Yusuke Mitsuki <mickey.happygolucky@gmail.com>
This commit is contained in:
Yusuke Mitsuki
2019-04-12 13:36:14 +09:00
committed by Ayke van Laethem
parent 315cd4059f
commit 1322f404a6
7 changed files with 571 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
// +build stm32,stm32f4disco
package machine
const (
PA0 = portA + 0
PA1 = portA + 1
PA2 = portA + 2
PA3 = portA + 3
PA4 = portA + 4
PA5 = portA + 5
PA6 = portA + 6
PA7 = portA + 7
PA8 = portA + 8
PA9 = portA + 9
PA10 = portA + 10
PA11 = portA + 11
PA12 = portA + 12
PA13 = portA + 13
PA14 = portA + 14
PA15 = portA + 15
PB0 = portB + 0
PB1 = portB + 1
PB2 = portB + 2
PB3 = portB + 3
PB4 = portB + 4
PB5 = portB + 5
PB6 = portB + 6
PB7 = portB + 7
PB8 = portB + 8
PB9 = portB + 9
PB10 = portB + 10
PB11 = portB + 11
PB12 = portB + 12
PB13 = portB + 13
PB14 = portB + 14
PB15 = portB + 15
PC0 = portC + 0
PC1 = portC + 1
PC2 = portC + 2
PC3 = portC + 3
PC4 = portC + 4
PC5 = portC + 5
PC6 = portC + 6
PC7 = portC + 7
PC8 = portC + 8
PC9 = portC + 9
PC10 = portC + 10
PC11 = portC + 11
PC12 = portC + 12
PC13 = portC + 13
PC14 = portC + 14
PC15 = portC + 15
PD0 = portD + 0
PD1 = portD + 1
PD2 = portD + 2
PD3 = portD + 3
PD4 = portD + 4
PD5 = portD + 5
PD6 = portD + 6
PD7 = portD + 7
PD8 = portD + 8
PD9 = portD + 9
PD10 = portD + 10
PD11 = portD + 11
PD12 = portD + 12
PD13 = portD + 13
PD14 = portD + 14
PD15 = portD + 15
PE0 = portE + 0
PE1 = portE + 1
PE2 = portE + 2
PE3 = portE + 3
PE4 = portE + 4
PE5 = portE + 5
PE6 = portE + 6
PE7 = portE + 7
PE8 = portE + 8
PE9 = portE + 9
PE10 = portE + 10
PE11 = portE + 11
PE12 = portE + 12
PE13 = portE + 13
PE14 = portE + 14
PE15 = portE + 15
PH0 = portH + 0
PH1 = portH + 1
)
const (
LED = LED_BUILTIN
LED1 = LED_GREEN
LED2 = LED_ORANGE
LED3 = LED_RED
LED4 = LED_BLUE
LED_BUILTIN = LED_GREEN
LED_GREEN = PD12
LED_ORANGE = PD13
LED_RED = PD14
LED_BLUE = PD15
)
// UART pins
const (
UART_TX_PIN = PA2
UART_RX_PIN = PA3
)
+1
View File
@@ -14,4 +14,5 @@ const (
portE
portF
portG
portH
)
+220
View File
@@ -0,0 +1,220 @@
// +build stm32,stm32f407
package machine
// Peripheral abstraction layer for the stm32.
import (
"device/arm"
"device/stm32"
)
const CPU_FREQUENCY = 168000000
const (
// Mode Flag
GPIO_OUTPUT = 0
GPIO_INPUT = GPIO_INPUT_PULLDOWN
GPIO_INPUT_FLOATING = 1
GPIO_INPUT_PULLDOWN = 2
GPIO_INPUT_PULLUP = 3
// for UART
GPIO_UART_TX = 4
GPIO_UART_RX = 5
//GPIOx_MODER
GPIO_MODE_INPUT = 0
GPIO_MODE_GENERAL_OUTPUT = 1
GPIO_MODE_ALTERNABTIVE = 2
GPIO_MODE_ANALOG = 3
//GPIOx_OTYPER
GPIO_OUTPUT_MODE_PUSH_PULL = 0
GPIO_OUTPUT_MODE_OPEN_DRAIN = 1
// GPIOx_OSPEEDR
GPIO_SPEED_LOW = 0
GPIO_SPEED_MID = 1
GPIO_SPEED_HI = 2
GPIO_SPEED_VERY_HI = 3
// GPIOx_PUPDR
GPIO_FLOATING = 0
GPIO_PULL_UP = 1
GPIO_PULL_DOWN = 2
)
func (p GPIO) getPort() *stm32.GPIO_Type {
switch p.Pin / 16 {
case 0:
return stm32.GPIOA
case 1:
return stm32.GPIOB
case 2:
return stm32.GPIOC
case 3:
return stm32.GPIOD
case 4:
return stm32.GPIOE
case 5:
return stm32.GPIOF
case 6:
return stm32.GPIOG
case 7:
return stm32.GPIOH
case 8:
return stm32.GPIOI
default:
panic("machine: unknown port")
}
}
// enableClock enables the clock for this desired GPIO port.
func (p GPIO) enableClock() {
switch p.Pin / 16 {
case 0:
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOAEN
case 1:
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOBEN
case 2:
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOCEN
case 3:
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIODEN
case 4:
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOEEN
case 5:
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOFEN
case 6:
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOGEN
case 7:
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOHEN
case 8:
stm32.RCC.AHB1ENR |= stm32.RCC_AHB1ENR_GPIOIEN
default:
panic("machine: unknown port")
}
}
// Configure this pin with the given configuration.
func (p GPIO) Configure(config GPIOConfig) {
// Configure the GPIO pin.
p.enableClock()
port := p.getPort()
pin := p.Pin % 16
pos := pin * 2
if config.Mode == GPIO_INPUT_FLOATING {
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos)))
} else if config.Mode == GPIO_INPUT_PULLDOWN {
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_DOWN) << pos)))
} else if config.Mode == GPIO_INPUT_PULLUP {
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos)))
} else if config.Mode == GPIO_OUTPUT {
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_GENERAL_OUTPUT) << pos)))
port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos)))
} else if config.Mode == GPIO_UART_TX {
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos)))
port.OSPEEDR = stm32.RegValue((uint32(port.OSPEEDR)&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos)))
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos)))
p.setAltFunc(0x7)
} else if config.Mode == GPIO_UART_RX {
port.MODER = stm32.RegValue((uint32(port.MODER)&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos)))
port.PUPDR = stm32.RegValue((uint32(port.PUPDR)&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos)))
p.setAltFunc(0x7)
}
}
func (p GPIO) setAltFunc(af uint32) {
port := p.getPort()
pin := p.Pin % 16
pos := pin * 4
if pin >= 8 {
port.AFRH = stm32.RegValue(uint32(port.AFRH)&^(0xF<<pos) | ((af & 0xF) << pos))
} else {
port.AFRL = stm32.RegValue(uint32(port.AFRL)&^(0xF<<pos) | ((af & 0xF) << pos))
}
}
// Set the pin to high or low.
// Warning: only use this on an output pin!
func (p GPIO) Set(high bool) {
port := p.getPort()
pin := p.Pin % 16
if high {
port.BSRR = 1 << pin
} else {
port.BSRR = 1 << (pin + 16)
}
}
// UART
type UART struct {
Buffer *RingBuffer
}
var (
// Both UART0 and UART1 refer to USART2.
UART0 = UART{Buffer: NewRingBuffer()}
UART1 = &UART0
)
// Configure the UART.
func (uart UART) Configure(config UARTConfig) {
// Default baud rate to 115200.
if config.BaudRate == 0 {
config.BaudRate = 115200
}
// pins
switch config.TX {
default:
// use standard TX/RX pins PA2 and PA3
GPIO{UART_TX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_TX})
GPIO{UART_RX_PIN}.Configure(GPIOConfig{Mode: GPIO_UART_RX})
}
// Enable USART2 clock
stm32.RCC.APB1ENR |= stm32.RCC_APB1ENR_USART2EN
/*
Set baud rate(115200)
OVER8 = 0, APB2 = 42mhz
+----------+--------+
| baudrate | BRR |
+----------+--------+
| 1200 | 0x88B8 |
| 2400 | 0x445C |
| 9600 | 0x1117 |
| 19200 | 0x88C |
| 38400 | 0x446 |
| 57600 | 0x2D9 |
| 115200 | 0x16D |
+----------+--------+
*/
stm32.USART2.BRR = 0x16c
// Enable USART2 port.
stm32.USART2.CR1 = stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE
// Enable RX IRQ.
arm.SetPriority(stm32.IRQ_USART2, 0xc0)
arm.EnableIRQ(stm32.IRQ_USART2)
}
// WriteByte writes a byte of data to the UART.
func (uart UART) WriteByte(c byte) error {
stm32.USART2.DR = stm32.RegValue(c)
for (stm32.USART2.SR & stm32.USART_SR_TXE) == 0 {
}
return nil
}
//go:export USART2_IRQHandler
func handleUSART2() {
UART1.Receive(byte((stm32.USART2.DR & 0xFF)))
}