machine/rp2040: implement UART0/UART1, can be used on all rp2040 boards
Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
b406b81416
коммит
87e48c1057
6 изменённых файлов: 192 добавлений и 8 удалений
|
@ -47,12 +47,6 @@ const (
|
||||||
LED = GPIO6
|
LED = GPIO6
|
||||||
)
|
)
|
||||||
|
|
||||||
// UART1 pins
|
|
||||||
const (
|
|
||||||
UART_TX_PIN Pin = GPIO0
|
|
||||||
UART_RX_PIN Pin = GPIO1
|
|
||||||
)
|
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
SDA_PIN Pin = GPIO12
|
SDA_PIN Pin = GPIO12
|
||||||
|
|
|
@ -4,7 +4,7 @@ package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/rp"
|
"device/rp"
|
||||||
_ "unsafe"
|
"runtime/interrupt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -82,3 +82,35 @@ func machineInit() {
|
||||||
func ticks() uint64 {
|
func ticks() uint64 {
|
||||||
return timer.timeElapsed()
|
return timer.timeElapsed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UART pins
|
||||||
|
const (
|
||||||
|
UART_TX_PIN = UART0_TX_PIN
|
||||||
|
UART_RX_PIN = UART0_RX_PIN
|
||||||
|
UART0_TX_PIN = GPIO0
|
||||||
|
UART0_RX_PIN = GPIO1
|
||||||
|
UART1_TX_PIN = GPIO8
|
||||||
|
UART1_RX_PIN = GPIO9
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART on the RP2040
|
||||||
|
var (
|
||||||
|
UART0 = &_UART0
|
||||||
|
_UART0 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: rp.UART0,
|
||||||
|
}
|
||||||
|
|
||||||
|
UART1 = &_UART1
|
||||||
|
_UART1 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: rp.UART1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var Serial = UART0
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
UART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)
|
||||||
|
UART1.Interrupt = interrupt.New(rp.IRQ_UART1_IRQ, _UART1.handleInterrupt)
|
||||||
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ const (
|
||||||
PinInputPulldown
|
PinInputPulldown
|
||||||
PinInputPullup
|
PinInputPullup
|
||||||
PinAnalog
|
PinAnalog
|
||||||
|
PinUART
|
||||||
)
|
)
|
||||||
|
|
||||||
// set drives the pin high
|
// set drives the pin high
|
||||||
|
@ -152,6 +153,8 @@ func (p Pin) Configure(config PinConfig) {
|
||||||
case PinAnalog:
|
case PinAnalog:
|
||||||
p.setFunc(fnNULL)
|
p.setFunc(fnNULL)
|
||||||
p.pulloff()
|
p.pulloff()
|
||||||
|
case PinUART:
|
||||||
|
p.setFunc(fnUART)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
133
src/machine/machine_rp2040_uart.go
Обычный файл
133
src/machine/machine_rp2040_uart.go
Обычный файл
|
@ -0,0 +1,133 @@
|
||||||
|
// +build rp2040
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/rp"
|
||||||
|
"runtime/interrupt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART on the RP2040.
|
||||||
|
type UART struct {
|
||||||
|
Buffer *RingBuffer
|
||||||
|
Bus *rp.UART0_Type
|
||||||
|
Interrupt interrupt.Interrupt
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the UART.
|
||||||
|
func (uart *UART) Configure(config UARTConfig) error {
|
||||||
|
initUART(uart)
|
||||||
|
|
||||||
|
// Default baud rate to 115200.
|
||||||
|
if config.BaudRate == 0 {
|
||||||
|
config.BaudRate = 115200
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use default pins if pins are not set.
|
||||||
|
if config.TX == 0 && config.RX == 0 {
|
||||||
|
// use default pins
|
||||||
|
config.TX = UART_TX_PIN
|
||||||
|
config.RX = UART_RX_PIN
|
||||||
|
}
|
||||||
|
|
||||||
|
uart.SetBaudRate(config.BaudRate)
|
||||||
|
|
||||||
|
// default to 8-1-N
|
||||||
|
uart.SetFormat(8, 1, ParityNone)
|
||||||
|
|
||||||
|
// Enable the UART, both TX and RX
|
||||||
|
uart.Bus.UARTCR.SetBits(rp.UART0_UARTCR_UARTEN |
|
||||||
|
rp.UART0_UARTCR_RXE |
|
||||||
|
rp.UART0_UARTCR_TXE)
|
||||||
|
|
||||||
|
// set GPIO mux to UART for the pins
|
||||||
|
config.TX.Configure(PinConfig{Mode: PinUART})
|
||||||
|
config.RX.Configure(PinConfig{Mode: PinUART})
|
||||||
|
|
||||||
|
// Enable RX IRQ.
|
||||||
|
uart.Interrupt.SetPriority(0x80)
|
||||||
|
uart.Interrupt.Enable()
|
||||||
|
|
||||||
|
// setup interrupt on receive
|
||||||
|
uart.Bus.UARTIMSC.Set(rp.UART0_UARTIMSC_RXIM)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBaudRate sets the baudrate to be used for the UART.
|
||||||
|
func (uart *UART) SetBaudRate(br uint32) {
|
||||||
|
div := 8 * 125 * MHz / br
|
||||||
|
|
||||||
|
ibrd := div >> 7
|
||||||
|
var fbrd uint32
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case ibrd == 0:
|
||||||
|
ibrd = 1
|
||||||
|
fbrd = 0
|
||||||
|
case ibrd >= 65535:
|
||||||
|
ibrd = 65535
|
||||||
|
fbrd = 0
|
||||||
|
default:
|
||||||
|
fbrd = ((div & 0x7f) + 1) / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// set PL011 baud divisor registers
|
||||||
|
uart.Bus.UARTIBRD.Set(ibrd)
|
||||||
|
uart.Bus.UARTFBRD.Set(fbrd)
|
||||||
|
|
||||||
|
// PL011 needs a (dummy) line control register write.
|
||||||
|
// See https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_uart/uart.c#L93-L95
|
||||||
|
uart.Bus.UARTLCR_H.SetBits(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteByte writes a byte of data to the UART.
|
||||||
|
func (uart *UART) WriteByte(c byte) error {
|
||||||
|
// wait until buffer is not full
|
||||||
|
for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_TXFF) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// write data
|
||||||
|
uart.Bus.UARTDR.Set(uint32(c))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFormat for number of data bits, stop bits, and parity for the UART.
|
||||||
|
func (uart *UART) SetFormat(databits, stopbits uint8, parity UARTParity) error {
|
||||||
|
var pen, pev uint8
|
||||||
|
if parity != ParityNone {
|
||||||
|
pen = rp.UART0_UARTLCR_H_PEN
|
||||||
|
}
|
||||||
|
if parity == ParityEven {
|
||||||
|
pev = rp.UART0_UARTLCR_H_EPS
|
||||||
|
}
|
||||||
|
uart.Bus.UARTLCR_H.SetBits(uint32((databits-5)<<rp.UART0_UARTLCR_H_WLEN_Pos |
|
||||||
|
(stopbits-1)<<rp.UART0_UARTLCR_H_STP2_Pos |
|
||||||
|
pen | pev))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initUART(uart *UART) {
|
||||||
|
var resetVal uint32
|
||||||
|
switch {
|
||||||
|
case uart.Bus == rp.UART0:
|
||||||
|
resetVal = rp.RESETS_RESET_UART0
|
||||||
|
case uart.Bus == rp.UART1:
|
||||||
|
resetVal = rp.RESETS_RESET_UART1
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset UART
|
||||||
|
rp.RESETS.RESET.SetBits(resetVal)
|
||||||
|
rp.RESETS.RESET.ClearBits(resetVal)
|
||||||
|
for !rp.RESETS.RESET_DONE.HasBits(resetVal) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleInterrupt should be called from the appropriate interrupt handler for
|
||||||
|
// this UART instance.
|
||||||
|
func (uart *UART) handleInterrupt(interrupt.Interrupt) {
|
||||||
|
for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_RXFE) {
|
||||||
|
}
|
||||||
|
uart.Receive(byte((uart.Bus.UARTDR.Get() & 0xFF)))
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// +build atmega esp nrf sam sifive stm32 k210 nxp
|
// +build atmega esp nrf sam sifive stm32 k210 nxp rp2040
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
@ -6,6 +6,23 @@ import "errors"
|
||||||
|
|
||||||
var errUARTBufferEmpty = errors.New("UART buffer empty")
|
var errUARTBufferEmpty = errors.New("UART buffer empty")
|
||||||
|
|
||||||
|
// UARTParity is the parity setting to be used for UART communication.
|
||||||
|
type UARTParity int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ParityNone means to not use any parity checking. This is
|
||||||
|
// the most common setting.
|
||||||
|
ParityNone UARTParity = 0
|
||||||
|
|
||||||
|
// ParityEven means to expect that the total number of 1 bits sent
|
||||||
|
// should be an even number.
|
||||||
|
ParityEven UARTParity = 1
|
||||||
|
|
||||||
|
// ParityOdd means to expect that the total number of 1 bits sent
|
||||||
|
// should be an odd number.
|
||||||
|
ParityOdd UARTParity = 2
|
||||||
|
)
|
||||||
|
|
||||||
type UARTConfig struct {
|
type UARTConfig struct {
|
||||||
BaudRate uint32
|
BaudRate uint32
|
||||||
TX Pin
|
TX Pin
|
||||||
|
|
|
@ -4,6 +4,8 @@ package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/arm"
|
"device/arm"
|
||||||
|
|
||||||
|
"machine"
|
||||||
)
|
)
|
||||||
|
|
||||||
// machineTicks is provided by package machine.
|
// machineTicks is provided by package machine.
|
||||||
|
@ -39,6 +41,7 @@ func waitForEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func putchar(c byte) {
|
func putchar(c byte) {
|
||||||
|
machine.Serial.WriteByte(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// machineInit is provided by package machine.
|
// machineInit is provided by package machine.
|
||||||
|
@ -46,6 +49,8 @@ func machineInit()
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
machineInit()
|
machineInit()
|
||||||
|
|
||||||
|
machine.Serial.Configure(machine.UARTConfig{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func postinit() {}
|
func postinit() {}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче