refactor stm32 UART code
Этот коммит содержится в:
родитель
046efdd93a
коммит
c61c5e5799
5 изменённых файлов: 107 добавлений и 104 удалений
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/stm32"
|
||||||
|
"runtime/interrupt"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PA0 = portA + 0
|
PA0 = portA + 0
|
||||||
PA1 = portA + 1
|
PA1 = portA + 1
|
||||||
|
@ -110,3 +115,17 @@ const (
|
||||||
UART_TX_PIN = PA2
|
UART_TX_PIN = PA2
|
||||||
UART_RX_PIN = PA3
|
UART_RX_PIN = PA3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
UART0 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: stm32.USART2,
|
||||||
|
AltFuncSelector: stm32.AF7_USART1_2_3,
|
||||||
|
}
|
||||||
|
UART1 = &UART0
|
||||||
|
)
|
||||||
|
|
||||||
|
// set up RX IRQ handler. Follow similar pattern for other UARTx instances
|
||||||
|
func init() {
|
||||||
|
UART0.Interrupt = interrupt.New(stm32.IRQ_USART2, UART0.handleInterrupt)
|
||||||
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ func (p Pin) ConfigureAltFunc(config PinConfig, altFunc stm32.AltFunc) {
|
||||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||||
p.SetAltFunc(altFunc)
|
p.SetAltFunc(altFunc)
|
||||||
|
|
||||||
// I2C)
|
// I2C
|
||||||
case PinModeI2CSCL:
|
case PinModeI2CSCL:
|
||||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||||
port.OTYPER.ReplaceBits(stm32.GPIOOutputTypeOpenDrain, 0x1, pos)
|
port.OTYPER.ReplaceBits(stm32.GPIOOutputTypeOpenDrain, 0x1, pos)
|
||||||
|
|
62
src/machine/machine_stm32_uart.go
Обычный файл
62
src/machine/machine_stm32_uart.go
Обычный файл
|
@ -0,0 +1,62 @@
|
||||||
|
// +build stm32
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Peripheral abstraction layer for UARTs on the stm32 family.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/stm32"
|
||||||
|
"runtime/interrupt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Configure the UART.
|
||||||
|
func (uart UART) Configure(config UARTConfig) {
|
||||||
|
// Default baud rate to 115200.
|
||||||
|
if config.BaudRate == 0 {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable USART clock
|
||||||
|
enableAltFuncClock(unsafe.Pointer(uart.Bus))
|
||||||
|
|
||||||
|
uart.configurePins(config)
|
||||||
|
|
||||||
|
// Set baud rate
|
||||||
|
uart.SetBaudRate(config.BaudRate)
|
||||||
|
|
||||||
|
// Enable USART port, tx, rx and rx interrupts
|
||||||
|
uart.Bus.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE)
|
||||||
|
|
||||||
|
// Enable RX IRQ
|
||||||
|
uart.Interrupt.SetPriority(0xc0)
|
||||||
|
uart.Interrupt.Enable()
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleInterrupt should be called from the appropriate interrupt handler for
|
||||||
|
// this UART instance.
|
||||||
|
func (uart *UART) handleInterrupt(interrupt.Interrupt) {
|
||||||
|
uart.Receive(byte((uart.Bus.DR.Get() & 0xFF)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBaudRate sets the communication speed for the UART. Defer to chip-specific
|
||||||
|
// routines for calculation
|
||||||
|
func (uart UART) SetBaudRate(br uint32) {
|
||||||
|
divider := uart.getBaudRateDivisor(br)
|
||||||
|
uart.Bus.BRR.Set(divider)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteByte writes a byte of data to the UART.
|
||||||
|
func (uart UART) WriteByte(c byte) error {
|
||||||
|
uart.Bus.DR.Set(uint32(c))
|
||||||
|
|
||||||
|
for !uart.Bus.SR.HasBits(stm32.USART_SR_TXE) {
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -104,25 +104,17 @@ func enableAltFuncClock(bus unsafe.Pointer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UART
|
//---------- UART related types and code
|
||||||
|
|
||||||
|
// UART representation
|
||||||
type UART struct {
|
type UART struct {
|
||||||
Buffer *RingBuffer
|
Buffer *RingBuffer
|
||||||
Bus *stm32.USART_Type
|
Bus *stm32.USART_Type
|
||||||
Interrupt interrupt.Interrupt
|
Interrupt interrupt.Interrupt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the UART.
|
// Configure the TX and RX pins
|
||||||
func (uart UART) Configure(config UARTConfig) {
|
func (uart UART) configurePins(config UARTConfig) {
|
||||||
// Default baud rate to 115200.
|
|
||||||
if config.BaudRate == 0 {
|
|
||||||
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
|
// pins
|
||||||
switch config.TX {
|
switch config.TX {
|
||||||
|
@ -139,23 +131,11 @@ func (uart UART) Configure(config UARTConfig) {
|
||||||
}
|
}
|
||||||
config.TX.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
config.TX.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
||||||
config.RX.Configure(PinConfig{Mode: PinInputModeFloating})
|
config.RX.Configure(PinConfig{Mode: PinInputModeFloating})
|
||||||
|
|
||||||
// Enable USART clock
|
|
||||||
enableAltFuncClock(unsafe.Pointer(uart.Bus))
|
|
||||||
|
|
||||||
// Set baud rate
|
|
||||||
uart.SetBaudRate(config.BaudRate)
|
|
||||||
|
|
||||||
// Enable USART port
|
|
||||||
uart.Bus.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE)
|
|
||||||
|
|
||||||
// Enable RX IRQ
|
|
||||||
uart.Interrupt.SetPriority(0xc0)
|
|
||||||
uart.Interrupt.Enable()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBaudRate sets the communication speed for the UART.
|
// Determine the divisor for USARTs to get the given baudrate
|
||||||
func (uart UART) SetBaudRate(br uint32) {
|
func (uart UART) getBaudRateDivisor(br uint32) uint32 {
|
||||||
|
|
||||||
// Note: PCLK2 (from APB2) used for USART1 and PCLK1 for USART2, 3, 4, 5
|
// Note: PCLK2 (from APB2) used for USART1 and PCLK1 for USART2, 3, 4, 5
|
||||||
var divider uint32
|
var divider uint32
|
||||||
if uart.Bus == stm32.USART1 {
|
if uart.Bus == stm32.USART1 {
|
||||||
|
@ -165,22 +145,7 @@ func (uart UART) SetBaudRate(br uint32) {
|
||||||
// first divide by PCLK1 prescaler (div 2) and then desired baudrate
|
// first divide by PCLK1 prescaler (div 2) and then desired baudrate
|
||||||
divider = CPUFrequency() / 2 / br
|
divider = CPUFrequency() / 2 / br
|
||||||
}
|
}
|
||||||
uart.Bus.BRR.Set(divider)
|
return divider
|
||||||
}
|
|
||||||
|
|
||||||
// WriteByte writes a byte of data to the UART.
|
|
||||||
func (uart UART) WriteByte(c byte) error {
|
|
||||||
uart.Bus.DR.Set(uint32(c))
|
|
||||||
|
|
||||||
for !uart.Bus.SR.HasBits(stm32.USART_SR_TXE) {
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleInterrupt should be called from the appropriate interrupt handler for
|
|
||||||
// this UART instance.
|
|
||||||
func (uart *UART) handleInterrupt(interrupt.Interrupt) {
|
|
||||||
uart.Receive(byte((uart.Bus.DR.Get() & 0xFF)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPI on the STM32.
|
// SPI on the STM32.
|
||||||
|
|
|
@ -79,75 +79,32 @@ func enableAltFuncClock(bus unsafe.Pointer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UART
|
//---------- UART related types and code
|
||||||
|
|
||||||
|
// UART representation
|
||||||
type UART struct {
|
type UART struct {
|
||||||
Buffer *RingBuffer
|
Buffer *RingBuffer
|
||||||
Bus *stm32.USART_Type
|
Bus *stm32.USART_Type
|
||||||
|
Interrupt interrupt.Interrupt
|
||||||
AltFuncSelector stm32.AltFunc
|
AltFuncSelector stm32.AltFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
UART0 = UART{
|
|
||||||
Buffer: NewRingBuffer(),
|
|
||||||
Bus: stm32.USART2,
|
|
||||||
AltFuncSelector: stm32.AF7_USART1_2_3,
|
|
||||||
}
|
|
||||||
UART1 = &UART0
|
|
||||||
)
|
|
||||||
|
|
||||||
// Configure the UART.
|
// Configure the UART.
|
||||||
func (uart UART) Configure(config UARTConfig) {
|
func (uart UART) configurePins(config UARTConfig) {
|
||||||
// Default baud rate to 115200.
|
// enable the alternate functions on the TX and RX pins
|
||||||
if config.BaudRate == 0 {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.AltFuncSelector)
|
||||||
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.AltFuncSelector)
|
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.AltFuncSelector)
|
||||||
|
|
||||||
/*
|
|
||||||
Set baud rate(115200)
|
|
||||||
OVER8 = 0, APB1 = 42mhz
|
|
||||||
+----------+--------+
|
|
||||||
| baudrate | BRR |
|
|
||||||
+----------+--------+
|
|
||||||
| 1200 | 0x88B8 |
|
|
||||||
| 2400 | 0x445C |
|
|
||||||
| 9600 | 0x1117 |
|
|
||||||
| 19200 | 0x88C |
|
|
||||||
| 38400 | 0x446 |
|
|
||||||
| 57600 | 0x2D9 |
|
|
||||||
| 115200 | 0x16D |
|
|
||||||
+----------+--------+
|
|
||||||
*/
|
|
||||||
uart.Bus.BRR.Set(0x16c)
|
|
||||||
|
|
||||||
// Enable USART2 port.
|
|
||||||
uart.Bus.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE)
|
|
||||||
|
|
||||||
// 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((UART1.Bus.DR.Get() & 0xFF)))
|
|
||||||
})
|
|
||||||
intr.SetPriority(0xc0)
|
|
||||||
intr.Enable()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteByte writes a byte of data to the UART.
|
// UART baudrate calc based on the bus and clockspeed
|
||||||
func (uart UART) WriteByte(c byte) error {
|
// NOTE: keep this in sync with the runtime/runtime_stm32f407.go clock init code
|
||||||
uart.Bus.DR.Set(uint32(c))
|
func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 {
|
||||||
|
var clock uint32
|
||||||
for !uart.Bus.SR.HasBits(stm32.USART_SR_TXE) {
|
switch uart.Bus {
|
||||||
|
case stm32.USART1, stm32.USART6:
|
||||||
|
clock = CPUFrequency() / 2 // APB2 Frequency
|
||||||
|
case stm32.USART2, stm32.USART3, stm32.UART4, stm32.UART5:
|
||||||
|
clock = CPUFrequency() / 4 // APB1 Frequency
|
||||||
}
|
}
|
||||||
return nil
|
return clock / baudRate
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче