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
|
||||
|
||||
import "device/stm32"
|
||||
|
||||
// https://wiki.stm32duino.com/index.php?title=File:Bluepillpinout.gif
|
||||
const (
|
||||
PA0 = portA + 0
|
||||
|
@ -47,10 +49,28 @@ const (
|
|||
|
||||
// UART pins
|
||||
const (
|
||||
UART_TX_PIN = PA9
|
||||
UART_RX_PIN = PA10
|
||||
UART_TX_PIN = PA9
|
||||
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
|
||||
const (
|
||||
SPI0_SCK_PIN = PA5
|
||||
|
|
|
@ -110,15 +110,10 @@ func (p Pin) Get() bool {
|
|||
// UART
|
||||
type UART struct {
|
||||
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.
|
||||
func (uart UART) Configure(config UARTConfig) {
|
||||
// Default baud rate to 115200.
|
||||
|
@ -128,53 +123,63 @@ func (uart UART) Configure(config UARTConfig) {
|
|||
|
||||
// pins
|
||||
switch config.TX {
|
||||
case PB6:
|
||||
// use alternate TX/RX pins PB6/PB7 via AFIO mapping
|
||||
case UART_ALT_TX_PIN:
|
||||
// use alternate TX/RX pins via AFIO mapping
|
||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)
|
||||
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_USART1_REMAP)
|
||||
PB6.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
||||
PB7.Configure(PinConfig{Mode: PinInputModeFloating})
|
||||
if uart.Bus == stm32.USART1 {
|
||||
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_USART1_REMAP)
|
||||
} 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})
|
||||
}
|
||||
|
||||
// Enable USART1 clock
|
||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Set baud rate
|
||||
uart.SetBaudRate(config.BaudRate)
|
||||
|
||||
// Enable USART1 port.
|
||||
stm32.USART1.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE)
|
||||
// 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.
|
||||
arm.SetPriority(stm32.IRQ_USART1, 0xc0)
|
||||
arm.EnableIRQ(stm32.IRQ_USART1)
|
||||
// Enable RX IRQ
|
||||
arm.SetPriority(uart.IRQVal, 0xc0)
|
||||
arm.EnableIRQ(uart.IRQVal)
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for the UART.
|
||||
func (uart UART) SetBaudRate(br uint32) {
|
||||
// first divide by PCLK2 prescaler (div 1) and then desired baudrate
|
||||
divider := CPU_FREQUENCY / br
|
||||
stm32.USART1.BRR.Set(divider)
|
||||
// Note: PCLK2 (from APB2) used for USART1 and PCLK1 for USART2, 3, 4, 5
|
||||
var divider uint32
|
||||
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.
|
||||
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
|
||||
}
|
||||
|
||||
//go:export USART1_IRQHandler
|
||||
func handleUART1() {
|
||||
UART1.Receive(byte((stm32.USART1.DR.Get() & 0xFF)))
|
||||
}
|
||||
|
||||
// SPI on the STM32.
|
||||
type SPI struct {
|
||||
Bus *stm32.SPI_Type
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче