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
54
- static uint32_t serial_irq_ids [UART_NUM ] = {0 };
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
+
55
71
static uart_irq_handler irq_handler ;
56
72
57
73
int stdio_uart_inited = 0 ;
58
74
serial_t stdio_uart ;
59
75
76
+ struct serial_global_data_s {
77
+ uint32_t serial_irq_id ;
78
+ gpio_t sw_rts , sw_cts ;
79
+ uint8_t rx_irq_set_flow , rx_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,9 @@ 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
+ uart_data [obj -> index ].sw_rts .pin = NC ;
134
+ uart_data [obj -> index ].sw_cts .pin = NC ;
135
+ serial_set_flow_control (obj , FlowControlNone , NC , NC );
110
136
111
137
is_stdio_uart = (uart == STDIO_UART ) ? (1 ) : (0 );
112
138
@@ -117,7 +143,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
117
143
}
118
144
119
145
void serial_free (serial_t * obj ) {
120
- serial_irq_ids [obj -> index ] = 0 ;
146
+ uart_data [obj -> index ]. serial_irq_id = 0 ;
121
147
}
122
148
123
149
// serial_baud
@@ -251,30 +277,36 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
251
277
/******************************************************************************
252
278
* INTERRUPTS HANDLING
253
279
******************************************************************************/
254
- static inline void uart_irq (uint32_t iir , uint32_t index ) {
280
+ static inline void uart_irq (uint32_t iir , uint32_t index , LPC_UART_TypeDef * puart ) {
255
281
// [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
256
282
SerialIrq irq_type ;
257
283
switch (iir ) {
258
284
case 1 : irq_type = TxIrq ; break ;
259
285
case 2 : irq_type = RxIrq ; break ;
260
286
default : return ;
261
287
}
262
-
263
- if (serial_irq_ids [index ] != 0 )
264
- irq_handler (serial_irq_ids [index ], irq_type );
288
+ if ((RxIrq == irq_type ) && (NC != uart_data [index ].sw_rts .pin )) {
289
+ gpio_write (& uart_data [index ].sw_rts , 1 );
290
+ // Disable interrupt if it wasn't enabled by other part of the application
291
+ if (!uart_data [index ].rx_irq_set_api )
292
+ puart -> IER &= ~(1 << RxIrq );
293
+ }
294
+ if (uart_data [index ].serial_irq_id != 0 )
295
+ if ((irq_type != RxIrq ) || (uart_data [index ].rx_irq_set_api ))
296
+ irq_handler (uart_data [index ].serial_irq_id , irq_type );
265
297
}
266
298
267
- void uart0_irq () {uart_irq ((LPC_UART0 -> IIR >> 1 ) & 0x7 , 0 );}
268
- void uart1_irq () {uart_irq ((LPC_UART1 -> IIR >> 1 ) & 0x7 , 1 );}
269
- void uart2_irq () {uart_irq ((LPC_UART2 -> IIR >> 1 ) & 0x7 , 2 );}
270
- void uart3_irq () {uart_irq ((LPC_UART3 -> IIR >> 1 ) & 0x7 , 3 );}
299
+ void uart0_irq () {uart_irq ((LPC_UART0 -> IIR >> 1 ) & 0x7 , 0 , ( LPC_UART_TypeDef * ) LPC_UART0 );}
300
+ void uart1_irq () {uart_irq ((LPC_UART1 -> IIR >> 1 ) & 0x7 , 1 , ( LPC_UART_TypeDef * ) LPC_UART1 );}
301
+ void uart2_irq () {uart_irq ((LPC_UART2 -> IIR >> 1 ) & 0x7 , 2 , ( LPC_UART_TypeDef * ) LPC_UART2 );}
302
+ void uart3_irq () {uart_irq ((LPC_UART3 -> IIR >> 1 ) & 0x7 , 3 , ( LPC_UART_TypeDef * ) LPC_UART3 );}
271
303
272
304
void serial_irq_handler (serial_t * obj , uart_irq_handler handler , uint32_t id ) {
273
305
irq_handler = handler ;
274
- serial_irq_ids [obj -> index ] = id ;
306
+ uart_data [obj -> index ]. serial_irq_id = id ;
275
307
}
276
308
277
- void serial_irq_set (serial_t * obj , SerialIrq irq , uint32_t enable ) {
309
+ static void serial_irq_set_internal (serial_t * obj , SerialIrq irq , uint32_t enable ) {
278
310
IRQn_Type irq_n = (IRQn_Type )0 ;
279
311
uint32_t vector = 0 ;
280
312
switch ((int )obj -> uart ) {
@@ -288,7 +320,7 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
288
320
obj -> uart -> IER |= 1 << irq ;
289
321
NVIC_SetVector (irq_n , vector );
290
322
NVIC_EnableIRQ (irq_n );
291
- } else { // disable
323
+ } else if (( TxIrq == irq ) || ( uart_data [ obj -> index ]. rx_irq_set_api + uart_data [ obj -> index ]. rx_irq_set_flow == 0 )) { // disable
292
324
int all_disabled = 0 ;
293
325
SerialIrq other_irq = (irq == RxIrq ) ? (TxIrq ) : (RxIrq );
294
326
obj -> uart -> IER &= ~(1 << irq );
@@ -298,18 +330,33 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
298
330
}
299
331
}
300
332
333
+ void serial_irq_set (serial_t * obj , SerialIrq irq , uint32_t enable ) {
334
+ if (RxIrq == irq )
335
+ uart_data [obj -> index ].rx_irq_set_api = enable ;
336
+ serial_irq_set_internal (obj , irq , enable );
337
+ }
338
+
339
+ static void serial_flow_irq_set (serial_t * obj , uint32_t enable ) {
340
+ uart_data [obj -> index ].rx_irq_set_flow = enable ;
341
+ serial_irq_set_internal (obj , RxIrq , enable );
342
+ }
343
+
301
344
/******************************************************************************
302
345
* READ/WRITE
303
346
******************************************************************************/
304
347
int serial_getc (serial_t * obj ) {
305
348
while (!serial_readable (obj ));
306
- return obj -> uart -> RBR ;
349
+ int data = obj -> uart -> RBR ;
350
+ if (NC != uart_data [obj -> index ].sw_rts .pin ) {
351
+ gpio_write (& uart_data [obj -> index ].sw_rts , 0 );
352
+ obj -> uart -> IER |= 1 << RxIrq ;
353
+ }
354
+ return data ;
307
355
}
308
356
309
357
void serial_putc (serial_t * obj , int c ) {
310
358
while (!serial_writable (obj ));
311
359
obj -> uart -> THR = c ;
312
- obj -> count ++ ;
313
360
}
314
361
315
362
int serial_readable (serial_t * obj ) {
@@ -318,11 +365,10 @@ int serial_readable(serial_t *obj) {
318
365
319
366
int serial_writable (serial_t * obj ) {
320
367
int isWritable = 1 ;
321
- if (obj -> uart -> LSR & 0x20 )
322
- obj -> count = 0 ;
323
- else if (obj -> count >= 16 )
324
- isWritable = 0 ;
325
-
368
+ if (NC != uart_data [obj -> index ].sw_cts .pin )
369
+ isWritable = gpio_read (& uart_data [obj -> index ].sw_cts ) == 0 ;
370
+ if (isWritable )
371
+ isWritable = obj -> uart -> LSR & 0x40 ;
326
372
return isWritable ;
327
373
}
328
374
@@ -345,3 +391,49 @@ void serial_break_clear(serial_t *obj) {
345
391
obj -> uart -> LCR &= ~(1 << 6 );
346
392
}
347
393
394
+ void serial_set_flow_control (serial_t * obj , FlowControl type , PinName rxflow , PinName txflow ) {
395
+ // Only UART1 has hardware flow control on LPC176x
396
+ LPC_UART1_TypeDef * uart1 = (uint32_t )obj -> uart == (uint32_t )LPC_UART1 ? LPC_UART1 : NULL ;
397
+ int index = obj -> index ;
398
+
399
+ // First, disable flow control completely
400
+ if (uart1 )
401
+ uart1 -> MCR = uart1 -> MCR & ~UART_MCR_FLOWCTRL_MASK ;
402
+ uart_data [index ].sw_rts .pin = uart_data [index ].sw_cts .pin = NC ;
403
+ serial_flow_irq_set (obj , 0 );
404
+ if (FlowControlNone == type )
405
+ return ;
406
+ // Check type(s) of flow control to use
407
+ UARTName uart_rts = (UARTName )pinmap_find_peripheral (rxflow , PinMap_UART_RTS );
408
+ UARTName uart_cts = (UARTName )pinmap_find_peripheral (txflow , PinMap_UART_CTS );
409
+ if (((FlowControlCTS == type ) || (FlowControlRTSCTS == type )) && (NC != txflow )) {
410
+ // Can this be enabled in hardware?
411
+ if ((UART_1 == uart_cts ) && (NULL != uart1 )) {
412
+ // Enable auto-CTS mode
413
+ uart1 -> MCR |= UART_MCR_CTSEN_MASK ;
414
+ pinmap_pinout (txflow , PinMap_UART_CTS );
415
+ } else {
416
+ // Can't enable in hardware, use software emulation
417
+ gpio_init (& uart_data [index ].sw_cts , txflow , PIN_INPUT );
418
+ }
419
+ }
420
+ if (((FlowControlRTS == type ) || (FlowControlRTSCTS == type )) && (NC != rxflow )) {
421
+ // Enable FIFOs, trigger level of 1 char on RX FIFO
422
+ obj -> uart -> FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
423
+ | 1 << 1 // Rx Fifo Reset
424
+ | 1 << 2 // Tx Fifo Reset
425
+ | 0 << 6 ; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
426
+ // Can this be enabled in hardware?
427
+ if ((UART_1 == uart_rts ) && (NULL != uart1 )) {
428
+ // Enable auto-RTS mode
429
+ uart1 -> MCR |= UART_MCR_RTSEN_MASK ;
430
+ pinmap_pinout (rxflow , PinMap_UART_RTS );
431
+ } else { // can't enable in hardware, use software emulation
432
+ gpio_init (& uart_data [index ].sw_rts , rxflow , PIN_OUTPUT );
433
+ gpio_write (& uart_data [index ].sw_rts , 0 );
434
+ // Enable RX interrupt
435
+ serial_flow_irq_set (obj , 1 );
436
+ }
437
+ }
438
+ }
439
+
0 commit comments