Skip to content

Commit 3745fb1

Browse files
aykevldeadprogram
authored andcommitted
machine/atsamd51: switch UART to use new pin configuration
This makes UART configuration much more flexible. I confirmed that UART1 and UART2 still work with this change on the ItsyBitsy M4.
1 parent a5ed993 commit 3745fb1

File tree

1 file changed

+37
-50
lines changed

1 file changed

+37
-50
lines changed

src/machine/machine_atsamd51.go

Lines changed: 37 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -627,90 +627,75 @@ func (a ADC) getADCChannel() uint8 {
627627
type UART struct {
628628
Buffer *RingBuffer
629629
Bus *sam.SERCOM_USART_INT_Type
630-
Mode PinMode
630+
SERCOM uint8
631631
}
632632

633633
var (
634634
// UART0 is actually a USB CDC interface.
635635
UART0 = USBCDC{Buffer: NewRingBuffer()}
636636

637637
// The first hardware serial port on the SAMD51. Uses the SERCOM3 interface.
638-
UART1 = UART{Bus: sam.SERCOM3_USART_INT,
638+
UART1 = UART{
639639
Buffer: NewRingBuffer(),
640-
Mode: PinSERCOMAlt,
640+
Bus: sam.SERCOM3_USART_INT,
641+
SERCOM: 3,
641642
}
642643

643644
// The second hardware serial port on the SAMD51. Uses the SERCOM0 interface.
644645
UART2 = UART{
645646
Buffer: NewRingBuffer(),
646647
Bus: sam.SERCOM0_USART_INT,
647-
Mode: PinSERCOMAlt,
648+
SERCOM: 0,
648649
}
649650
)
650651

651652
const (
652-
sampleRate16X = 16
653-
lsbFirst = 1
654-
sercomRXPad0 = 0
655-
sercomRXPad1 = 1
656-
sercomRXPad2 = 2
657-
sercomRXPad3 = 3
658-
sercomTXPad0 = 0 // Only for UART
659-
sercomTXPad2 = 1 // Only for UART
660-
sercomTXPad023 = 2 // Only for UART with TX on PAD0, RTS on PAD2 and CTS on PAD3
653+
sampleRate16X = 16
654+
lsbFirst = 1
661655
)
662656

663657
// Configure the UART.
664-
func (uart UART) Configure(config UARTConfig) {
658+
func (uart UART) Configure(config UARTConfig) error {
665659
// Default baud rate to 115200.
666660
if config.BaudRate == 0 {
667661
config.BaudRate = 115200
668662
}
669663

670664
// determine pins
671-
if config.TX == 0 {
665+
if config.TX == 0 && config.RX == 0 {
672666
// use default pins
673667
config.TX = UART_TX_PIN
674668
config.RX = UART_RX_PIN
675669
}
676670

677-
// determine pads
678-
var txpad, rxpad int
679-
switch config.TX {
680-
case PA04:
681-
txpad = sercomTXPad0
682-
case PA10:
683-
txpad = sercomTXPad2
684-
case PA18:
685-
txpad = sercomTXPad2
686-
case PA16:
687-
txpad = sercomTXPad0
671+
// Determine transmit pinout.
672+
txPinMode, txPad, ok := findPinPadMapping(uart.SERCOM, config.TX)
673+
if !ok {
674+
return ErrInvalidOutputPin
675+
}
676+
var txPinOut uint32
677+
// See CTRLA.RXPO bits of the SERCOM USART peripheral (page 945-946) for how
678+
// pads are mapped to pinout values.
679+
switch txPad {
680+
case 0:
681+
txPinOut = 0
688682
default:
689-
panic("Invalid TX pin for UART")
683+
// TODO: flow control (RTS/CTS)
684+
return ErrInvalidOutputPin
690685
}
691686

692-
switch config.RX {
693-
case PA06:
694-
rxpad = sercomRXPad2
695-
case PA07:
696-
rxpad = sercomRXPad3
697-
case PA11:
698-
rxpad = sercomRXPad3
699-
case PA18:
700-
rxpad = sercomRXPad2
701-
case PA16:
702-
rxpad = sercomRXPad0
703-
case PA19:
704-
rxpad = sercomRXPad3
705-
case PA17:
706-
rxpad = sercomRXPad1
707-
default:
708-
panic("Invalid RX pin for UART")
687+
// Determine receive pinout.
688+
rxPinMode, rxPad, ok := findPinPadMapping(uart.SERCOM, config.RX)
689+
if !ok {
690+
return ErrInvalidInputPin
709691
}
692+
// As you can see in the CTRLA.RXPO bits of the SERCOM USART peripheral
693+
// (page 945), input pins are mapped directly.
694+
rxPinOut := rxPad
710695

711696
// configure pins
712-
config.TX.Configure(PinConfig{Mode: uart.Mode})
713-
config.RX.Configure(PinConfig{Mode: uart.Mode})
697+
config.TX.Configure(PinConfig{Mode: txPinMode})
698+
config.RX.Configure(PinConfig{Mode: rxPinMode})
714699

715700
// reset SERCOM0
716701
uart.Bus.CTRLA.SetBits(sam.SERCOM_USART_INT_CTRLA_SWRST)
@@ -745,8 +730,8 @@ func (uart UART) Configure(config UARTConfig) {
745730
// set UART pads. This is not same as pins...
746731
// SERCOM_USART_CTRLA_TXPO(txPad) |
747732
// SERCOM_USART_CTRLA_RXPO(rxPad);
748-
uart.Bus.CTRLA.SetBits(uint32((txpad << sam.SERCOM_USART_INT_CTRLA_TXPO_Pos) |
749-
(rxpad << sam.SERCOM_USART_INT_CTRLA_RXPO_Pos)))
733+
uart.Bus.CTRLA.SetBits((txPinOut << sam.SERCOM_USART_INT_CTRLA_TXPO_Pos) |
734+
(rxPinOut << sam.SERCOM_USART_INT_CTRLA_RXPO_Pos))
750735

751736
// Enable Transceiver and Receiver
752737
//sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;
@@ -762,8 +747,8 @@ func (uart UART) Configure(config UARTConfig) {
762747
uart.Bus.INTENSET.Set(sam.SERCOM_USART_INT_INTENSET_RXC)
763748

764749
// Enable RX IRQ.
765-
switch uart.Bus {
766-
case sam.SERCOM0_USART_INT:
750+
switch uart.SERCOM {
751+
case 0:
767752
arm.EnableIRQ(sam.IRQ_SERCOM0_0)
768753
arm.EnableIRQ(sam.IRQ_SERCOM0_1)
769754
arm.EnableIRQ(sam.IRQ_SERCOM0_2)
@@ -775,6 +760,8 @@ func (uart UART) Configure(config UARTConfig) {
775760
arm.EnableIRQ(sam.IRQ_SERCOM3_2)
776761
arm.EnableIRQ(sam.IRQ_SERCOM3_OTHER)
777762
}
763+
764+
return nil
778765
}
779766

780767
// SetBaudRate sets the communication speed for the UART.

0 commit comments

Comments
 (0)