Skip to content

Commit

Permalink
[U(S)ART] hardware flow control support (#1634)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
akasona authored Feb 2, 2022
1 parent b8756be commit 497ea5a
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 10 deletions.
44 changes: 39 additions & 5 deletions cores/arduino/HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,14 @@
#endif // HAVE_HWSERIALx

// Constructors ////////////////////////////////////////////////////////////////
HardwareSerial::HardwareSerial(uint32_t _rx, uint32_t _tx)
HardwareSerial::HardwareSerial(uint32_t _rx, uint32_t _tx, uint32_t _rts, uint32_t _cts)
{
init(digitalPinToPinName(_rx), digitalPinToPinName(_tx));
init(digitalPinToPinName(_rx), digitalPinToPinName(_tx), digitalPinToPinName(_rts), digitalPinToPinName(_cts));
}

HardwareSerial::HardwareSerial(PinName _rx, PinName _tx)
HardwareSerial::HardwareSerial(PinName _rx, PinName _tx, PinName _rts, PinName _cts)
{
init(_rx, _tx);
init(_rx, _tx, _rts, _cts);
}

HardwareSerial::HardwareSerial(void *peripheral, HalfDuplexMode_t halfDuplex)
Expand Down Expand Up @@ -286,14 +286,16 @@ HardwareSerial::HardwareSerial(PinName _rxtx)
init(NC, _rxtx);
}

void HardwareSerial::init(PinName _rx, PinName _tx)
void HardwareSerial::init(PinName _rx, PinName _tx, PinName _rts, PinName _cts)
{
if (_rx == _tx) {
_serial.pin_rx = NC;
} else {
_serial.pin_rx = _rx;
}
_serial.pin_tx = _tx;
_serial.pin_rts = _rts;
_serial.pin_cts = _cts;
_serial.rx_buff = _rx_buffer;
_serial.rx_head = 0;
_serial.rx_tail = 0;
Expand Down Expand Up @@ -575,6 +577,38 @@ void HardwareSerial::setTx(PinName _tx)
_serial.pin_tx = _tx;
}

void HardwareSerial::setRts(uint32_t _rts)
{
_serial.pin_rts = digitalPinToPinName(_rts);
}

void HardwareSerial::setCts(uint32_t _cts)
{
_serial.pin_cts = digitalPinToPinName(_cts);
}

void HardwareSerial::setRtsCts(uint32_t _rts, uint32_t _cts)
{
_serial.pin_rts = digitalPinToPinName(_rts);
_serial.pin_cts = digitalPinToPinName(_cts);
}

void HardwareSerial::setRts(PinName _rts)
{
_serial.pin_rts = _rts;
}

void HardwareSerial::setCts(PinName _cts)
{
_serial.pin_cts = _cts;
}

void HardwareSerial::setRtsCts(PinName _rts, PinName _cts)
{
_serial.pin_rts = _rts;
_serial.pin_cts = _cts;
}

void HardwareSerial::setHalfDuplex(void)
{
_serial.pin_rx = NC;
Expand Down
14 changes: 11 additions & 3 deletions cores/arduino/HardwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ class HardwareSerial : public Stream {
serial_t _serial;

public:
HardwareSerial(uint32_t _rx, uint32_t _tx);
HardwareSerial(PinName _rx, PinName _tx);
HardwareSerial(uint32_t _rx, uint32_t _tx, uint32_t _rts = NUM_DIGITAL_PINS, uint32_t _cts = NUM_DIGITAL_PINS);
HardwareSerial(PinName _rx, PinName _tx, PinName _rts = NC, PinName _cts = NC);
HardwareSerial(void *peripheral, HalfDuplexMode_t halfDuplex = HALF_DUPLEX_DISABLED);
HardwareSerial(uint32_t _rxtx);
HardwareSerial(PinName _rxtx);
Expand Down Expand Up @@ -155,6 +155,14 @@ class HardwareSerial : public Stream {
void setRx(PinName _rx);
void setTx(PinName _tx);

// Enable HW flow control on RTS, CTS or both
void setRts(uint32_t _rts);
void setCts(uint32_t _cts);
void setRtsCts(uint32_t _rts, uint32_t _cts);
void setRts(PinName _rts);
void setCts(PinName _cts);
void setRtsCts(PinName _rts, PinName _cts);

// Enable half-duplex mode by setting the Rx pin to NC
// This needs to be done before the call to begin()
void setHalfDuplex(void);
Expand All @@ -170,7 +178,7 @@ class HardwareSerial : public Stream {
bool _rx_enabled;
uint8_t _config;
unsigned long _baud;
void init(PinName _rx, PinName _tx);
void init(PinName _rx, PinName _tx, PinName _rts = NC, PinName _cts = NC);
void configForLowPower(void);
};

Expand Down
2 changes: 2 additions & 0 deletions cores/arduino/stm32/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ struct serial_s {
int (*tx_callback)(serial_t *);
PinName pin_tx;
PinName pin_rx;
PinName pin_rts;
PinName pin_cts;
IRQn_Type irq;
uint8_t index;
uint8_t recv;
Expand Down
30 changes: 28 additions & 2 deletions libraries/SrcWrapper/src/stm32/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
/* Determine the U(S)ART peripheral to use (USART1, USART2, ...) */
USART_TypeDef *uart_tx = pinmap_peripheral(obj->pin_tx, PinMap_UART_TX);
USART_TypeDef *uart_rx = pinmap_peripheral(obj->pin_rx, PinMap_UART_RX);
USART_TypeDef *uart_rts = pinmap_peripheral(obj->pin_rts, PinMap_UART_RTS);
USART_TypeDef *uart_cts = pinmap_peripheral(obj->pin_cts, PinMap_UART_CTS);

/* Pin Tx must not be NP */
if (uart_tx == NP) {
Expand All @@ -121,15 +123,28 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
core_debug("ERROR: [U(S)ART] Rx pin has no peripheral!\n");
return;
}
/* Pin RTS must not be NP if flow control is enabled */
if ((obj->pin_rts != NC) && (uart_rts == NP)) {
core_debug("ERROR: [U(S)ART] RTS pin has no peripheral!\n");
return;
}
/* Pin CTS must not be NP if flow control is enabled */
if ((obj->pin_cts != NC) && (uart_cts == NP)) {
core_debug("ERROR: [U(S)ART] CTS pin has no peripheral!\n");
return;
}

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

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

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

/* Configure flow control */
uint32_t flow_control = UART_HWCONTROL_NONE;
if (uart_rts != NP) {
flow_control |= UART_HWCONTROL_RTS;
pinmap_pinout(obj->pin_rts, PinMap_UART_RTS);
}
if (uart_cts != NP) {
flow_control |= UART_HWCONTROL_CTS;
pinmap_pinout(obj->pin_cts, PinMap_UART_CTS);
}

/* Configure uart */
uart_handlers[obj->index] = huart;
huart->Instance = (USART_TypeDef *)(obj->uart);
Expand All @@ -298,7 +324,7 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
huart->Init.StopBits = stopbits;
huart->Init.Parity = parity;
huart->Init.Mode = UART_MODE_TX_RX;
huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart->Init.HwFlowCtl = flow_control;
huart->Init.OverSampling = UART_OVERSAMPLING_16;
#if !defined(STM32F1xx) && !defined(STM32F2xx) && !defined(STM32F4xx)\
&& !defined(STM32L1xx)
Expand Down

0 comments on commit 497ea5a

Please sign in to comment.