stm32f4: refactor GPIO, in prep for adding SPI, I2C, PWM etc
Этот коммит содержится в:
родитель
3aaa029c70
коммит
c8a4994feb
6 изменённых файлов: 306 добавлений и 145 удалений
45
src/device/stm32/stm32-moder-bitfields.go
Обычный файл
45
src/device/stm32/stm32-moder-bitfields.go
Обычный файл
|
@ -0,0 +1,45 @@
|
|||
// Hand created file. DO NOT DELETE.
|
||||
// STM32FXXX (except stm32f1xx) bitfield definitions that are not
|
||||
// auto-generated by gen-device-svd.go
|
||||
|
||||
// These apply to the stm32 families that use the MODER, OTYPE amd PUPDR
|
||||
// registers for managing GPIO functionality.
|
||||
|
||||
// Add in other families that use the same settings, e.g. stm32f0xx, etc
|
||||
|
||||
// +build stm32,!stm32f103xx
|
||||
|
||||
package stm32
|
||||
|
||||
// AltFunc represents the alternate function peripherals that can be mapped to
|
||||
// the GPIO ports. Since these differ by what is supported on the stm32 family
|
||||
// they are defined in the more specific files
|
||||
type AltFunc uint8
|
||||
|
||||
// Family-wide common post-reset AltFunc. This represents
|
||||
// normal GPIO operation of the pins
|
||||
const AF0_SYSTEM AltFunc = 0
|
||||
|
||||
const (
|
||||
// Register values for the chip
|
||||
// GPIOx_MODER
|
||||
GPIOModeInput = 0
|
||||
GPIOModeOutputGeneral = 1
|
||||
GPIOModeOutputAltFunc = 2
|
||||
GPIOModeAnalog = 3
|
||||
|
||||
// GPIOx_OTYPER
|
||||
GPIOOutputTypePushPull = 0
|
||||
GPIOOutputTypeOpenDrain = 1
|
||||
|
||||
// GPIOx_OSPEEDR
|
||||
GPIOSpeedLow = 0
|
||||
GPIOSpeedMid = 1
|
||||
GPIOSpeedHigh = 2 // Note: this is also low speed on stm32f0, see RM0091
|
||||
GPIOSpeedVeryHigh = 3
|
||||
|
||||
// GPIOx_PUPDR
|
||||
GPIOPUPDRFloating = 0
|
||||
GPIOPUPDRPullUp = 1
|
||||
GPIOPUPDRPullDown = 2
|
||||
)
|
26
src/device/stm32/stm32f407xx-altfunc-bitfields.go
Обычный файл
26
src/device/stm32/stm32f407xx-altfunc-bitfields.go
Обычный файл
|
@ -0,0 +1,26 @@
|
|||
// These are the supported alternate function numberings on the stm32f407
|
||||
// +build stm32,stm32f407
|
||||
|
||||
// Alternate function settings on the stm32f4xx series
|
||||
|
||||
package stm32
|
||||
|
||||
const (
|
||||
// Alternative peripheral pin functions
|
||||
// AF0_SYSTEM is defined im the common bitfields package
|
||||
AF1_TIM1_2 AltFunc = 1
|
||||
AF2_TIM3_4_5 = 2
|
||||
AF3_TIM8_9_10_11 = 3
|
||||
AF4_I2C1_2_3 = 4
|
||||
AF5_SPI1_SPI2 = 5
|
||||
AF6_SPI3 = 6
|
||||
AF7_USART1_2_3 = 7
|
||||
AF8_USART4_5_6 = 8
|
||||
AF9_CAN1_CAN2_TIM12_13_14 = 9
|
||||
AF10_OTG_FS_OTG_HS = 10
|
||||
AF11_ETH = 11
|
||||
AF12_FSMC_SDIO_OTG_HS_1 = 12
|
||||
AF13_DCMI = 13
|
||||
AF14 = 14
|
||||
AF15_EVENTOUT = 15
|
||||
)
|
|
@ -5,3 +5,38 @@ package machine
|
|||
// Peripheral abstraction layer for the stm32.
|
||||
|
||||
type PinMode uint8
|
||||
|
||||
// Peripheral operations sequence:
|
||||
// 1. Enable the clock to the alternate function.
|
||||
// 2. Enable clock to corresponding GPIO
|
||||
// 3. Attach the alternate function.
|
||||
// 4. Configure the input-output port and pins (of the corresponding GPIOx) to match the AF .
|
||||
// 5. If desired enable the nested vector interrupt control to generate interrupts.
|
||||
// 6. Program the AF/peripheral for the required configuration (eg baud rate for a USART) .
|
||||
|
||||
// Given that the stm32 family has the AF and GPIO on different registers based on the chip,
|
||||
// use the main function here for configuring, and use hooks in the more specific chip
|
||||
// definition files
|
||||
// Also, the stm32f1xx series handles things differently from the stm32f0/2/3/4
|
||||
|
||||
// ---------- General pin operations ----------
|
||||
|
||||
// Set the pin to high or low.
|
||||
// Warning: only use this on an output pin!
|
||||
func (p Pin) Set(high bool) {
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
if high {
|
||||
port.BSRR.Set(1 << pin)
|
||||
} else {
|
||||
port.BSRR.Set(1 << (pin + 16))
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the current value of a GPIO pin.
|
||||
func (p Pin) Get() bool {
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
val := port.IDR.Get() & (1 << pin)
|
||||
return (val > 0)
|
||||
}
|
||||
|
|
128
src/machine/machine_stm32_moder_gpio.go
Обычный файл
128
src/machine/machine_stm32_moder_gpio.go
Обычный файл
|
@ -0,0 +1,128 @@
|
|||
// +build stm32,!stm32f103xx
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
)
|
||||
|
||||
// GPIO for the stm32 families except the stm32f1xx which uses a simpler but
|
||||
// less flexible mechanism. Extend the +build directive above to exclude other
|
||||
// models in the stm32f1xx series as necessary
|
||||
|
||||
const (
|
||||
// Mode Flag
|
||||
PinOutput PinMode = 0
|
||||
PinInput PinMode = PinInputFloating
|
||||
PinInputFloating PinMode = 1
|
||||
PinInputPulldown PinMode = 2
|
||||
PinInputPullup PinMode = 3
|
||||
|
||||
// for UART
|
||||
PinModeUARTTX PinMode = 4
|
||||
PinModeUARTRX PinMode = 5
|
||||
|
||||
// for I2C
|
||||
PinModeI2CSCL PinMode = 6
|
||||
PinModeI2CSDA PinMode = 7
|
||||
|
||||
// for SPI
|
||||
PinModeSPICLK PinMode = 8
|
||||
PinModeSPIMOSI PinMode = 9
|
||||
PinModeSPIMISO PinMode = 10
|
||||
|
||||
// for analog/ADC
|
||||
PinInputAnalog PinMode = 11
|
||||
|
||||
// for PWM
|
||||
// TBD
|
||||
)
|
||||
|
||||
// Configure this pin with the given configuration
|
||||
func (p Pin) Configure(config PinConfig) {
|
||||
// Use the default system alternate function; this
|
||||
// will only be used if you try to call this with
|
||||
// one of the peripheral modes instead of vanilla GPIO.
|
||||
p.ConfigureAltFunc(config, stm32.AF0_SYSTEM)
|
||||
}
|
||||
|
||||
// Configure this pin with the given configuration including alternate
|
||||
// function mapping if necessary.
|
||||
func (p Pin) ConfigureAltFunc(config PinConfig, altFunc stm32.AltFunc) {
|
||||
// Configure the GPIO pin.
|
||||
p.enableClock()
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
pos := pin * 2
|
||||
|
||||
switch config.Mode {
|
||||
|
||||
// GPIO
|
||||
case PinInputFloating:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeInput, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
case PinInputPulldown:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeInput, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRPullDown, 0x3, pos)
|
||||
case PinInputPullup:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeInput, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRPullUp, 0x3, pos)
|
||||
case PinOutput:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputGeneral, 0x3, pos)
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedHigh, 0x3, pos)
|
||||
|
||||
// UART
|
||||
case PinModeUARTTX:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedHigh, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRPullUp, 0x3, pos)
|
||||
p.SetAltFunc(altFunc)
|
||||
case PinModeUARTRX:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
p.SetAltFunc(altFunc)
|
||||
|
||||
// I2C)
|
||||
case PinModeI2CSCL:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||
port.OTYPER.ReplaceBits(stm32.GPIOOutputTypeOpenDrain, 0x1, pos)
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
p.SetAltFunc(altFunc)
|
||||
case PinModeI2CSDA:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||
port.OTYPER.ReplaceBits(stm32.GPIOOutputTypeOpenDrain, 0x1, pos)
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
p.SetAltFunc(altFunc)
|
||||
|
||||
// SPI
|
||||
case PinModeSPICLK:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
p.SetAltFunc(altFunc)
|
||||
case PinModeSPIMOSI:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
p.SetAltFunc(altFunc)
|
||||
case PinModeSPIMISO:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
p.SetAltFunc(altFunc)
|
||||
}
|
||||
}
|
||||
|
||||
// SetAltFunc maps the given alternative function to the I/O pin
|
||||
func (p Pin) SetAltFunc(af stm32.AltFunc) {
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
pos := (pin % 8) * 4
|
||||
if pin < 8 {
|
||||
port.AFRL.ReplaceBits(uint32(af), 0xf, pos)
|
||||
} else {
|
||||
port.AFRH.ReplaceBits(uint32(af), 0xf, pos)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import (
|
|||
"device/stm32"
|
||||
"errors"
|
||||
"runtime/interrupt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func CPUFrequency() uint32 {
|
||||
|
@ -32,6 +33,20 @@ const (
|
|||
PinOutputModeAltOpenDrain PinMode = 12 // Output mode alt. purpose open drain
|
||||
)
|
||||
|
||||
// Configure this pin with the given I/O settings.
|
||||
// stm32f1xx uses different technique for setting the GPIO pins than the stm32f407
|
||||
func (p Pin) Configure(config PinConfig) {
|
||||
// Configure the GPIO pin.
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
pos := (pin % 8) * 4
|
||||
if pin < 8 {
|
||||
port.CRL.ReplaceBits(uint32(config.Mode), 0xf, pos)
|
||||
} else {
|
||||
port.CRH.ReplaceBits(uint32(config.Mode), 0xf, pos)
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) getPort() *stm32.GPIO_Type {
|
||||
switch p / 16 {
|
||||
case 0:
|
||||
|
@ -75,40 +90,19 @@ func (p Pin) enableClock() {
|
|||
}
|
||||
}
|
||||
|
||||
// Configure this pin with the given configuration.
|
||||
func (p Pin) Configure(config PinConfig) {
|
||||
// Configure the GPIO pin.
|
||||
p.enableClock()
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
pos := uint8(p) % 8 * 4
|
||||
if pin < 8 {
|
||||
port.CRL.Set((uint32(port.CRL.Get()) &^ (0xf << pos)) | (uint32(config.Mode) << pos))
|
||||
} else {
|
||||
port.CRH.Set((uint32(port.CRH.Get()) &^ (0xf << pos)) | (uint32(config.Mode) << pos))
|
||||
// Enable peripheral clock. Expand to include all the desired peripherals
|
||||
func enableAltFuncClock(bus unsafe.Pointer) {
|
||||
if bus == unsafe.Pointer(stm32.USART1) {
|
||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
|
||||
} else if bus == unsafe.Pointer(stm32.USART2) {
|
||||
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)
|
||||
} else if bus == unsafe.Pointer(stm32.I2C1) {
|
||||
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)
|
||||
} else if bus == unsafe.Pointer(stm32.SPI1) {
|
||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)
|
||||
}
|
||||
}
|
||||
|
||||
// Set the pin to high or low.
|
||||
// Warning: only use this on an output pin!
|
||||
func (p Pin) Set(high bool) {
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
if high {
|
||||
port.BSRR.Set(1 << pin)
|
||||
} else {
|
||||
port.BSRR.Set(1 << (pin + 16))
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the current value of a GPIO pin.
|
||||
func (p Pin) Get() bool {
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
val := port.IDR.Get() & (1 << pin)
|
||||
return (val > 0)
|
||||
}
|
||||
|
||||
// UART
|
||||
type UART struct {
|
||||
Buffer *RingBuffer
|
||||
|
@ -123,6 +117,12 @@ func (uart UART) Configure(config UARTConfig) {
|
|||
config.BaudRate = 115200
|
||||
}
|
||||
|
||||
// Set the GPIO pins to defaults if they're not set
|
||||
if config.TX == 0 && config.RX == 0 {
|
||||
config.TX = UART_TX_PIN
|
||||
config.RX = UART_RX_PIN
|
||||
}
|
||||
|
||||
// pins
|
||||
switch config.TX {
|
||||
case UART_ALT_TX_PIN:
|
||||
|
@ -133,20 +133,14 @@ func (uart UART) Configure(config UARTConfig) {
|
|||
} else if uart.Bus == stm32.USART2 {
|
||||
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_USART2_REMAP)
|
||||
}
|
||||
UART_ALT_TX_PIN.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
||||
UART_ALT_RX_PIN.Configure(PinConfig{Mode: PinInputModeFloating})
|
||||
default:
|
||||
// use standard TX/RX pins PA9 and PA10
|
||||
UART_TX_PIN.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
||||
UART_RX_PIN.Configure(PinConfig{Mode: PinInputModeFloating})
|
||||
}
|
||||
config.TX.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
||||
config.RX.Configure(PinConfig{Mode: PinInputModeFloating})
|
||||
|
||||
// Enable USART clock
|
||||
if uart.Bus == stm32.USART1 {
|
||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
|
||||
} else if uart.Bus == stm32.USART2 {
|
||||
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)
|
||||
}
|
||||
enableAltFuncClock(unsafe.Pointer(uart.Bus))
|
||||
|
||||
// Set baud rate
|
||||
uart.SetBaudRate(config.BaudRate)
|
||||
|
|
|
@ -2,51 +2,18 @@
|
|||
|
||||
package machine
|
||||
|
||||
// Peripheral abstraction layer for the stm32.
|
||||
// Peripheral abstraction layer for the stm32f4(07)
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
"runtime/interrupt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func CPUFrequency() uint32 {
|
||||
return 168000000
|
||||
}
|
||||
|
||||
const (
|
||||
// Mode Flag
|
||||
PinOutput PinMode = 0
|
||||
PinInput PinMode = PinInputFloating
|
||||
PinInputFloating PinMode = 1
|
||||
PinInputPulldown PinMode = 2
|
||||
PinInputPullup PinMode = 3
|
||||
|
||||
// for UART
|
||||
PinModeUartTX PinMode = 4
|
||||
PinModeUartRX PinMode = 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 Pin) getPort() *stm32.GPIO_Type {
|
||||
switch p / 16 {
|
||||
case 0:
|
||||
|
@ -98,69 +65,33 @@ func (p Pin) enableClock() {
|
|||
}
|
||||
}
|
||||
|
||||
// Configure this pin with the given configuration.
|
||||
func (p Pin) Configure(config PinConfig) {
|
||||
// Configure the GPIO pin.
|
||||
p.enableClock()
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
pos := pin * 2
|
||||
|
||||
if config.Mode == PinInputFloating {
|
||||
port.MODER.Set((uint32(port.MODER.Get())&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
|
||||
port.PUPDR.Set((uint32(port.PUPDR.Get())&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos)))
|
||||
} else if config.Mode == PinInputPulldown {
|
||||
port.MODER.Set((uint32(port.MODER.Get())&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
|
||||
port.PUPDR.Set((uint32(port.PUPDR.Get())&^(0x3<<pos) | (uint32(GPIO_PULL_DOWN) << pos)))
|
||||
} else if config.Mode == PinInputPullup {
|
||||
port.MODER.Set((uint32(port.MODER.Get())&^(0x3<<pos) | (uint32(GPIO_MODE_INPUT) << pos)))
|
||||
port.PUPDR.Set((uint32(port.PUPDR.Get())&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos)))
|
||||
} else if config.Mode == PinOutput {
|
||||
port.MODER.Set((uint32(port.MODER.Get())&^(0x3<<pos) | (uint32(GPIO_MODE_GENERAL_OUTPUT) << pos)))
|
||||
port.OSPEEDR.Set((uint32(port.OSPEEDR.Get())&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos)))
|
||||
} else if config.Mode == PinModeUartTX {
|
||||
port.MODER.Set((uint32(port.MODER.Get())&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos)))
|
||||
port.OSPEEDR.Set((uint32(port.OSPEEDR.Get())&^(0x3<<pos) | (uint32(GPIO_SPEED_HI) << pos)))
|
||||
port.PUPDR.Set((uint32(port.PUPDR.Get())&^(0x3<<pos) | (uint32(GPIO_PULL_UP) << pos)))
|
||||
p.setAltFunc(0x7)
|
||||
} else if config.Mode == PinModeUartRX {
|
||||
port.MODER.Set((uint32(port.MODER.Get())&^(0x3<<pos) | (uint32(GPIO_MODE_ALTERNABTIVE) << pos)))
|
||||
port.PUPDR.Set((uint32(port.PUPDR.Get())&^(0x3<<pos) | (uint32(GPIO_FLOATING) << pos)))
|
||||
p.setAltFunc(0x7)
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) setAltFunc(af uint32) {
|
||||
port := p.getPort()
|
||||
pin := uint8(p) % 16
|
||||
pos := pin * 4
|
||||
if pin >= 8 {
|
||||
port.AFRH.Set(uint32(port.AFRH.Get())&^(0xF<<pos) | ((af & 0xF) << pos))
|
||||
} else {
|
||||
port.AFRL.Set(uint32(port.AFRL.Get())&^(0xF<<pos) | ((af & 0xF) << pos))
|
||||
}
|
||||
}
|
||||
|
||||
// Set the pin to high or low.
|
||||
// Warning: only use this on an output pin!
|
||||
func (p Pin) Set(high bool) {
|
||||
port := p.getPort()
|
||||
pin := p % 16
|
||||
if high {
|
||||
port.BSRR.Set(1 << uint8(pin))
|
||||
} else {
|
||||
port.BSRR.Set(1 << uint8(pin+16))
|
||||
// Enable peripheral clock
|
||||
func enableAltFuncClock(bus unsafe.Pointer) {
|
||||
switch bus {
|
||||
case unsafe.Pointer(stm32.USART1):
|
||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
|
||||
case unsafe.Pointer(stm32.USART2):
|
||||
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)
|
||||
case unsafe.Pointer(stm32.I2C1):
|
||||
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)
|
||||
case unsafe.Pointer(stm32.SPI1):
|
||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)
|
||||
}
|
||||
}
|
||||
|
||||
// UART
|
||||
type UART struct {
|
||||
Buffer *RingBuffer
|
||||
Bus *stm32.USART_Type
|
||||
AltFuncSelector stm32.AltFunc
|
||||
}
|
||||
|
||||
var (
|
||||
// Both UART0 and UART1 refer to USART2.
|
||||
UART0 = UART{Buffer: NewRingBuffer()}
|
||||
UART0 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: stm32.USART2,
|
||||
AltFuncSelector: stm32.AF7_USART1_2_3,
|
||||
}
|
||||
UART1 = &UART0
|
||||
)
|
||||
|
||||
|
@ -171,20 +102,22 @@ func (uart UART) Configure(config UARTConfig) {
|
|||
config.BaudRate = 115200
|
||||
}
|
||||
|
||||
// pins
|
||||
switch config.TX {
|
||||
default:
|
||||
// use standard TX/RX pins PA2 and PA3
|
||||
UART_TX_PIN.Configure(PinConfig{Mode: PinModeUartTX})
|
||||
UART_RX_PIN.Configure(PinConfig{Mode: PinModeUartRX})
|
||||
// Set the GPIO pins to defaults if they're not set
|
||||
if config.TX == 0 && config.RX == 0 {
|
||||
config.TX = UART_TX_PIN
|
||||
config.RX = UART_RX_PIN
|
||||
}
|
||||
|
||||
// Enable USART2 clock
|
||||
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)
|
||||
// Enable USART clock
|
||||
enableAltFuncClock(unsafe.Pointer(uart.Bus))
|
||||
|
||||
// use standard TX/RX pins PA2 and PA3
|
||||
config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.AltFuncSelector)
|
||||
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.AltFuncSelector)
|
||||
|
||||
/*
|
||||
Set baud rate(115200)
|
||||
OVER8 = 0, APB2 = 42mhz
|
||||
OVER8 = 0, APB1 = 42mhz
|
||||
+----------+--------+
|
||||
| baudrate | BRR |
|
||||
+----------+--------+
|
||||
|
@ -197,14 +130,14 @@ func (uart UART) Configure(config UARTConfig) {
|
|||
| 115200 | 0x16D |
|
||||
+----------+--------+
|
||||
*/
|
||||
stm32.USART2.BRR.Set(0x16c)
|
||||
uart.Bus.BRR.Set(0x16c)
|
||||
|
||||
// Enable USART2 port.
|
||||
stm32.USART2.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE)
|
||||
uart.Bus.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE)
|
||||
|
||||
// Enable RX IRQ.
|
||||
// Enable RX IRQ. TODO: pick the right IRQ_xxx for the bus and the uart
|
||||
intr := interrupt.New(stm32.IRQ_USART2, func(interrupt.Interrupt) {
|
||||
UART1.Receive(byte((stm32.USART2.DR.Get() & 0xFF)))
|
||||
UART1.Receive(byte((UART1.Bus.DR.Get() & 0xFF)))
|
||||
})
|
||||
intr.SetPriority(0xc0)
|
||||
intr.Enable()
|
||||
|
@ -212,9 +145,9 @@ func (uart UART) Configure(config UARTConfig) {
|
|||
|
||||
// WriteByte writes a byte of data to the UART.
|
||||
func (uart UART) WriteByte(c byte) error {
|
||||
stm32.USART2.DR.Set(uint32(c))
|
||||
uart.Bus.DR.Set(uint32(c))
|
||||
|
||||
for !stm32.USART2.SR.HasBits(stm32.USART_SR_TXE) {
|
||||
for !uart.Bus.SR.HasBits(stm32.USART_SR_TXE) {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче