mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 06:38:42 +00:00
Add UART line inversion support (#5522)
* feat(machine): add UART line inversion support. Add InvertTX and InvertRX to UARTConfig to allow enabling hardware line inversion on supported targets. Added hardware implementation for RP2 (RP2040, RP2350), STM32 (newer families), SAM (SAMD51, SAME5x), and ESP (ESP32, ESP32-C3, ESP32-C6). * refactor(machine): Refactor UART inversion with pin setter helpers. RP2: Extract setOutOver/setInOver methods on Pin, removing inline IO control register manipulation from UART configure. SAM: Switch to SetCTRLA_TXINV/SetCTRLA_RXINV methods, dropping the unused device/sam import and raw SetBits/ClearBits calls. --------- Co-authored-by: Konstantin Sharlaimov <ksharlaimov@inavflight.com>
This commit is contained in:
committed by
GitHub
parent
7994d2e912
commit
ea003da13f
@@ -621,6 +621,9 @@ func (uart *UART) Configure(config UARTConfig) error {
|
|||||||
//sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;
|
//sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;
|
||||||
uart.Bus.CTRLB.SetBits(sam.SERCOM_USART_CTRLB_TXEN | sam.SERCOM_USART_CTRLB_RXEN)
|
uart.Bus.CTRLB.SetBits(sam.SERCOM_USART_CTRLB_TXEN | sam.SERCOM_USART_CTRLB_RXEN)
|
||||||
|
|
||||||
|
// Configure RX/TX inversion
|
||||||
|
uart.setInversion(config)
|
||||||
|
|
||||||
// Enable USART1 port.
|
// Enable USART1 port.
|
||||||
// sercom->USART.CTRLA.bit.ENABLE = 0x1u;
|
// sercom->USART.CTRLA.bit.ENABLE = 0x1u;
|
||||||
uart.Bus.CTRLA.SetBits(sam.SERCOM_USART_CTRLA_ENABLE)
|
uart.Bus.CTRLA.SetBits(sam.SERCOM_USART_CTRLA_ENABLE)
|
||||||
|
|||||||
@@ -1102,6 +1102,9 @@ func (uart *UART) Configure(config UARTConfig) error {
|
|||||||
//sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;
|
//sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;
|
||||||
uart.Bus.CTRLB.SetBits(sam.SERCOM_USART_INT_CTRLB_TXEN | sam.SERCOM_USART_INT_CTRLB_RXEN)
|
uart.Bus.CTRLB.SetBits(sam.SERCOM_USART_INT_CTRLB_TXEN | sam.SERCOM_USART_INT_CTRLB_RXEN)
|
||||||
|
|
||||||
|
// Configure RX/TX inversion
|
||||||
|
uart.setInversion(config)
|
||||||
|
|
||||||
// Enable USART1 port.
|
// Enable USART1 port.
|
||||||
// sercom->USART.CTRLA.bit.ENABLE = 0x1u;
|
// sercom->USART.CTRLA.bit.ENABLE = 0x1u;
|
||||||
uart.Bus.CTRLA.SetBits(sam.SERCOM_USART_INT_CTRLA_ENABLE)
|
uart.Bus.CTRLA.SetBits(sam.SERCOM_USART_INT_CTRLA_ENABLE)
|
||||||
|
|||||||
@@ -332,10 +332,20 @@ func (uart *UART) Configure(config UARTConfig) {
|
|||||||
|
|
||||||
if config.RX != NoPin {
|
if config.RX != NoPin {
|
||||||
config.RX.configure(PinConfig{Mode: PinInputPullup}, uart.TXRXSignal)
|
config.RX.configure(PinConfig{Mode: PinInputPullup}, uart.TXRXSignal)
|
||||||
|
if config.InvertRX {
|
||||||
|
inFunc(uart.TXRXSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.RX)<<esp.GPIO_FUNC_IN_SEL_CFG_IN_SEL_Pos | esp.GPIO_FUNC_IN_SEL_CFG_IN_INV_SEL)
|
||||||
|
} else {
|
||||||
|
inFunc(uart.TXRXSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.RX)<<esp.GPIO_FUNC_IN_SEL_CFG_IN_SEL_Pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.TX != NoPin {
|
if config.TX != NoPin {
|
||||||
config.TX.configure(PinConfig{Mode: PinOutput}, uart.TXRXSignal)
|
config.TX.configure(PinConfig{Mode: PinOutput}, uart.TXRXSignal)
|
||||||
|
if config.InvertTX {
|
||||||
|
config.TX.outFunc().Set(uart.TXRXSignal | esp.GPIO_FUNC_OUT_SEL_CFG_INV_SEL)
|
||||||
|
} else {
|
||||||
|
config.TX.outFunc().Set(uart.TXRXSignal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.RTS != NoPin {
|
if config.RTS != NoPin {
|
||||||
|
|||||||
@@ -447,9 +447,17 @@ func (uart *UART) setupPins(config UARTConfig, regs registerSet) {
|
|||||||
config.TX.Configure(PinConfig{Mode: PinInputPullup})
|
config.TX.Configure(PinConfig{Mode: PinInputPullup})
|
||||||
|
|
||||||
// link TX with GPIO signal X (technical reference manual 5.10) (this is not interrupt signal!)
|
// link TX with GPIO signal X (technical reference manual 5.10) (this is not interrupt signal!)
|
||||||
config.TX.outFunc().Set(regs.gpioMatrixSignal)
|
if config.InvertTX {
|
||||||
|
config.TX.outFunc().Set(regs.gpioMatrixSignal | esp.GPIO_FUNC_OUT_SEL_CFG_INV_SEL)
|
||||||
|
} else {
|
||||||
|
config.TX.outFunc().Set(regs.gpioMatrixSignal)
|
||||||
|
}
|
||||||
// link RX with GPIO signal X and route signals via GPIO matrix (GPIO_SIGn_IN_SEL 0x40)
|
// link RX with GPIO signal X and route signals via GPIO matrix (GPIO_SIGn_IN_SEL 0x40)
|
||||||
inFunc(regs.gpioMatrixSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.RX))
|
if config.InvertRX {
|
||||||
|
inFunc(regs.gpioMatrixSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.RX) | esp.GPIO_FUNC_IN_SEL_CFG_IN_INV_SEL)
|
||||||
|
} else {
|
||||||
|
inFunc(regs.gpioMatrixSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.RX))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uart *UART) configureInterrupt(intrMapReg *volatile.Register32) { // Disable all UART interrupts
|
func (uart *UART) configureInterrupt(intrMapReg *volatile.Register32) { // Disable all UART interrupts
|
||||||
|
|||||||
@@ -460,9 +460,17 @@ func (uart *UART) setupPins(config UARTConfig, regs registerSet) {
|
|||||||
config.TX.Configure(PinConfig{Mode: PinInputPullup})
|
config.TX.Configure(PinConfig{Mode: PinInputPullup})
|
||||||
|
|
||||||
// link TX with GPIO signal X (technical reference manual, GPIO matrix)
|
// link TX with GPIO signal X (technical reference manual, GPIO matrix)
|
||||||
config.TX.outFunc().Set(regs.gpioMatrixSignal)
|
if config.InvertTX {
|
||||||
|
config.TX.outFunc().Set(regs.gpioMatrixSignal | esp.GPIO_FUNC_OUT_SEL_CFG_INV_SEL)
|
||||||
|
} else {
|
||||||
|
config.TX.outFunc().Set(regs.gpioMatrixSignal)
|
||||||
|
}
|
||||||
// link RX with GPIO signal X and route signals via GPIO matrix
|
// link RX with GPIO signal X and route signals via GPIO matrix
|
||||||
inFunc(regs.gpioMatrixSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.RX))
|
if config.InvertRX {
|
||||||
|
inFunc(regs.gpioMatrixSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.RX) | esp.GPIO_FUNC_IN_SEL_CFG_IN_INV_SEL)
|
||||||
|
} else {
|
||||||
|
inFunc(regs.gpioMatrixSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.RX))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uart *UART) configureInterrupt(intrMapReg *volatile.Register32) {
|
func (uart *UART) configureInterrupt(intrMapReg *volatile.Register32) {
|
||||||
|
|||||||
@@ -141,6 +141,16 @@ func (p Pin) setSchmitt(trigger bool) {
|
|||||||
p.padCtrl().ReplaceBits(boolToBit(trigger)<<rp.PADS_BANK0_GPIO0_SCHMITT_Pos, rp.PADS_BANK0_GPIO0_SCHMITT_Msk, 0)
|
p.padCtrl().ReplaceBits(boolToBit(trigger)<<rp.PADS_BANK0_GPIO0_SCHMITT_Pos, rp.PADS_BANK0_GPIO0_SCHMITT_Msk, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setOutOver sets the output override (OUTOVER field) for the pin.
|
||||||
|
func (p Pin) setOutOver(over uint32) {
|
||||||
|
p.ioCtrl().ReplaceBits(over<<rp.IO_BANK0_GPIO0_CTRL_OUTOVER_Pos, rp.IO_BANK0_GPIO0_CTRL_OUTOVER_Msk, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setInOver sets the input override (INOVER field) for the pin.
|
||||||
|
func (p Pin) setInOver(over uint32) {
|
||||||
|
p.ioCtrl().ReplaceBits(over<<rp.IO_BANK0_GPIO0_CTRL_INOVER_Pos, rp.IO_BANK0_GPIO0_CTRL_INOVER_Msk, 0)
|
||||||
|
}
|
||||||
|
|
||||||
// setFunc will set pin function to fn.
|
// setFunc will set pin function to fn.
|
||||||
func (p Pin) setFunc(fn pinFunc) {
|
func (p Pin) setFunc(fn pinFunc) {
|
||||||
// Set input enable, Clear output disable
|
// Set input enable, Clear output disable
|
||||||
|
|||||||
@@ -52,9 +52,19 @@ func (uart *UART) Configure(config UARTConfig) error {
|
|||||||
// set GPIO mux to UART for the pins
|
// set GPIO mux to UART for the pins
|
||||||
if config.TX != NoPin {
|
if config.TX != NoPin {
|
||||||
config.TX.Configure(PinConfig{Mode: PinUART})
|
config.TX.Configure(PinConfig{Mode: PinUART})
|
||||||
|
if config.InvertTX {
|
||||||
|
config.TX.setOutOver(rp.IO_BANK0_GPIO0_CTRL_OUTOVER_INVERT)
|
||||||
|
} else {
|
||||||
|
config.TX.setOutOver(rp.IO_BANK0_GPIO0_CTRL_OUTOVER_NORMAL)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if config.RX != NoPin {
|
if config.RX != NoPin {
|
||||||
config.RX.Configure(PinConfig{Mode: PinUART})
|
config.RX.Configure(PinConfig{Mode: PinUART})
|
||||||
|
if config.InvertRX {
|
||||||
|
config.RX.setInOver(rp.IO_BANK0_GPIO0_CTRL_INOVER_INVERT)
|
||||||
|
} else {
|
||||||
|
config.RX.setInOver(rp.IO_BANK0_GPIO0_CTRL_INOVER_NORMAL)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if config.RTS != 0 {
|
if config.RTS != 0 {
|
||||||
config.RTS.Configure(PinConfig{Mode: PinOutput})
|
config.RTS.Configure(PinConfig{Mode: PinOutput})
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//go:build sam && (atsamd51 || atsame5x)
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Configure UART TX/RX line inversion using SVD-generated APIs.
|
||||||
|
func (uart *UART) setInversion(config UARTConfig) {
|
||||||
|
if config.InvertTX {
|
||||||
|
uart.Bus.SetCTRLA_TXINV(1)
|
||||||
|
} else {
|
||||||
|
uart.Bus.SetCTRLA_TXINV(0)
|
||||||
|
}
|
||||||
|
if config.InvertRX {
|
||||||
|
uart.Bus.SetCTRLA_RXINV(1)
|
||||||
|
} else {
|
||||||
|
uart.Bus.SetCTRLA_RXINV(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build sam && !atsamd51 && !atsame5x
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Hardware inversion is not supported on SAMD21.
|
||||||
|
func (uart *UART) setInversion(config UARTConfig) {
|
||||||
|
}
|
||||||
@@ -56,6 +56,9 @@ func (uart *UART) Configure(config UARTConfig) {
|
|||||||
// Set baud rate
|
// Set baud rate
|
||||||
uart.SetBaudRate(config.BaudRate)
|
uart.SetBaudRate(config.BaudRate)
|
||||||
|
|
||||||
|
// Configure RX/TX inversion
|
||||||
|
uart.setInversion(config)
|
||||||
|
|
||||||
// Enable USART port, tx, rx and rx interrupts
|
// 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)
|
uart.Bus.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//go:build stm32 && !(stm32f1 || stm32f4)
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Configure UART TX/RX line inversion using SVD-generated APIs.
|
||||||
|
func (uart *UART) setInversion(config UARTConfig) {
|
||||||
|
if config.InvertTX {
|
||||||
|
uart.Bus.SetCR2_TXINV(1)
|
||||||
|
} else {
|
||||||
|
uart.Bus.SetCR2_TXINV(0)
|
||||||
|
}
|
||||||
|
if config.InvertRX {
|
||||||
|
uart.Bus.SetCR2_RXINV(1)
|
||||||
|
} else {
|
||||||
|
uart.Bus.SetCR2_RXINV(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build stm32 && (stm32f1 || stm32f4)
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Hardware inversion is not supported on F1/F4.
|
||||||
|
func (uart *UART) setInversion(config UARTConfig) {
|
||||||
|
}
|
||||||
@@ -13,6 +13,8 @@ type UARTConfig struct {
|
|||||||
RX Pin
|
RX Pin
|
||||||
RTS Pin
|
RTS Pin
|
||||||
CTS Pin
|
CTS Pin
|
||||||
|
InvertTX bool // Invert TX line (active low becomes active high, etc.)
|
||||||
|
InvertRX bool // Invert RX line (active low becomes active high, etc.)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NullSerial is a serial version of /dev/null (or null router): it drops
|
// NullSerial is a serial version of /dev/null (or null router): it drops
|
||||||
|
|||||||
Reference in New Issue
Block a user