Skip to content

Commit 497ea5a

Browse files
authored
[U(S)ART] hardware flow control support (#1634)
* Add RTS/CTS configuration interface void setRts(_rts); void setCts(_cts); void setRtsCts(_rts, _cts); Add constructor with RTS/CTS parameters These APIs accept either uint32_t pin number or PinName.
1 parent b8756be commit 497ea5a

File tree

4 files changed

+80
-10
lines changed

4 files changed

+80
-10
lines changed

Diff for: cores/arduino/HardwareSerial.cpp

+39-5
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,14 @@
115115
#endif // HAVE_HWSERIALx
116116

117117
// Constructors ////////////////////////////////////////////////////////////////
118-
HardwareSerial::HardwareSerial(uint32_t _rx, uint32_t _tx)
118+
HardwareSerial::HardwareSerial(uint32_t _rx, uint32_t _tx, uint32_t _rts, uint32_t _cts)
119119
{
120-
init(digitalPinToPinName(_rx), digitalPinToPinName(_tx));
120+
init(digitalPinToPinName(_rx), digitalPinToPinName(_tx), digitalPinToPinName(_rts), digitalPinToPinName(_cts));
121121
}
122122

123-
HardwareSerial::HardwareSerial(PinName _rx, PinName _tx)
123+
HardwareSerial::HardwareSerial(PinName _rx, PinName _tx, PinName _rts, PinName _cts)
124124
{
125-
init(_rx, _tx);
125+
init(_rx, _tx, _rts, _cts);
126126
}
127127

128128
HardwareSerial::HardwareSerial(void *peripheral, HalfDuplexMode_t halfDuplex)
@@ -286,14 +286,16 @@ HardwareSerial::HardwareSerial(PinName _rxtx)
286286
init(NC, _rxtx);
287287
}
288288

289-
void HardwareSerial::init(PinName _rx, PinName _tx)
289+
void HardwareSerial::init(PinName _rx, PinName _tx, PinName _rts, PinName _cts)
290290
{
291291
if (_rx == _tx) {
292292
_serial.pin_rx = NC;
293293
} else {
294294
_serial.pin_rx = _rx;
295295
}
296296
_serial.pin_tx = _tx;
297+
_serial.pin_rts = _rts;
298+
_serial.pin_cts = _cts;
297299
_serial.rx_buff = _rx_buffer;
298300
_serial.rx_head = 0;
299301
_serial.rx_tail = 0;
@@ -575,6 +577,38 @@ void HardwareSerial::setTx(PinName _tx)
575577
_serial.pin_tx = _tx;
576578
}
577579

580+
void HardwareSerial::setRts(uint32_t _rts)
581+
{
582+
_serial.pin_rts = digitalPinToPinName(_rts);
583+
}
584+
585+
void HardwareSerial::setCts(uint32_t _cts)
586+
{
587+
_serial.pin_cts = digitalPinToPinName(_cts);
588+
}
589+
590+
void HardwareSerial::setRtsCts(uint32_t _rts, uint32_t _cts)
591+
{
592+
_serial.pin_rts = digitalPinToPinName(_rts);
593+
_serial.pin_cts = digitalPinToPinName(_cts);
594+
}
595+
596+
void HardwareSerial::setRts(PinName _rts)
597+
{
598+
_serial.pin_rts = _rts;
599+
}
600+
601+
void HardwareSerial::setCts(PinName _cts)
602+
{
603+
_serial.pin_cts = _cts;
604+
}
605+
606+
void HardwareSerial::setRtsCts(PinName _rts, PinName _cts)
607+
{
608+
_serial.pin_rts = _rts;
609+
_serial.pin_cts = _cts;
610+
}
611+
578612
void HardwareSerial::setHalfDuplex(void)
579613
{
580614
_serial.pin_rx = NC;

Diff for: cores/arduino/HardwareSerial.h

+11-3
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ class HardwareSerial : public Stream {
110110
serial_t _serial;
111111

112112
public:
113-
HardwareSerial(uint32_t _rx, uint32_t _tx);
114-
HardwareSerial(PinName _rx, PinName _tx);
113+
HardwareSerial(uint32_t _rx, uint32_t _tx, uint32_t _rts = NUM_DIGITAL_PINS, uint32_t _cts = NUM_DIGITAL_PINS);
114+
HardwareSerial(PinName _rx, PinName _tx, PinName _rts = NC, PinName _cts = NC);
115115
HardwareSerial(void *peripheral, HalfDuplexMode_t halfDuplex = HALF_DUPLEX_DISABLED);
116116
HardwareSerial(uint32_t _rxtx);
117117
HardwareSerial(PinName _rxtx);
@@ -155,6 +155,14 @@ class HardwareSerial : public Stream {
155155
void setRx(PinName _rx);
156156
void setTx(PinName _tx);
157157

158+
// Enable HW flow control on RTS, CTS or both
159+
void setRts(uint32_t _rts);
160+
void setCts(uint32_t _cts);
161+
void setRtsCts(uint32_t _rts, uint32_t _cts);
162+
void setRts(PinName _rts);
163+
void setCts(PinName _cts);
164+
void setRtsCts(PinName _rts, PinName _cts);
165+
158166
// Enable half-duplex mode by setting the Rx pin to NC
159167
// This needs to be done before the call to begin()
160168
void setHalfDuplex(void);
@@ -170,7 +178,7 @@ class HardwareSerial : public Stream {
170178
bool _rx_enabled;
171179
uint8_t _config;
172180
unsigned long _baud;
173-
void init(PinName _rx, PinName _tx);
181+
void init(PinName _rx, PinName _tx, PinName _rts = NC, PinName _cts = NC);
174182
void configForLowPower(void);
175183
};
176184

Diff for: cores/arduino/stm32/uart.h

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ struct serial_s {
7171
int (*tx_callback)(serial_t *);
7272
PinName pin_tx;
7373
PinName pin_rx;
74+
PinName pin_rts;
75+
PinName pin_cts;
7476
IRQn_Type irq;
7577
uint8_t index;
7678
uint8_t recv;

Diff for: libraries/SrcWrapper/src/stm32/uart.c

+28-2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
110110
/* Determine the U(S)ART peripheral to use (USART1, USART2, ...) */
111111
USART_TypeDef *uart_tx = pinmap_peripheral(obj->pin_tx, PinMap_UART_TX);
112112
USART_TypeDef *uart_rx = pinmap_peripheral(obj->pin_rx, PinMap_UART_RX);
113+
USART_TypeDef *uart_rts = pinmap_peripheral(obj->pin_rts, PinMap_UART_RTS);
114+
USART_TypeDef *uart_cts = pinmap_peripheral(obj->pin_cts, PinMap_UART_CTS);
113115

114116
/* Pin Tx must not be NP */
115117
if (uart_tx == NP) {
@@ -121,15 +123,28 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
121123
core_debug("ERROR: [U(S)ART] Rx pin has no peripheral!\n");
122124
return;
123125
}
126+
/* Pin RTS must not be NP if flow control is enabled */
127+
if ((obj->pin_rts != NC) && (uart_rts == NP)) {
128+
core_debug("ERROR: [U(S)ART] RTS pin has no peripheral!\n");
129+
return;
130+
}
131+
/* Pin CTS must not be NP if flow control is enabled */
132+
if ((obj->pin_cts != NC) && (uart_cts == NP)) {
133+
core_debug("ERROR: [U(S)ART] CTS pin has no peripheral!\n");
134+
return;
135+
}
124136

125137
/*
126138
* Get the peripheral name (USART1, USART2, ...) from the pin
127139
* and assign it to the object
128140
*/
129141
obj->uart = pinmap_merge_peripheral(uart_tx, uart_rx);
142+
/* We also merge RTS/CTS and assert all pins belong to the same instance */
143+
obj->uart = pinmap_merge_peripheral(obj->uart, uart_rts);
144+
obj->uart = pinmap_merge_peripheral(obj->uart, uart_cts);
130145

131146
if (obj->uart == NP) {
132-
core_debug("ERROR: [U(S)ART] Rx and Tx pins peripherals mismatch!\n");
147+
core_debug("ERROR: [U(S)ART] Rx/Tx/RTS/CTS pins peripherals mismatch!\n");
133148
return;
134149
}
135150

@@ -290,6 +305,17 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
290305
pinmap_pinout(obj->pin_rx, PinMap_UART_RX);
291306
}
292307

308+
/* Configure flow control */
309+
uint32_t flow_control = UART_HWCONTROL_NONE;
310+
if (uart_rts != NP) {
311+
flow_control |= UART_HWCONTROL_RTS;
312+
pinmap_pinout(obj->pin_rts, PinMap_UART_RTS);
313+
}
314+
if (uart_cts != NP) {
315+
flow_control |= UART_HWCONTROL_CTS;
316+
pinmap_pinout(obj->pin_cts, PinMap_UART_CTS);
317+
}
318+
293319
/* Configure uart */
294320
uart_handlers[obj->index] = huart;
295321
huart->Instance = (USART_TypeDef *)(obj->uart);
@@ -298,7 +324,7 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
298324
huart->Init.StopBits = stopbits;
299325
huart->Init.Parity = parity;
300326
huart->Init.Mode = UART_MODE_TX_RX;
301-
huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
327+
huart->Init.HwFlowCtl = flow_control;
302328
huart->Init.OverSampling = UART_OVERSAMPLING_16;
303329
#if !defined(STM32F1xx) && !defined(STM32F2xx) && !defined(STM32F4xx)\
304330
&& !defined(STM32L1xx)

0 commit comments

Comments
 (0)