diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 52883d0986..20d2a99377 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -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) @@ -286,7 +286,7 @@ 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; @@ -294,6 +294,8 @@ void HardwareSerial::init(PinName _rx, PinName _tx) _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; @@ -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; diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 4048c5cebf..de5b6a94f9 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -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); @@ -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); @@ -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); }; diff --git a/cores/arduino/stm32/uart.h b/cores/arduino/stm32/uart.h index 9b5a1857d1..b08c0d9d54 100644 --- a/cores/arduino/stm32/uart.h +++ b/cores/arduino/stm32/uart.h @@ -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; diff --git a/libraries/SrcWrapper/src/stm32/uart.c b/libraries/SrcWrapper/src/stm32/uart.c index 6f947e4066..9a2afe1a6b 100644 --- a/libraries/SrcWrapper/src/stm32/uart.c +++ b/libraries/SrcWrapper/src/stm32/uart.c @@ -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) { @@ -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; } @@ -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); @@ -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)