machine/stm32f103xx: allow board specific UART usage
Motivation: The bluepill uses USART1 as UART0 but other boards like the STM32 Nucleo boards (and disco as well) use USART2 for USB COM port. To avoid duplication of code the same pattern as in `machine_atsamd21.go` is applied where only UART-specific code is moved to `board_*.go`.
Этот коммит содержится в:
родитель
abca3132a9
коммит
688dd81400
2 изменённых файлов: 56 добавлений и 31 удалений
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
import "device/stm32"
|
||||||
|
|
||||||
// https://wiki.stm32duino.com/index.php?title=File:Bluepillpinout.gif
|
// https://wiki.stm32duino.com/index.php?title=File:Bluepillpinout.gif
|
||||||
const (
|
const (
|
||||||
PA0 = portA + 0
|
PA0 = portA + 0
|
||||||
|
@ -47,10 +49,28 @@ const (
|
||||||
|
|
||||||
// UART pins
|
// UART pins
|
||||||
const (
|
const (
|
||||||
UART_TX_PIN = PA9
|
UART_TX_PIN = PA9
|
||||||
UART_RX_PIN = PA10
|
UART_RX_PIN = PA10
|
||||||
|
UART_ALT_TX_PIN = PB6
|
||||||
|
UART_ALT_RX_PIN = PB7
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// USART1 is the first hardware serial port on the STM32.
|
||||||
|
// Both UART0 and UART1 refer to USART1.
|
||||||
|
UART0 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: stm32.USART1,
|
||||||
|
IRQVal: stm32.IRQ_USART1,
|
||||||
|
}
|
||||||
|
UART1 = &UART0
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:export USART1_IRQHandler
|
||||||
|
func handleUART1() {
|
||||||
|
UART1.Receive(byte((UART1.Bus.DR.Get() & 0xFF)))
|
||||||
|
}
|
||||||
|
|
||||||
// SPI pins
|
// SPI pins
|
||||||
const (
|
const (
|
||||||
SPI0_SCK_PIN = PA5
|
SPI0_SCK_PIN = PA5
|
||||||
|
|
|
@ -110,15 +110,10 @@ func (p Pin) Get() bool {
|
||||||
// UART
|
// UART
|
||||||
type UART struct {
|
type UART struct {
|
||||||
Buffer *RingBuffer
|
Buffer *RingBuffer
|
||||||
|
Bus *stm32.USART_Type
|
||||||
|
IRQVal uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
// USART1 is the first hardware serial port on the STM32.
|
|
||||||
// Both UART0 and UART1 refer to USART1.
|
|
||||||
UART0 = UART{Buffer: NewRingBuffer()}
|
|
||||||
UART1 = &UART0
|
|
||||||
)
|
|
||||||
|
|
||||||
// Configure the UART.
|
// Configure the UART.
|
||||||
func (uart UART) Configure(config UARTConfig) {
|
func (uart UART) Configure(config UARTConfig) {
|
||||||
// Default baud rate to 115200.
|
// Default baud rate to 115200.
|
||||||
|
@ -128,53 +123,63 @@ func (uart UART) Configure(config UARTConfig) {
|
||||||
|
|
||||||
// pins
|
// pins
|
||||||
switch config.TX {
|
switch config.TX {
|
||||||
case PB6:
|
case UART_ALT_TX_PIN:
|
||||||
// use alternate TX/RX pins PB6/PB7 via AFIO mapping
|
// use alternate TX/RX pins via AFIO mapping
|
||||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)
|
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)
|
||||||
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_USART1_REMAP)
|
if uart.Bus == stm32.USART1 {
|
||||||
PB6.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_USART1_REMAP)
|
||||||
PB7.Configure(PinConfig{Mode: PinInputModeFloating})
|
} 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:
|
default:
|
||||||
// use standard TX/RX pins PA9 and PA10
|
// use standard TX/RX pins PA9 and PA10
|
||||||
UART_TX_PIN.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
UART_TX_PIN.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
||||||
UART_RX_PIN.Configure(PinConfig{Mode: PinInputModeFloating})
|
UART_RX_PIN.Configure(PinConfig{Mode: PinInputModeFloating})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable USART1 clock
|
// Enable USART clock
|
||||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
// Set baud rate
|
// Set baud rate
|
||||||
uart.SetBaudRate(config.BaudRate)
|
uart.SetBaudRate(config.BaudRate)
|
||||||
|
|
||||||
// Enable USART1 port.
|
// Enable USART port
|
||||||
stm32.USART1.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
|
||||||
arm.SetPriority(stm32.IRQ_USART1, 0xc0)
|
arm.SetPriority(uart.IRQVal, 0xc0)
|
||||||
arm.EnableIRQ(stm32.IRQ_USART1)
|
arm.EnableIRQ(uart.IRQVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBaudRate sets the communication speed for the UART.
|
// SetBaudRate sets the communication speed for the UART.
|
||||||
func (uart UART) SetBaudRate(br uint32) {
|
func (uart UART) SetBaudRate(br uint32) {
|
||||||
// first divide by PCLK2 prescaler (div 1) and then desired baudrate
|
// Note: PCLK2 (from APB2) used for USART1 and PCLK1 for USART2, 3, 4, 5
|
||||||
divider := CPU_FREQUENCY / br
|
var divider uint32
|
||||||
stm32.USART1.BRR.Set(divider)
|
if uart.Bus == stm32.USART1 {
|
||||||
|
// first divide by PCLK2 prescaler (div 1) and then desired baudrate
|
||||||
|
divider = CPU_FREQUENCY / br
|
||||||
|
} else {
|
||||||
|
// first divide by PCLK1 prescaler (div 2) and then desired baudrate
|
||||||
|
divider = CPU_FREQUENCY / 2 / br
|
||||||
|
}
|
||||||
|
uart.Bus.BRR.Set(divider)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteByte writes a byte of data to the UART.
|
// WriteByte writes a byte of data to the UART.
|
||||||
func (uart UART) WriteByte(c byte) error {
|
func (uart UART) WriteByte(c byte) error {
|
||||||
stm32.USART1.DR.Set(uint32(c))
|
uart.Bus.DR.Set(uint32(c))
|
||||||
|
|
||||||
for !stm32.USART1.SR.HasBits(stm32.USART_SR_TXE) {
|
for !uart.Bus.SR.HasBits(stm32.USART_SR_TXE) {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:export USART1_IRQHandler
|
|
||||||
func handleUART1() {
|
|
||||||
UART1.Receive(byte((stm32.USART1.DR.Get() & 0xFF)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SPI on the STM32.
|
// SPI on the STM32.
|
||||||
type SPI struct {
|
type SPI struct {
|
||||||
Bus *stm32.SPI_Type
|
Bus *stm32.SPI_Type
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче