@@ -33,7 +33,6 @@ type UART struct {
3333
3434 // auxiliary state data used internally
3535 configured bool
36- msbFirst bool
3736 transmitting volatile.Register32
3837}
3938
@@ -46,6 +45,11 @@ func (uart *UART) resetTransmitting() {
4645 uart .Bus .GLOBAL .ClearBits (nxp .LPUART_GLOBAL_RST )
4746}
4847
48+ func (uart * UART ) usesConfig (c UARTConfig ) bool {
49+ return uart .configured && uart .baud == c .BaudRate &&
50+ uart .rx == c .RX && uart .tx == c .TX
51+ }
52+
4953// Configure initializes a UART with the given UARTConfig and other default
5054// settings.
5155func (uart * UART ) Configure (config UARTConfig ) {
@@ -56,13 +60,19 @@ func (uart *UART) Configure(config UARTConfig) {
5660 if config .BaudRate == 0 {
5761 config .BaudRate = defaultUartFreq
5862 }
59- uart .baud = config .BaudRate
6063
6164 // use default UART pins if not specified
6265 if config .RX == 0 && config .TX == 0 {
6366 config .RX = UART_RX_PIN
6467 config .TX = UART_TX_PIN
6568 }
69+
70+ // Do not reconfigure pins and device buffers if duplicate config provided.
71+ if uart .usesConfig (config ) {
72+ return
73+ }
74+
75+ uart .baud = config .BaudRate
6676 uart .rx = config .RX
6777 uart .tx = config .TX
6878
@@ -77,84 +87,58 @@ func (uart *UART) Configure(config UARTConfig) {
7787 // reset all internal logic and registers
7888 uart .resetTransmitting ()
7989
90+ // disable until we have finished configuring registers
91+ uart .Bus .CTRL .Set (0 )
92+
8093 // determine the baud rate and over-sample divisors
8194 sbr , osr := uart .getBaudRateDivisor (uart .baud )
8295
83- // for now we assume some configuration. in particular:
84- // Data bits -> 8-bit
85- // Parity bit -> None (parity bit generation disabled)
86- // Stop bits -> 1 stop bit
87- // MSB first -> false
88- // RX idle type -> idle count starts after start bit
89- // RX idle config -> 1 idle character
90- // RX RTS enabled -> false
91- // TX CTS enabled -> false
92-
9396 // set the baud rate, over-sample configuration, stop bits
9497 baudBits := (((osr - 1 ) << nxp .LPUART_BAUD_OSR_Pos ) & nxp .LPUART_BAUD_OSR_Msk ) |
95- ((sbr << nxp .LPUART_BAUD_SBR_Pos ) & nxp .LPUART_BAUD_SBR_Msk ) |
96- ((nxp .LPUART_BAUD_SBNS_SBNS_0 << nxp .LPUART_BAUD_SBNS_Pos ) & nxp .LPUART_BAUD_SBNS_Msk )
98+ ((sbr << nxp .LPUART_BAUD_SBR_Pos ) & nxp .LPUART_BAUD_SBR_Msk )
9799 if osr <= 8 {
98100 // if OSR less than or equal to 8, we must enable sampling on both edges
99101 baudBits |= nxp .LPUART_BAUD_BOTHEDGE
100102 }
101103 uart .Bus .BAUD .Set (baudBits )
102-
103104 uart .Bus .PINCFG .Set (0 ) // disable triggers
104105
105- // use 8 data bits, disable parity, use 1 idle char, and idle count starts
106- // after start bit
107- ctrlBits := uint32 (((nxp .LPUART_CTRL_M_M_0 << nxp .LPUART_CTRL_M_Pos ) & nxp .LPUART_CTRL_M_Msk ) |
108- ((nxp .LPUART_CTRL_PE_PE_0 << nxp .LPUART_CTRL_PE_Pos ) & nxp .LPUART_CTRL_PE_Msk ) |
109- ((nxp .LPUART_CTRL_ILT_ILT_0 << nxp .LPUART_CTRL_ILT_Pos ) & nxp .LPUART_CTRL_ILT_Msk ) |
110- ((nxp .LPUART_CTRL_IDLECFG_IDLECFG_0 << nxp .LPUART_CTRL_IDLECFG_Pos ) & nxp .LPUART_CTRL_IDLECFG_Msk ))
111- uart .Bus .CTRL .Set (ctrlBits )
112-
106+ // configure watermarks, flush and enable TX/RX FIFOs
113107 rxSize , txSize := uart .getFIFOSize ()
114-
115108 rxWater := rxSize >> 1
116109 if rxWater > uint32 (nxp .LPUART_FIFO_RXFIFOSIZE_Msk >> nxp .LPUART_FIFO_RXFIFOSIZE_Pos ) {
117110 rxWater = uint32 (nxp .LPUART_FIFO_RXFIFOSIZE_Msk >> nxp .LPUART_FIFO_RXFIFOSIZE_Pos )
118111 }
119-
120112 txWater := txSize >> 1
121113 if txWater > uint32 (nxp .LPUART_FIFO_TXFIFOSIZE_Msk >> nxp .LPUART_FIFO_TXFIFOSIZE_Pos ) {
122114 txWater = uint32 (nxp .LPUART_FIFO_TXFIFOSIZE_Msk >> nxp .LPUART_FIFO_TXFIFOSIZE_Pos )
123115 }
124-
125116 uart .Bus .WATER .Set (
126117 ((rxWater << nxp .LPUART_WATER_RXWATER_Pos ) & nxp .LPUART_WATER_RXWATER_Msk ) |
127118 ((txWater << nxp .LPUART_WATER_TXWATER_Pos ) & nxp .LPUART_WATER_TXWATER_Msk ))
119+ uart .Bus .FIFO .SetBits (nxp .LPUART_FIFO_RXFE | nxp .LPUART_FIFO_TXFE |
120+ nxp .LPUART_FIFO_RXFLUSH | nxp .LPUART_FIFO_TXFLUSH )
128121
129- // enable TX/RX FIFOs
130- uart .Bus .FIFO .SetBits (nxp .LPUART_FIFO_RXFE | nxp .LPUART_FIFO_TXFE )
131-
132- // flush TX/RX FIFOs
133- uart .Bus .FIFO .SetBits (nxp .LPUART_FIFO_RXFLUSH | nxp .LPUART_FIFO_TXFLUSH )
122+ // for now we assume some configuration. in particular:
123+ // Data bits -> 8-bit
124+ // Parity bit -> None (parity bit generation disabled)
125+ // Stop bits -> 1 stop bit
126+ // MSB first -> false
127+ // RX idle type -> idle count starts after start bit
128+ // RX idle config -> 1 idle character
129+ // RX RTS enabled -> false
130+ // TX CTS enabled -> false
134131
135- uart .Bus .MODIR .SetBits ( // set the CTS configuration/TX CTS source
136- ((nxp .LPUART_MODIR_TXCTSC_TXCTSC_0 << nxp .LPUART_MODIR_TXCTSC_Pos ) & nxp .LPUART_MODIR_TXCTSC_Msk ) |
137- ((nxp .LPUART_MODIR_TXCTSSRC_TXCTSSRC_0 << nxp .LPUART_MODIR_TXCTSSRC_Pos ) & nxp .LPUART_MODIR_TXCTSSRC_Msk ))
132+ // enable transmitter, receiver functions
133+ uart .Bus .CTRL .Set (nxp .LPUART_CTRL_TE | nxp .LPUART_CTRL_RE |
134+ // enable receiver, idle line interrupts
135+ nxp .LPUART_CTRL_RIE | nxp .LPUART_CTRL_ILIE )
138136
139137 // clear all status flags
140- stat := uint32 (nxp .LPUART_STAT_RXEDGIF_Msk | nxp .LPUART_STAT_IDLE_Msk | nxp .LPUART_STAT_OR_Msk |
141- nxp .LPUART_STAT_NF_Msk | nxp .LPUART_STAT_FE_Msk | nxp .LPUART_STAT_PF_Msk |
142- nxp .LPUART_STAT_LBKDIF_Msk | nxp .LPUART_STAT_MA1F_Msk | nxp .LPUART_STAT_MA2F_Msk )
143-
144- // set data bits order
145- if uart .msbFirst {
146- stat |= nxp .LPUART_STAT_MSBF
147- } else {
148- stat &^= nxp .LPUART_STAT_MSBF
149- }
150-
151- uart .Bus .STAT .SetBits (stat )
152-
153- // enable RX/TX functions
154- uart .Bus .CTRL .SetBits (nxp .LPUART_CTRL_TE | nxp .LPUART_CTRL_RE )
138+ uart .Bus .STAT .Set (uart .Bus .STAT .Get ())
155139
156- // enable RX IRQ
157- uart .Interrupt .SetPriority (0xc0 )
140+ // enable RX interrupt
141+ uart .Interrupt .SetPriority (0xC0 )
158142 uart .Interrupt .Enable ()
159143
160144 uart .configured = true
@@ -211,13 +195,13 @@ func (uart *UART) WriteByte(c byte) error {
211195// corresponding baud rate divisor (1..8191) that best partition a given baud
212196// rate into equal intervals.
213197//
214- // This is an integral (i.e. non-floating point) port of the logic at the
198+ // This is an integral (non-floating point) translation of the logic at the
215199// beginning of:
216200// void HardwareSerial::begin(uint32_t baud, uint16_t format)
217201// (from Teensyduino: `cores/teensy4/HardwareSerial.cpp`)
218202//
219- // We don't want to risk using floating point here in the machine package in
220- // case it gets called before the FPU or interrupts are ready (e.g., init()) .
203+ // We don't want to use floating point here in case it gets called from an ISR
204+ // or very early during system init.
221205func (uart * UART ) getBaudRateDivisor (baudRate uint32 ) (sbr uint32 , osr uint32 ) {
222206 const clock = 24000000 // UART is muxed to 24 MHz OSC
223207 err := uint32 (0xFFFFFFFF )
0 commit comments