39
39
40
40
#include "fsl_lpuart.h"
41
41
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 ];
43
45
44
46
#define UART_CLOCK_FREQ (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U)
45
47
@@ -79,126 +81,180 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
79
81
mp_float_t timeout , uint16_t receiver_buffer_size , byte * receiver_buffer ,
80
82
bool sigint_enabled ) {
81
83
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
-
90
84
self -> baudrate = baudrate ;
91
85
self -> character_bits = bits ;
92
86
self -> timeout_ms = timeout * 1000 ;
93
87
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;
96
93
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 );
100
96
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 ) {
103
101
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 ) {
106
134
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 ];
111
141
break ;
112
142
}
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" ));
113
149
}
114
150
115
- if (self -> rx_pin == NULL || self -> tx_pin == NULL ) {
151
+ if (self -> rx == NULL && self -> tx == NULL ) {
116
152
mp_raise_RuntimeError (translate ("Invalid UART pin selection" ));
117
153
}
118
154
155
+ if (is_onedirection && ((rts != NULL ) || (cts != NULL ))) {
156
+ mp_raise_RuntimeError (translate ("Both RX and TX required for flow control" ));
157
+ }
158
+
119
159
// Filter for sane settings for RS485
120
160
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 ;
126
166
}
127
167
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
+ }
131
171
}
132
172
133
173
// 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 );
136
176
137
177
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" ));
144
188
}
145
- }
146
- if (self -> rts_pin == NULL )
147
- mp_raise_ValueError (translate ("Selected RTS pin not valid" ));
148
189
}
149
190
150
191
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" ));
157
202
}
158
- }
159
- if (self -> cts_pin == NULL )
160
- mp_raise_ValueError (translate ("Selected CTS pin not valid" ));
161
203
}
162
204
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
+ }
164
210
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
+ }
171
223
172
224
lpuart_config_t config = { 0 };
173
225
LPUART_GetDefaultConfig (& config );
174
226
175
227
config .dataBitsCount = self -> character_bits == 8 ? kLPUART_EightDataBits : kLPUART_SevenDataBits ;
176
228
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
+ }
185
239
186
240
LPUART_Init (self -> uart , & config , UART_CLOCK_FREQ );
187
241
188
242
// Before we init, setup RS485 direction pin
189
243
// ..unfortunately this isn't done by the driver library
190
244
uint32_t modir = (self -> uart -> MODIR ) & ~(LPUART_MODIR_TXRTSPOL_MASK | LPUART_MODIR_TXRTSE_MASK );
191
245
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
+ }
195
250
}
196
251
self -> uart -> MODIR = modir ;
197
252
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
+ }
200
256
201
- if (self -> rx_pin != NULL ) {
257
+ if (self -> rx != NULL ) {
202
258
// The LPUART ring buffer wastes one byte to distinguish between full and empty.
203
259
self -> ringbuf = gc_alloc (receiver_buffer_size + 1 , false, true /*long-lived*/ );
204
260
@@ -212,12 +268,12 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
212
268
// the capacity is one less than the size.
213
269
LPUART_TransferStartRingBuffer (self -> uart , & self -> handle , self -> ringbuf , receiver_buffer_size + 1 );
214
270
215
- claim_pin (self -> rx_pin -> pin );
271
+ claim_pin (self -> rx -> pin );
216
272
}
217
273
}
218
274
219
275
bool 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 ;
221
277
}
222
278
223
279
void 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) {
229
285
230
286
gc_free (self -> ringbuf );
231
287
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 );
234
290
235
- self -> rx_pin = NULL ;
236
- self -> tx_pin = NULL ;
291
+ self -> rx = NULL ;
292
+ self -> tx = NULL ;
237
293
}
238
294
239
295
// Read characters.
240
296
size_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 ) {
242
298
mp_raise_ValueError (translate ("No RX pin" ));
243
299
}
244
300
@@ -284,7 +340,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
284
340
285
341
// Write characters.
286
342
size_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 ) {
288
344
mp_raise_ValueError (translate ("No TX pin" ));
289
345
}
290
346
@@ -320,7 +376,7 @@ void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
320
376
}
321
377
322
378
bool common_hal_busio_uart_ready_to_tx (busio_uart_obj_t * self ) {
323
- if (self -> tx_pin == NULL ) {
379
+ if (self -> tx == NULL ) {
324
380
return false;
325
381
}
326
382
0 commit comments