Skip to content

Commit 34a43ea

Browse files
author
Bogdan Marinescu
committed
Merge branch 'flow_control'
Conflicts: workspace_tools/tests.py
2 parents f56cbfa + bb8ed20 commit 34a43ea

File tree

16 files changed

+329
-37
lines changed

16 files changed

+329
-37
lines changed

libraries/mbed/api/SerialBase.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ class SerialBase {
5151
TxIrq
5252
};
5353

54+
enum Flow {
55+
Disabled = 0,
56+
RTS,
57+
CTS,
58+
RTSCTS
59+
};
60+
5461
/** Set the transmission format used by the serial port
5562
*
5663
* @param bits The number of bits in a word (5-8; default = 8)
@@ -99,6 +106,16 @@ class SerialBase {
99106
/** Generate a break condition on the serial line
100107
*/
101108
void send_break();
109+
110+
#if DEVICE_SERIAL_FC
111+
/** Set the flow control type on the serial port
112+
*
113+
* @param type the flow control type (Disabled, RTS, CTS, RTSCTS)
114+
* @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS)
115+
* @param flow2 the second flow control pin (CTS for RTSCTS)
116+
*/
117+
void set_flow_control(Flow type, PinName flow1=NC, PinName flow2=NC);
118+
#endif
102119

103120
static void _irq_handler(uint32_t id, SerialIrq irq_type);
104121

libraries/mbed/common/SerialBase.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,28 @@ void SerialBase::send_break() {
8181
serial_break_clear(&_serial);
8282
}
8383

84+
#ifdef DEVICE_SERIAL_FC
85+
void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2) {
86+
FlowControl flow_type = (FlowControl)type;
87+
switch(type) {
88+
case RTS:
89+
serial_set_flow_control(&_serial, flow_type, flow1, NC);
90+
break;
91+
92+
case CTS:
93+
serial_set_flow_control(&_serial, flow_type, NC, flow1);
94+
break;
95+
96+
case RTSCTS:
97+
serial_set_flow_control(&_serial, flow_type, flow1, flow2);
98+
break;
99+
100+
default:
101+
break;
102+
}
103+
}
104+
#endif
105+
84106
} // namespace mbed
85107

86108
#endif

libraries/mbed/common/pinmap_common.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,22 @@ uint32_t pinmap_merge(uint32_t a, uint32_t b) {
4444
return (uint32_t)NC;
4545
}
4646

47-
uint32_t pinmap_peripheral(PinName pin, const PinMap* map) {
48-
if (pin == (PinName)NC)
49-
return (uint32_t)NC;
50-
47+
uint32_t pinmap_find_peripheral(PinName pin, const PinMap* map) {
5148
while (map->pin != NC) {
5249
if (map->pin == pin)
5350
return map->peripheral;
5451
map++;
5552
}
56-
57-
// no mapping available
58-
error("pinmap not found for peripheral");
5953
return (uint32_t)NC;
6054
}
55+
56+
uint32_t pinmap_peripheral(PinName pin, const PinMap* map) {
57+
uint32_t peripheral = (uint32_t)NC;
58+
59+
if (pin == (PinName)NC)
60+
return (uint32_t)NC;
61+
peripheral = pinmap_find_peripheral(pin, map);
62+
if ((uint32_t)NC == peripheral) // no mapping available
63+
error("pinmap not found for peripheral");
64+
return peripheral;
65+
}

libraries/mbed/hal/pinmap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ void pin_mode (PinName pin, PinMode mode);
3434
uint32_t pinmap_peripheral(PinName pin, const PinMap* map);
3535
uint32_t pinmap_merge (uint32_t a, uint32_t b);
3636
void pinmap_pinout (PinName pin, const PinMap *map);
37+
uint32_t pinmap_find_peripheral(PinName pin, const PinMap* map);
3738

3839
#ifdef __cplusplus
3940
}

libraries/mbed/hal/serial_api.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ typedef enum {
3737
TxIrq
3838
} SerialIrq;
3939

40+
typedef enum {
41+
FlowControlNone,
42+
FlowControlRTS,
43+
FlowControlCTS,
44+
FlowControlRTSCTS
45+
} FlowControl;
46+
4047
typedef void (*uart_irq_handler)(uint32_t id, SerialIrq event);
4148

4249
typedef struct serial_s serial_t;
@@ -60,6 +67,8 @@ void serial_break_clear(serial_t *obj);
6067

