21
21
#include "cmsis.h"
22
22
#include "pinmap.h"
23
23
#include "error.h"
24
+ #include "gpio_api.h"
24
25
25
26
/******************************************************************************
26
27
* INITIALIZATION
@@ -51,12 +52,35 @@ static const PinMap PinMap_UART_RX[] = {
51
52
{NC , NC , 0 }
52
53
};
53
54
55
+ static const PinMap PinMap_UART_RTS [] = {
56
+ {P0_22 , UART_1 , 1 },
57
+ {P2_7 , UART_1 , 2 },
58
+ {NC , NC , 0 }
59
+ };
60
+
61
+ static const PinMap PinMap_UART_CTS [] = {
62
+ {P0_17 , UART_1 , 1 },
63
+ {P2_2 , UART_1 , 2 },
64
+ {NC , NC , 0 }
65
+ };
66
+
67
+ #define UART_MCR_RTSEN_MASK (1 << 6)
68
+ #define UART_MCR_CTSEN_MASK (1 << 7)
69
+ #define UART_MCR_FLOWCTRL_MASK (UART_MCR_RTSEN_MASK | UART_MCR_CTSEN_MASK)
70
+
54
71
static uint32_t serial_irq_ids [UART_NUM ] = {0 };
55
72
static uart_irq_handler irq_handler ;
56
73
57
74
int stdio_uart_inited = 0 ;
58
75
serial_t stdio_uart ;
59
76
77
+ struct serial_global_data_s {
78
+ gpio_t sw_rts , sw_cts ;
79
+ uint8_t count , initialized , irq_set_flow , irq_set_api ;
80
+ };
81
+
82
+ static struct serial_global_data_s uart_data [UART_NUM ];
83
+
60
84
void serial_init (serial_t * obj , PinName tx , PinName rx ) {
61
85
int is_stdio_uart = 0 ;
62
86
@@ -106,7 +130,11 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
106
130
case UART_2 : obj -> index = 2 ; break ;
107
131
case UART_3 : obj -> index = 3 ; break ;
108
132
}
109
- obj -> count = 0 ;
133
+ if (!uart_data [obj -> index ].initialized ) {
134
+ uart_data [obj -> index ].sw_rts .pin = NC ;
135
+ uart_data [obj -> index ].sw_cts .pin = NC ;
136
+ uart_data [obj -> index ].initialized = 1 ;
137
+ }
110
138
111
139
is_stdio_uart = (uart == STDIO_UART ) ? (1 ) : (0 );
112
140
@@ -234,7 +262,9 @@ static inline void uart_irq(uint32_t iir, uint32_t index) {
234
262
case 2 : irq_type = RxIrq ; break ;
235
263
default : return ;
236
264
}
237
-
265
+
266
+ if ((RxIrq == irq_type ) && (uart_data [index ].sw_rts .pin != NC ))
267
+ gpio_write (& uart_data [index ].sw_rts , 1 );
238
268
if (serial_irq_ids [index ] != 0 )
239
269
irq_handler (serial_irq_ids [index ], irq_type );
240
270
}
@@ -249,7 +279,7 @@ void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
249
279
serial_irq_ids [obj -> index ] = id ;
250
280
}
251
281
252
- void serial_irq_set (serial_t * obj , SerialIrq irq , uint32_t enable ) {
282
+ static void serial_irq_set_internal (serial_t * obj , SerialIrq irq , uint32_t enable ) {
253
283
IRQn_Type irq_n = (IRQn_Type )0 ;
254
284
uint32_t vector = 0 ;
255
285
switch ((int )obj -> uart ) {
@@ -263,7 +293,7 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
263
293
obj -> uart -> IER |= 1 << irq ;
264
294
NVIC_SetVector (irq_n , vector );
265
295
NVIC_EnableIRQ (irq_n );
266
- } else { // disable
296
+ } else if ( uart_data [ obj -> index ]. irq_set_api + uart_data [ obj -> index ]. irq_set_flow == 0 ) { // disable
267
297
int all_disabled = 0 ;
268
298
SerialIrq other_irq = (irq == RxIrq ) ? (TxIrq ) : (RxIrq );
269
299
obj -> uart -> IER &= ~(1 << irq );
@@ -273,18 +303,30 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
273
303
}
274
304
}
275
305
306
+ void serial_irq_set (serial_t * obj , SerialIrq irq , uint32_t enable ) {
307
+ uart_data [obj -> index ].irq_set_api = enable ;
308
+ serial_irq_set_internal (obj , irq , enable );
309
+ }
310
+
311
+ static void serial_flow_irq_set (serial_t * obj , SerialIrq irq , uint32_t enable ) {
312
+ uart_data [obj -> index ].irq_set_flow = enable ;
313
+ serial_irq_set_internal (obj , irq , enable );
314
+ }
315
+
276
316
/******************************************************************************
277
317
* READ/WRITE
278
318
******************************************************************************/
279
319
int serial_getc (serial_t * obj ) {
280
320
while (!serial_readable (obj ));
321
+ if (NC != uart_data [obj -> index ].sw_rts .pin )
322
+ gpio_write (& uart_data [obj -> index ].sw_rts , 0 );
281
323
return obj -> uart -> RBR ;
282
324
}
283
325
284
326
void serial_putc (serial_t * obj , int c ) {
285
327
while (!serial_writable (obj ));
286
328
obj -> uart -> THR = c ;
287
- obj -> count ++ ;
329
+ uart_data [ obj -> index ]. count ++ ;
288
330
}
289
331
290
332
int serial_readable (serial_t * obj ) {
@@ -293,11 +335,14 @@ int serial_readable(serial_t *obj) {
293
335
294
336
int serial_writable (serial_t * obj ) {
295
337
int isWritable = 1 ;
296
- if (obj -> uart -> LSR & 0x20 )
297
- obj -> count = 0 ;
298
- else if (obj -> count >= 16 )
299
- isWritable = 0 ;
300
-
338
+ if (NC != uart_data [obj -> index ].sw_cts .pin )
339
+ isWritable = gpio_read (& uart_data [obj -> index ].sw_cts ) == 0 ;
340
+ if (isWritable ) {
341
+ if (obj -> uart -> LSR & 0x20 )
342
+ uart_data [obj -> index ].count = 0 ;
343
+ else if (uart_data [obj -> index ].count >= 16 )
344
+ isWritable = 0 ;
345
+ }
301
346
return isWritable ;
302
347
}
303
348
@@ -320,3 +365,47 @@ void serial_break_clear(serial_t *obj) {
320
365
obj -> uart -> LCR &= ~(1 << 6 );
321
366
}
322
367
368
+ void serial_set_flow_control (serial_t * obj , FlowControl type , PinName rxflow , PinName txflow ) {
369
+ // Only UART1 has hardware flow control on LPC176x
370
+ LPC_UART1_TypeDef * uart1 = (uint32_t )obj -> uart == (uint32_t )LPC_UART1 ? LPC_UART1 : NULL ;
371
+ int index = obj -> index ;
372
+
373
+ // First, disable flow control completely
374
+ if (uart1 )
375
+ uart1 -> MCR = uart1 -> MCR & ~UART_MCR_FLOWCTRL_MASK ;
376
+ serial_flow_irq_set (obj , RxIrq , 0 );
377
+ uart_data [index ].sw_rts .pin = uart_data [index ].sw_cts .pin = NC ;
378
+ if (FlowControlNone == type )
379
+ return ;
380
+ // Check type(s) of flow control to use
381
+ UARTName uart_rts = (UARTName )pinmap_find_peripheral (rxflow , PinMap_UART_RTS );
382
+ UARTName uart_cts = (UARTName )pinmap_find_peripheral (txflow , PinMap_UART_CTS );
383
+ if (((FlowControlCTS == type ) || (FlowControlRTSCTS == type )) && (NC != txflow )) {
384
+ // Can this be enabled in hardware?
385
+ if ((UART_1 == uart_cts ) && (NULL != uart1 )) {
386
+ // Enable auto-CTS mode
387
+ uart1 -> MCR |= UART_MCR_CTSEN_MASK ;
388
+ } else {
389
+ // Can't enable in hardware, use software emulation
390
+ gpio_init (& uart_data [index ].sw_cts , txflow , PIN_INPUT );
391
+ }
392
+ }
393
+ if (((FlowControlRTS == type ) || (FlowControlRTSCTS == type )) && (NC != rxflow )) {
394
+ // Enable FIFOs, trigger level of 1 char on RX FIFO
395
+ obj -> uart -> FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
396
+ | 1 << 1 // Rx Fifo Reset
397
+ | 1 << 2 // Tx Fifo Reset
398
+ | 0 << 6 ; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
399
+ // Can this be enabled in hardware?
400
+ if ((UART_1 == uart_rts ) && (NULL != uart1 )) {
401
+ // Enable auto-RTS mode
402
+ uart1 -> MCR |= UART_MCR_RTSEN_MASK ;
403
+ } else { // can't enable in hardware, use software emulation
404
+ gpio_init (& uart_data [index ].sw_rts , rxflow , PIN_OUTPUT );
405
+ gpio_write (& uart_data [index ].sw_rts , 0 );
406
+ // Enable RX interrupt
407
+ serial_flow_irq_set (obj , RxIrq , 1 );
408
+ }
409
+ }
410
+ }
411
+
0 commit comments