From 31937c2fcc2f4a15515d30fb4c81ebc136e0534c Mon Sep 17 00:00:00 2001 From: Akaiwa Wataru Date: Wed, 26 Jan 2022 01:11:13 +0900 Subject: [PATCH 1/6] Add RTS/CTS configuration interface void setRts(_rts); void setCts(_cts); void setRtsCts(_rts, _cts); These APIs accept either uint32_t pin number or PinName. --- cores/arduino/HardwareSerial.cpp | 34 ++++++++++++++++++++++++++++++++ cores/arduino/HardwareSerial.h | 8 ++++++++ cores/arduino/stm32/uart.h | 2 ++ 3 files changed, 44 insertions(+) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 52883d0986..2d1acdd9a8 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -294,6 +294,8 @@ void HardwareSerial::init(PinName _rx, PinName _tx) _serial.pin_rx = _rx; } _serial.pin_tx = _tx; + _serial.pin_rts = NC; + _serial.pin_cts = NC; _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..871974933d 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -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); 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; From 16ac042576e6dc2759eb85a23e9507d18ca6c388 Mon Sep 17 00:00:00 2001 From: Akaiwa Wataru Date: Wed, 26 Jan 2022 01:26:11 +0900 Subject: [PATCH 2/6] Implement UART flow control configuration --- libraries/SrcWrapper/src/stm32/uart.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libraries/SrcWrapper/src/stm32/uart.c b/libraries/SrcWrapper/src/stm32/uart.c index 6f947e4066..18ec8797db 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) { @@ -290,6 +292,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 +311,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) From 54581cfb21a4ab9633fdb0fa904d501cf5f05c70 Mon Sep 17 00:00:00 2001 From: Akaiwa Wataru Date: Wed, 26 Jan 2022 02:05:24 +0900 Subject: [PATCH 3/6] Implement RTS/CTS pin name validation --- libraries/SrcWrapper/src/stm32/uart.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libraries/SrcWrapper/src/stm32/uart.c b/libraries/SrcWrapper/src/stm32/uart.c index 18ec8797db..1b17aeb8d9 100644 --- a/libraries/SrcWrapper/src/stm32/uart.c +++ b/libraries/SrcWrapper/src/stm32/uart.c @@ -123,6 +123,16 @@ 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 @@ -133,6 +143,12 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par if (obj->uart == NP) { core_debug("ERROR: [U(S)ART] Rx and Tx pins peripherals mismatch!\n"); return; + } else if (uart_rts != NP && obj->uart != uart_rts) { + core_debug("ERROR: [U(S)ART] Rx/Tx and RTS pins peripherals mismatch!\n"); + return; + } else if (uart_cts != NP && obj->uart != uart_cts) { + core_debug("ERROR: [U(S)ART] Rx/Tx and CTS pins peripherals mismatch!\n"); + return; } /* Enable USART clock */ From 0049c76215c5a51334f8d67d3613661d5a8267dd Mon Sep 17 00:00:00 2001 From: Akaiwa Wataru Date: Sat, 29 Jan 2022 20:15:02 +0900 Subject: [PATCH 4/6] Merge all pins' peripherals explicitly --- libraries/SrcWrapper/src/stm32/uart.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libraries/SrcWrapper/src/stm32/uart.c b/libraries/SrcWrapper/src/stm32/uart.c index 1b17aeb8d9..9a2afe1a6b 100644 --- a/libraries/SrcWrapper/src/stm32/uart.c +++ b/libraries/SrcWrapper/src/stm32/uart.c @@ -139,15 +139,12 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par * 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"); - return; - } else if (uart_rts != NP && obj->uart != uart_rts) { - core_debug("ERROR: [U(S)ART] Rx/Tx and RTS pins peripherals mismatch!\n"); - return; - } else if (uart_cts != NP && obj->uart != uart_cts) { - core_debug("ERROR: [U(S)ART] Rx/Tx and CTS pins peripherals mismatch!\n"); + core_debug("ERROR: [U(S)ART] Rx/Tx/RTS/CTS pins peripherals mismatch!\n"); return; } From 1a91670ebbdff340d5298bbe4a67bc9b6c62306e Mon Sep 17 00:00:00 2001 From: Akaiwa Wataru Date: Sat, 29 Jan 2022 21:09:40 +0900 Subject: [PATCH 5/6] Add constructor with RTS/CTS parameters --- cores/arduino/HardwareSerial.cpp | 16 +++++++++++++--- cores/arduino/HardwareSerial.h | 4 +++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 2d1acdd9a8..dc273131db 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -125,6 +125,16 @@ HardwareSerial::HardwareSerial(PinName _rx, PinName _tx) init(_rx, _tx); } +HardwareSerial::HardwareSerial(uint32_t _rx, uint32_t _tx, uint32_t _rts, uint32_t _cts) +{ + init(digitalPinToPinName(_rx), digitalPinToPinName(_tx), digitalPinToPinName(_rts), digitalPinToPinName(_cts)); +} + +HardwareSerial::HardwareSerial(PinName _rx, PinName _tx, PinName _rts, PinName _cts) +{ + init(_rx, _tx, _rts, _cts); +} + HardwareSerial::HardwareSerial(void *peripheral, HalfDuplexMode_t halfDuplex) { // If PIN_SERIALy_RX is not defined assume half-duplex @@ -286,7 +296,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,8 +304,8 @@ void HardwareSerial::init(PinName _rx, PinName _tx) _serial.pin_rx = _rx; } _serial.pin_tx = _tx; - _serial.pin_rts = NC; - _serial.pin_cts = NC; + _serial.pin_rts = _rts; + _serial.pin_cts = _cts; _serial.rx_buff = _rx_buffer; _serial.rx_head = 0; _serial.rx_tail = 0; diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 871974933d..d8ec1fa2de 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -112,6 +112,8 @@ class HardwareSerial : public Stream { public: HardwareSerial(uint32_t _rx, uint32_t _tx); HardwareSerial(PinName _rx, PinName _tx); + HardwareSerial(uint32_t _rx, uint32_t _tx, uint32_t _rts, uint32_t _cts); + HardwareSerial(PinName _rx, PinName _tx, PinName _rts, PinName _cts); HardwareSerial(void *peripheral, HalfDuplexMode_t halfDuplex = HALF_DUPLEX_DISABLED); HardwareSerial(uint32_t _rxtx); HardwareSerial(PinName _rxtx); @@ -178,7 +180,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); }; From 7ff51aa1a91a9a94b60604a76f4793b46b9794d2 Mon Sep 17 00:00:00 2001 From: Akaiwa Wataru Date: Mon, 31 Jan 2022 20:35:20 +0900 Subject: [PATCH 6/6] Reduce repeated constructor definition --- cores/arduino/HardwareSerial.cpp | 10 ---------- cores/arduino/HardwareSerial.h | 6 ++---- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index dc273131db..20d2a99377 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -115,16 +115,6 @@ #endif // HAVE_HWSERIALx // Constructors //////////////////////////////////////////////////////////////// -HardwareSerial::HardwareSerial(uint32_t _rx, uint32_t _tx) -{ - init(digitalPinToPinName(_rx), digitalPinToPinName(_tx)); -} - -HardwareSerial::HardwareSerial(PinName _rx, PinName _tx) -{ - init(_rx, _tx); -} - HardwareSerial::HardwareSerial(uint32_t _rx, uint32_t _tx, uint32_t _rts, uint32_t _cts) { init(digitalPinToPinName(_rx), digitalPinToPinName(_tx), digitalPinToPinName(_rts), digitalPinToPinName(_cts)); diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index d8ec1fa2de..de5b6a94f9 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -110,10 +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, uint32_t _cts); - HardwareSerial(PinName _rx, PinName _tx, PinName _rts, PinName _cts); + 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);