6168
void serial_pinout_tx(PinName tx);
6269

70+
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow);
71+
6372
#ifdef __cplusplus
6473
}
6574
#endif

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/device.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define DEVICE_ANALOGOUT 1
2727

2828
#define DEVICE_SERIAL 1
29+
#define DEVICE_SERIAL_FC 1
2930

3031
#define DEVICE_I2C 1
3132
#define DEVICE_I2CSLAVE 1

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/objects.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "PortNames.h"
2121
#include "PeripheralNames.h"
2222
#include "PinNames.h"
23+
#include "gpio_object.h"
2324

2425
#ifdef __cplusplus
2526
extern "C" {
@@ -47,7 +48,6 @@ struct pwmout_s {
4748
struct serial_s {
4849
LPC_UART_TypeDef *uart;
4950
int index;
50-
uint8_t count;
5151
};
5252

5353
struct analogin_s {
@@ -71,8 +71,6 @@ struct spi_s {
7171
LPC_SSP_TypeDef *spi;
7272
};
7373

74-
#include "gpio_object.h"
75-
7674
#ifdef __cplusplus
7775
}
7876
#endif

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c

Lines changed: 113 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "cmsis.h"
2222
#include "pinmap.h"
2323
#include "error.h"
24+
#include "gpio_api.h"
2425

2526
/******************************************************************************
2627
* INITIALIZATION
@@ -51,12 +52,35 @@ static const PinMap PinMap_UART_RX[] = {
5152
{NC , NC , 0}
5253
};
5354

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+
5571
static uart_irq_handler irq_handler;
5672

5773
int stdio_uart_inited = 0;
5874
serial_t stdio_uart;
5975

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+
6084
void serial_init(serial_t *obj, PinName tx, PinName rx) {
6185
int is_stdio_uart = 0;
6286

@@ -106,7 +130,9 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
106130
case UART_2: obj->index = 2; break;
107131
case UART_3: obj->index = 3; break;
108132
}
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);
110136

111137
is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
112138

@@ -117,7 +143,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
117143
}
118144

119145
void serial_free(serial_t *obj) {
120-
serial_irq_ids[obj->index] = 0;
146+
uart_data[obj->index].serial_irq_id = 0;
121147
}
122148

123149
// serial_baud
@@ -251,30 +277,36 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
251277
/******************************************************************************
252278
* INTERRUPTS HANDLING
253279
******************************************************************************/
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) {
255281
// [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
256282
SerialIrq irq_type;
257283
switch (iir) {
258284
case 1: irq_type = TxIrq; break;
259285
case 2: irq_type = RxIrq; break;
260286
default: return;
261287
}
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);
265297
}
266298

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);}
271303

272304
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
273305
irq_handler = handler;
274-
serial_irq_ids[obj->index] = id;
306+
uart_data[obj->index].serial_irq_id = id;
275307
}
276308

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) {
278310
IRQn_Type irq_n = (IRQn_Type)0;
279311
uint32_t vector = 0;
280312
switch ((int)obj->uart) {
@@ -288,7 +320,7 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
288320
obj->uart->IER |= 1 << irq;
289321
NVIC_SetVector(irq_n, vector);
290322
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
292324
int all_disabled = 0;
293325
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
294326
obj->uart->IER &= ~(1 << irq);
@@ -298,18 +330,33 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
298330
}
299331
}
300332

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+
301344
/******************************************************************************
302345
* READ/WRITE
303346
******************************************************************************/
304347
int serial_getc(serial_t *obj) {
305348
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;
307355
}
308356

309357
void serial_putc(serial_t *obj, int c) {
310358
while (!serial_writable(obj));
311359
obj->uart->THR = c;
312-
obj->count++;
313360
}
314361

315362
int serial_readable(serial_t *obj) {
@@ -318,11 +365,10 @@ int serial_readable(serial_t *obj) {
318365

319366
int serial_writable(serial_t *obj) {
320367
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;
326372
return isWritable;
327373
}
328374

@@ -345,3 +391,49 @@ void serial_break_clear(serial_t *obj) {
345391
obj->uart->LCR &= ~(1 << 6);
346392
}
347393

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+

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC81X/device.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define DEVICE_ANALOGOUT 0
2727

2828
#define DEVICE_SERIAL 1
29+
#define DEVICE_SERIAL_FC 1
2930

3031
#define DEVICE_I2C 1
3132
#define DEVICE_I2CSLAVE 0

0 commit comments

Comments
 (0)