39
39
#include "periph.h"
40
40
41
41
#include "fsl_lpuart.h"
42
+ #include "fsl_gpio.h"
43
+ // ==========================================================
44
+ // Debug code
45
+ // ==========================================================
46
+ #define ENABLE_DEBUG_PRINTING 0
47
+ #if ENABLE_DEBUG_PRINTING
48
+ #define DBGPrintf mp_printf
49
+ #else
50
+ #define DBGPrintf (p ,...)
51
+ #endif
52
+
42
53
43
54
// arrays use 0 based numbering: UART1 is stored at index 0
44
55
#define MAX_UART 8
@@ -90,6 +101,7 @@ void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) {
90
101
common_hal_never_reset_pin (self -> rx );
91
102
common_hal_never_reset_pin (self -> rts );
92
103
common_hal_never_reset_pin (self -> cts );
104
+ common_hal_never_reset_pin (self -> rs485_dir );
93
105
}
94
106
95
107
void common_hal_busio_uart_construct (busio_uart_obj_t * self ,
@@ -108,9 +120,12 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
108
120
mp_raise_ValueError (translate ("Invalid word/bit length" ));
109
121
}
110
122
123
+ DBGPrintf (& mp_plat_print , "uart_construct: tx:%p rx:%p rts:%p cts:%p rs485:%p\n" , tx , rx , rts , cts , rs485_dir );
124
+
111
125
// We are transmitting one direction if one pin is NULL and the other isn't.
112
126
bool is_onedirection = (rx == NULL ) != (tx == NULL );
113
127
bool uart_taken = false;
128
+ bool use_rts_for_rs485 = false;
114
129
115
130
const uint32_t rx_count = MP_ARRAY_SIZE (mcu_uart_rx_list );
116
131
const uint32_t tx_count = MP_ARRAY_SIZE (mcu_uart_tx_list );
@@ -187,11 +202,14 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
187
202
188
203
// Filter for sane settings for RS485
189
204
if (rs485_dir != NULL ) {
205
+ DBGPrintf (& mp_plat_print , "\t(485 pin): gpio:%p #:%x Mux: %x %x cfg:%x reset:%x %x\n" ,
206
+ rs485_dir -> gpio , rs485_dir -> number , rs485_dir -> mux_idx , rs485_dir -> mux_reg , rs485_dir -> cfg_reg ,
207
+ rs485_dir -> mux_reset , rs485_dir -> pad_reset );
190
208
if ((rts != NULL ) || (cts != NULL )) {
191
209
mp_raise_ValueError (translate ("Cannot specify RTS or CTS in RS485 mode" ));
192
210
}
193
- // For IMXRT the RTS pin is used for RS485 direction
194
- rts = rs485_dir ;
211
+ // For IMXRT the RTS pin is used for RS485 direction ???? - Can be will try
212
+ // it if this is an rts pin.
195
213
} else {
196
214
if (rs485_invert ) {
197
215
mp_raise_ValueError (translate ("RS485 inversion specified when not in RS485 mode" ));
@@ -202,16 +220,22 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
202
220
const uint32_t rts_count = MP_ARRAY_SIZE (mcu_uart_rts_list );
203
221
const uint32_t cts_count = MP_ARRAY_SIZE (mcu_uart_cts_list );
204
222
205
- if (rts != NULL ) {
223
+ if (( rts != NULL ) || ( rs485_dir != NULL ) ) {
206
224
for (uint32_t i = 0 ; i < rts_count ; ++ i ) {
207
225
if (mcu_uart_rts_list [i ].bank_idx == rx_config -> bank_idx ) {
208
226
if (mcu_uart_rts_list [i ].pin == rts ) {
209
227
rts_config = & mcu_uart_rts_list [i ];
210
228
break ;
229
+ } else if (mcu_uart_rts_list [i ].pin == rs485_dir ) {
230
+ rts_config = & mcu_uart_rts_list [i ];
231
+ use_rts_for_rs485 = true;
232
+ rts = rs485_dir ;
233
+ rs485_dir = NULL ;
234
+ break ;
211
235
}
212
236
}
213
237
}
214
- if (rts_config == NULL ) {
238
+ if (( rts != NULL ) && ( rts_config == NULL ) ) {
215
239
mp_raise_ValueError_varg (translate ("Invalid %q pin" ), MP_QSTR_RTS );
216
240
}
217
241
}
@@ -225,7 +249,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
225
249
}
226
250
}
227
251
}
228
- if (cts == NULL ) {
252
+ if (cts_config == NULL ) {
229
253
mp_raise_ValueError_varg (translate ("Invalid %q pin" ), MP_QSTR_CTS );
230
254
}
231
255
}
@@ -257,7 +281,32 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
257
281
config_periph_pin (cts_config );
258
282
self -> cts = cts ;
259
283
}
284
+ if (rs485_dir ) {
285
+ DBGPrintf (& mp_plat_print , "\tInit rs485 pin\n" );
286
+ // lets configure this pin as standard GPIO output pin.
287
+ claim_pin (rs485_dir );
288
+
289
+ #define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_ALT5 5U
290
+ IOMUXC_SetPinMux (rs485_dir -> mux_reg , IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_ALT5 , 0 , 0 , 0 , 0 );
291
+ DBGPrintf (& mp_plat_print , "\tAfter IOMUXC_SetPinMux\n" );
292
+ IOMUXC_SetPinConfig (0 , 0 , 0 , 0 , rs485_dir -> cfg_reg ,
293
+ IOMUXC_SW_PAD_CTL_PAD_HYS (1 )
294
+ | IOMUXC_SW_PAD_CTL_PAD_PUS (0 )
295
+ | IOMUXC_SW_PAD_CTL_PAD_PUE (0 )
296
+ | IOMUXC_SW_PAD_CTL_PAD_PKE (1 )
297
+ | IOMUXC_SW_PAD_CTL_PAD_ODE (0 )
298
+ | IOMUXC_SW_PAD_CTL_PAD_SPEED (2 )
299
+ | IOMUXC_SW_PAD_CTL_PAD_DSE (1 )
300
+ | IOMUXC_SW_PAD_CTL_PAD_SRE (0 ));
301
+ DBGPrintf (& mp_plat_print , "\tAfter IOMUXC_SetPinConfig\n" );
302
+
303
+ const gpio_pin_config_t config = { kGPIO_DigitalOutput , rs485_invert , kGPIO_NoIntmode };
304
+ GPIO_PinInit (rs485_dir -> gpio , rs485_dir -> number , & config );
305
+ DBGPrintf (& mp_plat_print , "\tAfter GPIO_PinInit\n" );
306
+ self -> rs485_dir = rs485_dir ;
307
+ self -> rs485_invert = rs485_invert ;
260
308
309
+ }
261
310
lpuart_config_t config = { 0 };
262
311
LPUART_GetDefaultConfig (& config );
263
312
@@ -279,7 +328,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
279
328
// Before we init, setup RS485 direction pin
280
329
// ..unfortunately this isn't done by the driver library
281
330
uint32_t modir = (self -> uart -> MODIR ) & ~(LPUART_MODIR_TXRTSPOL_MASK | LPUART_MODIR_TXRTSE_MASK );
282
- if (rs485_dir != NULL ) {
331
+ if (use_rts_for_rs485 ) {
283
332
modir |= LPUART_MODIR_TXRTSE_MASK ;
284
333
if (rs485_invert ) {
285
334
modir |= LPUART_MODIR_TXRTSPOL_MASK ;
@@ -311,6 +360,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
311
360
312
361
claim_pin (self -> rx );
313
362
}
363
+ DBGPrintf (& mp_plat_print , "\t<< Init completed >>\n" );
314
364
}
315
365
316
366
bool common_hal_busio_uart_deinited (busio_uart_obj_t * self ) {
@@ -330,9 +380,16 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
330
380
331
381
common_hal_reset_pin (self -> rx );
332
382
common_hal_reset_pin (self -> tx );
383
+ common_hal_reset_pin (self -> cts );
384
+ common_hal_reset_pin (self -> rts );
385
+ common_hal_reset_pin (self -> rs485_dir );
333
386
334
387
self -> rx = NULL ;
335
388
self -> tx = NULL ;
389
+ self -> cts = NULL ;
390
+ self -> rts = NULL ;
391
+ self -> rs485_dir = NULL ;
392
+
336
393
}
337
394
338
395
// Read characters.
@@ -371,6 +428,10 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
371
428
uint32_t recvd = 0 ;
372
429
LPUART_TransferGetReceiveCount (self -> uart , & self -> handle , & recvd );
373
430
LPUART_TransferAbortReceive (self -> uart , & self -> handle );
431
+ if (recvd == 0 ) {
432
+ * errcode = EAGAIN ;
433
+ return MP_STREAM_ERROR ;
434
+ }
374
435
return recvd ;
375
436
}
376
437
@@ -393,8 +454,21 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data,
393
454
if (self -> tx == NULL ) {
394
455
mp_raise_ValueError (translate ("No TX pin" ));
395
456
}
396
-
397
- LPUART_WriteBlocking (self -> uart , data , len );
457
+ if (self -> rs485_dir && len ) {
458
+ GPIO_PinWrite (self -> rs485_dir -> gpio , self -> rs485_dir -> number , !self -> rs485_invert );
459
+ LPUART_WriteBlocking (self -> uart , data , len );
460
+ // Probably need to verify we have completed output.
461
+ uint32_t dont_hang_count = 0xffff ;
462
+ while (dont_hang_count -- ) {
463
+ if (LPUART_GetStatusFlags (self -> uart ) & kLPUART_TransmissionCompleteFlag ) {
464
+ break ; // hardware says it completed.
465
+ }
466
+ }
467
+ GPIO_PinWrite (self -> rs485_dir -> gpio , self -> rs485_dir -> number , self -> rs485_invert );
468
+ } else {
469
+ // could combine with above but would go through two ifs
470
+ LPUART_WriteBlocking (self -> uart , data , len );
471
+ }
398
472
399
473
return len ;
400
474
}
0 commit comments