diff --git a/src/machine/board_arduino_nano33.go b/src/machine/board_arduino_nano33.go index fba4e200..e70f5e8e 100644 --- a/src/machine/board_arduino_nano33.go +++ b/src/machine/board_arduino_nano33.go @@ -68,10 +68,10 @@ const ( // UART1 on the Arduino Nano 33 connects to the onboard NINA-W102 WiFi chip. var ( - UART1 = UART{Bus: sam.SERCOM5_USART, + UART1 = UART{ Buffer: NewRingBuffer(), - Mode: PinSERCOMAlt, - IRQVal: sam.IRQ_SERCOM5, + Bus: sam.SERCOM5_USART, + SERCOM: 5, } ) @@ -88,10 +88,10 @@ func handleUART1() { // UART2 on the Arduino Nano 33 connects to the normal TX/RX pins. var ( - UART2 = UART{Bus: sam.SERCOM3_USART, + UART2 = UART{ Buffer: NewRingBuffer(), - Mode: PinSERCOMAlt, - IRQVal: sam.IRQ_SERCOM3, + Bus: sam.SERCOM3_USART, + SERCOM: 3, } ) diff --git a/src/machine/board_circuitplay_express.go b/src/machine/board_circuitplay_express.go index 6f7e34a1..9041ef88 100644 --- a/src/machine/board_circuitplay_express.go +++ b/src/machine/board_circuitplay_express.go @@ -70,10 +70,10 @@ const ( // UART1 on the Circuit Playground Express. var ( - UART1 = UART{Bus: sam.SERCOM1_USART, + UART1 = UART{ Buffer: NewRingBuffer(), - Mode: PinSERCOM, - IRQVal: sam.IRQ_SERCOM1, + Bus: sam.SERCOM4_USART, + SERCOM: 4, } ) diff --git a/src/machine/board_feather-m0.go b/src/machine/board_feather-m0.go index 57704cc5..97af7f90 100644 --- a/src/machine/board_feather-m0.go +++ b/src/machine/board_feather-m0.go @@ -53,10 +53,10 @@ const ( // UART1 on the Feather M0. var ( - UART1 = UART{Bus: sam.SERCOM1_USART, + UART1 = UART{ Buffer: NewRingBuffer(), - Mode: PinSERCOM, - IRQVal: sam.IRQ_SERCOM1, + Bus: sam.SERCOM1_USART, + SERCOM: 1, } ) diff --git a/src/machine/board_itsybitsy-m0.go b/src/machine/board_itsybitsy-m0.go index 0d7248c6..3238d203 100644 --- a/src/machine/board_itsybitsy-m0.go +++ b/src/machine/board_itsybitsy-m0.go @@ -55,10 +55,10 @@ const ( // UART1 on the ItsyBitsy M0. var ( - UART1 = UART{Bus: sam.SERCOM1_USART, + UART1 = UART{ Buffer: NewRingBuffer(), - Mode: PinSERCOM, - IRQVal: sam.IRQ_SERCOM1, + Bus: sam.SERCOM1_USART, + SERCOM: 1, } ) diff --git a/src/machine/board_trinket.go b/src/machine/board_trinket.go index d5acf8ee..f2c62160 100644 --- a/src/machine/board_trinket.go +++ b/src/machine/board_trinket.go @@ -44,10 +44,10 @@ const ( // UART1 on the Trinket M0. var ( - UART1 = UART{Bus: sam.SERCOM1_USART, + UART1 = UART{ Buffer: NewRingBuffer(), - Mode: PinSERCOM, - IRQVal: sam.IRQ_SERCOM1, + Bus: sam.SERCOM0_USART, + SERCOM: 0, } ) diff --git a/src/machine/machine_atsamd21.go b/src/machine/machine_atsamd21.go index 1c5b676b..1975f61c 100644 --- a/src/machine/machine_atsamd21.go +++ b/src/machine/machine_atsamd21.go @@ -364,8 +364,7 @@ func waitADCSync() { type UART struct { Buffer *RingBuffer Bus *sam.SERCOM_USART_Type - Mode PinMode - IRQVal uint32 + SERCOM uint8 } var ( @@ -374,66 +373,54 @@ var ( ) const ( - sampleRate16X = 16 - lsbFirst = 1 - sercomRXPad0 = 0 - sercomRXPad1 = 1 - sercomRXPad2 = 2 - sercomRXPad3 = 3 - sercomTXPad0 = 0 // Only for UART - sercomTXPad2 = 1 // Only for UART - sercomTXPad023 = 2 // Only for UART with TX on PAD0, RTS on PAD2 and CTS on PAD3 + sampleRate16X = 16 + lsbFirst = 1 ) // Configure the UART. -func (uart UART) Configure(config UARTConfig) { +func (uart UART) Configure(config UARTConfig) error { // Default baud rate to 115200. if config.BaudRate == 0 { config.BaudRate = 115200 } - // determine pins - if config.TX == 0 { + // 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 } - // determine pads - var txpad, rxpad int - switch config.TX { - case PA10: - txpad = sercomTXPad2 - case PA18: - txpad = sercomTXPad2 - case PA16: - txpad = sercomTXPad0 - case PA22: - txpad = sercomTXPad0 + // Determine transmit pinout. + txPinMode, txPad, ok := findPinPadMapping(uart.SERCOM, config.TX) + if !ok { + return ErrInvalidOutputPin + } + var txPinOut uint32 + // See table 25-9 of the datasheet (page 459) for how pads are mapped to + // pinout values. + switch txPad { + case 0: + txPinOut = 0 + case 2: + txPinOut = 1 default: - panic("Invalid TX pin for UART") + // TODO: flow control (RTS/CTS) + return ErrInvalidOutputPin } - switch config.RX { - case PA11: - rxpad = sercomRXPad3 - case PA18: - rxpad = sercomRXPad2 - case PA16: - rxpad = sercomRXPad0 - case PA19: - rxpad = sercomRXPad3 - case PA17: - rxpad = sercomRXPad1 - case PA23: - rxpad = sercomRXPad1 - default: - panic("Invalid RX pin for UART") + // Determine receive pinout. + rxPinMode, rxPad, ok := findPinPadMapping(uart.SERCOM, config.RX) + if !ok { + return ErrInvalidInputPin } + // As you can see in table 25-8 on page 459 of the datasheet, input pins + // are mapped directly. + rxPinOut := rxPad // configure pins - config.TX.Configure(PinConfig{Mode: uart.Mode}) - config.RX.Configure(PinConfig{Mode: uart.Mode}) + config.TX.Configure(PinConfig{Mode: txPinMode}) + config.RX.Configure(PinConfig{Mode: rxPinMode}) // reset SERCOM0 uart.Bus.CTRLA.SetBits(sam.SERCOM_USART_CTRLA_SWRST) @@ -467,8 +454,8 @@ func (uart UART) Configure(config UARTConfig) { // set UART pads. This is not same as pins... // SERCOM_USART_CTRLA_TXPO(txPad) | // SERCOM_USART_CTRLA_RXPO(rxPad); - uart.Bus.CTRLA.SetBits(uint32((txpad << sam.SERCOM_USART_CTRLA_TXPO_Pos) | - (rxpad << sam.SERCOM_USART_CTRLA_RXPO_Pos))) + uart.Bus.CTRLA.SetBits((txPinOut << sam.SERCOM_USART_CTRLA_TXPO_Pos) | + (rxPinOut << sam.SERCOM_USART_CTRLA_RXPO_Pos)) // Enable Transceiver and Receiver //sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ; @@ -484,7 +471,12 @@ func (uart UART) Configure(config UARTConfig) { uart.Bus.INTENSET.Set(sam.SERCOM_USART_INTENSET_RXC) // Enable RX IRQ. - arm.EnableIRQ(uart.IRQVal) + // IRQ lines are in the same order as SERCOM instance numbers on SAMD21 + // chips, so the IRQ number can be trivially determined from the SERCOM + // number. + arm.EnableIRQ(sam.IRQ_SERCOM0 + uint32(uart.SERCOM)) + + return nil } // SetBaudRate sets the communication speed for the UART.