3939
4040#include "fsl_lpuart.h"
4141
42- // TODO
42+ //arrays use 0 based numbering: UART is stored at index 0
43+ #define MAX_UART 8
44+ STATIC bool reserved_uart [MAX_UART ];
4345
4446#define UART_CLOCK_FREQ (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U)
4547
@@ -79,126 +81,180 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
7981 mp_float_t timeout , uint16_t receiver_buffer_size , byte * receiver_buffer ,
8082 bool sigint_enabled ) {
8183
82- // TODO: Allow none rx or tx
83-
84- bool have_tx = tx != NULL ;
85- bool have_rx = rx != NULL ;
86- if (!have_tx && !have_rx ) {
87- mp_raise_ValueError (translate ("tx and rx cannot both be None" ));
88- }
89-
9084 self -> baudrate = baudrate ;
9185 self -> character_bits = bits ;
9286 self -> timeout_ms = timeout * 1000 ;
9387
94- const uint32_t rx_count = sizeof (mcu_uart_rx_list ) / sizeof (mcu_periph_obj_t );
95- const uint32_t tx_count = sizeof (mcu_uart_tx_list ) / sizeof (mcu_periph_obj_t );
88+ bool is_onedirection = false;
89+ if (!rx != !tx ) {
90+ is_onedirection = true;
91+ }
92+ bool uart_taken = false;
9693
97- for (uint32_t i = 0 ; i < rx_count ; ++ i ) {
98- if (mcu_uart_rx_list [i ].pin != rx )
99- continue ;
94+ const uint32_t rx_count = MP_ARRAY_SIZE (mcu_uart_rx_list );
95+ const uint32_t tx_count = MP_ARRAY_SIZE (mcu_uart_tx_list );
10096
101- for (uint32_t j = 0 ; j < tx_count ; ++ j ) {
102- if (mcu_uart_tx_list [j ].pin != tx )
97+ // RX loop handles rx only, or both rx and tx
98+ if (rx != NULL ) {
99+ for (uint32_t i = 0 ; i < rx_count ; ++ i ) {
100+ if (mcu_uart_rx_list [i ].pin != rx ) {
103101 continue ;
104-
105- if (mcu_uart_tx_list [j ].bank_idx != mcu_uart_rx_list [i ].bank_idx )
102+ }
103+ // If TX is on, keep looking, else stop
104+ if (tx != NULL ) {
105+ for (uint32_t j = 0 ; j < tx_count ; ++ j ) {
106+ if (mcu_uart_tx_list [j ].pin != tx ||
107+ mcu_uart_tx_list [j ].bank_idx != mcu_uart_rx_list [i ].bank_idx ) {
108+ continue ;
109+ }
110+ // If UART is taken, break (pins never have >1 periph)
111+ if (reserved_uart [mcu_uart_rx_list [i ].bank_idx - 1 ]) {
112+ uart_taken = true;
113+ break ;
114+ }
115+ self -> rx = & mcu_uart_rx_list [i ];
116+ self -> tx = & mcu_uart_tx_list [j ];
117+ break ;
118+ }
119+ if (self -> tx != NULL || uart_taken ) {
120+ break ;
121+ }
122+ } else {
123+ if (reserved_uart [mcu_uart_rx_list [i ].bank_idx - 1 ]) {
124+ uart_taken = true;
125+ break ;
126+ }
127+ self -> rx = & mcu_uart_rx_list [i ];
128+ }
129+ }
130+ } else if (tx != NULL ) {
131+ // TX only case
132+ for (uint32_t i = 0 ; i < tx_count ; ++ i ) {
133+ if (mcu_uart_tx_list [i ].pin != tx ) {
106134 continue ;
107-
108- self -> rx_pin = & mcu_uart_rx_list [i ];
109- self -> tx_pin = & mcu_uart_tx_list [j ];
110-
135+ }
136+ if (reserved_uart [mcu_uart_tx_list [i ].bank_idx - 1 ]) {
137+ uart_taken = true;
138+ break ;
139+ }
140+ self -> tx = & mcu_uart_tx_list [i ];
111141 break ;
112142 }
143+ } else {
144+ mp_raise_ValueError (translate ("Supply at least one UART pin" ));
145+ }
146+
147+ if (uart_taken ) {
148+ mp_raise_RuntimeError (translate ("UART peripheral is already in use" ));
113149 }
114150
115- if (self -> rx_pin == NULL || self -> tx_pin == NULL ) {
151+ if (self -> rx == NULL && self -> tx == NULL ) {
116152 mp_raise_RuntimeError (translate ("Invalid UART pin selection" ));
117153 }
118154
155+ if (is_onedirection && ((rts != NULL ) || (cts != NULL ))) {
156+ mp_raise_RuntimeError (translate ("Both RX and TX required for flow control" ));
157+ }
158+
119159 // Filter for sane settings for RS485
120160 if (rs485_dir != NULL ) {
121- if ((rts != NULL ) || (cts != NULL )) {
122- mp_raise_ValueError (translate ("Cannot specify RTS or CTS in RS485 mode" ));
123- }
124- // For IMXRT the RTS pin is used for RS485 direction
125- rts = rs485_dir ;
161+ if ((rts != NULL ) || (cts != NULL )) {
162+ mp_raise_ValueError (translate ("Cannot specify RTS or CTS in RS485 mode" ));
163+ }
164+ // For IMXRT the RTS pin is used for RS485 direction
165+ rts = rs485_dir ;
126166 }
127167 else {
128- if (rs485_invert ) {
129- mp_raise_ValueError (translate ("RS485 inversion specified when not in RS485 mode" ));
130- }
168+ if (rs485_invert ) {
169+ mp_raise_ValueError (translate ("RS485 inversion specified when not in RS485 mode" ));
170+ }
131171 }
132172
133173 // Now check for RTS/CTS (or overloaded RS485 direction) pin(s)
134- const uint32_t rts_count = sizeof (mcu_uart_rts_list ) / sizeof ( mcu_periph_obj_t );
135- const uint32_t cts_count = sizeof (mcu_uart_cts_list ) / sizeof ( mcu_periph_obj_t );
174+ const uint32_t rts_count = MP_ARRAY_SIZE (mcu_uart_rts_list );
175+ const uint32_t cts_count = MP_ARRAY_SIZE (mcu_uart_cts_list );
136176
137177 if (rts != NULL ) {
138- for (uint32_t i = 0 ; i < rts_count ; ++ i ) {
139- if (mcu_uart_rts_list [i ].bank_idx == self -> rx_pin -> bank_idx ) {
140- if (mcu_uart_rts_list [i ].pin == rts ) {
141- self -> rts_pin = & mcu_uart_rts_list [i ];
142- break ;
143- }
178+ for (uint32_t i = 0 ; i < rts_count ; ++ i ) {
179+ if (mcu_uart_rts_list [i ].bank_idx == self -> rx -> bank_idx ) {
180+ if (mcu_uart_rts_list [i ].pin == rts ) {
181+ self -> rts = & mcu_uart_rts_list [i ];
182+ break ;
183+ }
184+ }
185+ }
186+ if (self -> rts == NULL ){
187+ mp_raise_ValueError (translate ("Selected RTS pin not valid" ));
144188 }
145- }
146- if (self -> rts_pin == NULL )
147- mp_raise_ValueError (translate ("Selected RTS pin not valid" ));
148189 }
149190
150191 if (cts != NULL ) {
151- for (uint32_t i = 0 ; i < cts_count ; ++ i ) {
152- if (mcu_uart_cts_list [i ].bank_idx == self -> rx_pin -> bank_idx ) {
153- if (mcu_uart_cts_list [i ].pin == cts ) {
154- self -> cts_pin = & mcu_uart_cts_list [i ];
155- break ;
156- }
192+ for (uint32_t i = 0 ; i < cts_count ; ++ i ) {
193+ if (mcu_uart_cts_list [i ].bank_idx == self -> rx -> bank_idx ) {
194+ if (mcu_uart_cts_list [i ].pin == cts ) {
195+ self -> cts = & mcu_uart_cts_list [i ];
196+ break ;
197+ }
198+ }
199+ }
200+ if (self -> cts == NULL ){
201+ mp_raise_ValueError (translate ("Selected CTS pin not valid" ));
157202 }
158- }
159- if (self -> cts_pin == NULL )
160- mp_raise_ValueError (translate ("Selected CTS pin not valid" ));
161203 }
162204
163- self -> uart = mcu_uart_banks [self -> tx_pin -> bank_idx - 1 ];
205+ if (self -> rx ) {
206+ self -> uart = mcu_uart_banks [self -> rx -> bank_idx - 1 ];
207+ } else {
208+ self -> uart = mcu_uart_banks [self -> tx -> bank_idx - 1 ];
209+ }
164210
165- config_periph_pin (self -> rx_pin );
166- config_periph_pin (self -> tx_pin );
167- if (self -> rts_pin )
168- config_periph_pin (self -> rts_pin );
169- if (self -> cts_pin )
170- config_periph_pin (self -> cts_pin );
211+ if (self -> rx ) {
212+ config_periph_pin (self -> rx );
213+ }
214+ if (self -> tx ) {
215+ config_periph_pin (self -> tx );
216+ }
217+ if (self -> rts ) {
218+ config_periph_pin (self -> rts );
219+ }
220+ if (self -> cts ) {
221+ config_periph_pin (self -> cts );
222+ }
171223
172224 lpuart_config_t config = { 0 };
173225 LPUART_GetDefaultConfig (& config );
174226
175227 config .dataBitsCount = self -> character_bits == 8 ? kLPUART_EightDataBits : kLPUART_SevenDataBits ;
176228 config .baudRate_Bps = self -> baudrate ;
177- config .enableTx = self -> tx_pin != NULL ;
178- config .enableRx = self -> rx_pin != NULL ;
179- config .enableRxRTS = self -> rts_pin != NULL ;
180- config .enableTxCTS = self -> cts_pin != NULL ;
181- if (self -> rts_pin != NULL )
182- claim_pin (self -> rts_pin -> pin );
183- if (self -> cts_pin != NULL )
184- claim_pin (self -> cts_pin -> pin );
229+ config .enableTx = self -> tx != NULL ;
230+ config .enableRx = self -> rx != NULL ;
231+ config .enableRxRTS = self -> rts != NULL ;
232+ config .enableTxCTS = self -> cts != NULL ;
233+ if (self -> rts != NULL ) {
234+ claim_pin (self -> rts -> pin );
235+ }
236+ if (self -> cts != NULL ) {
237+ claim_pin (self -> cts -> pin );
238+ }
185239
186240 LPUART_Init (self -> uart , & config , UART_CLOCK_FREQ );
187241
188242 // Before we init, setup RS485 direction pin
189243 // ..unfortunately this isn't done by the driver library
190244 uint32_t modir = (self -> uart -> MODIR ) & ~(LPUART_MODIR_TXRTSPOL_MASK | LPUART_MODIR_TXRTSE_MASK );
191245 if (rs485_dir != NULL ) {
192- modir |= LPUART_MODIR_TXRTSE_MASK ;
193- if (rs485_invert )
194- modir |= LPUART_MODIR_TXRTSPOL_MASK ;
246+ modir |= LPUART_MODIR_TXRTSE_MASK ;
247+ if (rs485_invert ) {
248+ modir |= LPUART_MODIR_TXRTSPOL_MASK ;
249+ }
195250 }
196251 self -> uart -> MODIR = modir ;
197252
198- if (self -> tx_pin != NULL )
199- claim_pin (self -> tx_pin -> pin );
253+ if (self -> tx != NULL ) {
254+ claim_pin (self -> tx -> pin );
255+ }
200256
201- if (self -> rx_pin != NULL ) {
257+ if (self -> rx != NULL ) {
202258 // The LPUART ring buffer wastes one byte to distinguish between full and empty.
203259 self -> ringbuf = gc_alloc (receiver_buffer_size + 1 , false, true /*long-lived*/ );
204260
@@ -212,12 +268,12 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
212268 // the capacity is one less than the size.
213269 LPUART_TransferStartRingBuffer (self -> uart , & self -> handle , self -> ringbuf , receiver_buffer_size + 1 );
214270
215- claim_pin (self -> rx_pin -> pin );
271+ claim_pin (self -> rx -> pin );
216272 }
217273}
218274
219275bool common_hal_busio_uart_deinited (busio_uart_obj_t * self ) {
220- return self -> rx_pin == NULL && self -> tx_pin == NULL ;
276+ return self -> rx == NULL && self -> tx == NULL ;
221277}
222278
223279void common_hal_busio_uart_deinit (busio_uart_obj_t * self ) {
@@ -229,16 +285,16 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
229285
230286 gc_free (self -> ringbuf );
231287
232- // reset_pin_number(self->rx_pin );
233- // reset_pin_number(self->tx_pin );
288+ // reset_pin_number(self->rx );
289+ // reset_pin_number(self->tx );
234290
235- self -> rx_pin = NULL ;
236- self -> tx_pin = NULL ;
291+ self -> rx = NULL ;
292+ self -> tx = NULL ;
237293}
238294
239295// Read characters.
240296size_t common_hal_busio_uart_read (busio_uart_obj_t * self , uint8_t * data , size_t len , int * errcode ) {
241- if (self -> rx_pin == NULL ) {
297+ if (self -> rx == NULL ) {
242298 mp_raise_ValueError (translate ("No RX pin" ));
243299 }
244300
@@ -284,7 +340,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
284340
285341// Write characters.
286342size_t common_hal_busio_uart_write (busio_uart_obj_t * self , const uint8_t * data , size_t len , int * errcode ) {
287- if (self -> tx_pin == NULL ) {
343+ if (self -> tx == NULL ) {
288344 mp_raise_ValueError (translate ("No TX pin" ));
289345 }
290346
@@ -320,7 +376,7 @@ void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
320376}
321377
322378bool common_hal_busio_uart_ready_to_tx (busio_uart_obj_t * self ) {
323- if (self -> tx_pin == NULL ) {
379+ if (self -> tx == NULL ) {
324380 return false;
325381 }
326382
0 commit comments