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`.
Этот коммит содержится в:
cn 2019-09-17 02:21:53 +02:00 коммит произвёл Ron Evans
родитель 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