Skip to content

Commit 7d26bf8

Browse files
jamesarm97SuGlider
authored andcommitted
Add setMode function HardwareSerial.c to set the esp32 uart mode for use with RS485 auto RTS (#7935)
* Added setMode function to set the esp32 uart mode Used to set the esp32 uart mode for use with RS485 Half Duplex and the auto RTS pin mode. This will set/clear the RTS pin output to control the RE/DE pin on most RS485 chips. * Add Success (bool) return in some functions * Add Success (bool) return code to some functions * Add Success (bool) return to some functions * Add Success (bool) return to some functions * Fix uartSetRxTimeout return type --------- Co-authored-by: Rodrigo Garcia <[email protected]>
1 parent 5367814 commit 7d26bf8

File tree

4 files changed

+71
-27
lines changed

4 files changed

+71
-27
lines changed

Diff for: cores/esp32/HardwareSerial.cpp

+20-10
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ void HardwareSerial::onReceive(OnReceiveCb function, bool onlyOnTimeout)
233233
// A low value of FIFO Full bytes will consume more CPU time within the ISR
234234
// A high value of FIFO Full bytes will make the application wait longer to have byte available for the Stkech in a streaming scenario
235235
// Both RX FIFO Full and RX Timeout may affect when onReceive() will be called
236-
void HardwareSerial::setRxFIFOFull(uint8_t fifoBytes)
236+
bool HardwareSerial::setRxFIFOFull(uint8_t fifoBytes)
237237
{
238238
HSERIAL_MUTEX_LOCK();
239239
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high
@@ -242,14 +242,15 @@ void HardwareSerial::setRxFIFOFull(uint8_t fifoBytes)
242242
fifoBytes = 120;
243243
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
244244
}
245-
uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout
245+
bool retCode = uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout
246246
if (fifoBytes > 0 && fifoBytes < SOC_UART_FIFO_LEN - 1) _rxFIFOFull = fifoBytes;
247247
HSERIAL_MUTEX_UNLOCK();
248+
return retCode;
248249
}
249250

250251
// timout is calculates in time to receive UART symbols at the UART baudrate.
251252
// the estimation is about 11 bits per symbol (SERIAL_8N1)
252-
void HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
253+
bool HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
253254
{
254255
HSERIAL_MUTEX_LOCK();
255256

@@ -258,9 +259,10 @@ void HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
258259
_rxTimeout = symbols_timeout;
259260
if (!symbols_timeout) _onReceiveTimeout = false; // only when RX timeout is disabled, we also must disable this flag
260261

261-
uartSetRxTimeout(_uart, _rxTimeout); // Set new timeout
262+
bool retCode = uartSetRxTimeout(_uart, _rxTimeout); // Set new timeout
262263

263264
HSERIAL_MUTEX_UNLOCK();
265+
return retCode;
264266
}
265267

266268
void HardwareSerial::eventQueueReset()
@@ -548,28 +550,36 @@ void HardwareSerial::setRxInvert(bool invert)
548550
}
549551

550552
// negative Pin value will keep it unmodified
551-
void HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
553+
bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
552554
{
553555
if(_uart == NULL) {
554556
log_e("setPins() shall be called after begin() - nothing done\n");
555-
return;
557+
return false;
556558
}
557559

558-
// uartSetPins() checks if pins are valid for each function and for the SoC
559-
if (uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin)) {
560+
// uartSetPins() checks if pins are valid for each function and for the SoC
561+
bool retCode = uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin);
562+
if (retCode) {
560563
_txPin = _txPin >= 0 ? txPin : _txPin;
561564
_rxPin = _rxPin >= 0 ? rxPin : _rxPin;
562565
_rtsPin = _rtsPin >= 0 ? rtsPin : _rtsPin;
563566
_ctsPin = _ctsPin >= 0 ? ctsPin : _ctsPin;
564567
} else {
565568
log_e("Error when setting Serial port Pins. Invalid Pin.\n");
566569
}
570+
return retCode;
567571
}
568572

569573
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
570-
void HardwareSerial::setHwFlowCtrlMode(uint8_t mode, uint8_t threshold)
574+
bool HardwareSerial::setHwFlowCtrlMode(uint8_t mode, uint8_t threshold)
575+
{
576+
return uartSetHwFlowCtrlMode(_uart, mode, threshold);
577+
}
578+
579+
// Sets the uart mode in the esp32 uart for use with RS485 modes (HwFlowCtrl must be disabled and RTS pin set)
580+
bool HardwareSerial::setMode(uint8_t mode)
571581
{
572-
uartSetHwFlowCtrlMode(_uart, mode, threshold);
582+
return uartSetMode(_uart, mode);
573583
}
574584

575585
size_t HardwareSerial::setRxBufferSize(size_t new_size) {

Diff for: cores/esp32/HardwareSerial.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,13 @@ class HardwareSerial: public Stream
8080
// Examples: Maximum for 11 bits symbol is 92 (SERIAL_8N2, SERIAL_8E1, SERIAL_8O1, etc), Maximum for 10 bits symbol is 101 (SERIAL_8N1).
8181
// For example symbols_timeout=1 defines a timeout equal to transmission time of one symbol (~11 bit) on current baudrate.
8282
// For a baudrate of 9600, SERIAL_8N1 (10 bit symbol) and symbols_timeout = 3, the timeout would be 3 / (9600 / 10) = 3.125 ms
83-
void setRxTimeout(uint8_t symbols_timeout);
83+
bool setRxTimeout(uint8_t symbols_timeout);
8484

8585
// setRxFIFOFull(uint8_t fifoBytes) will set the number of bytes that will trigger UART_INTR_RXFIFO_FULL interrupt and fill up RxRingBuffer
8686
// This affects some functions such as Serial::available() and Serial.read() because, in a UART flow of receiving data, Serial internal
8787
// RxRingBuffer will be filled only after these number of bytes arrive or a RX Timeout happens.
8888
// This parameter can be set to 1 in order to receive byte by byte, but it will also consume more CPU time as the ISR will be activates often.
89-
void setRxFIFOFull(uint8_t fifoBytes);
89+
bool setRxFIFOFull(uint8_t fifoBytes);
9090

9191
// onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT)
9292
// UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by default in IDF)
@@ -161,10 +161,11 @@ class HardwareSerial: public Stream
161161

162162
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
163163
// SetPins shall be called after Serial begin()
164-
void setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
164+
bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
165165
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
166-
void setHwFlowCtrlMode(uint8_t mode = HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
167-
166+
bool setHwFlowCtrlMode(uint8_t mode = HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
167+
// Used to set RS485 modes such as UART_MODE_RS485_HALF_DUPLEX for Auto RTS function on ESP32
168+
bool setMode(uint8_t mode);
168169
size_t setRxBufferSize(size_t new_size);
169170
size_t setTxBufferSize(size_t new_size);
170171

Diff for: cores/esp32/esp32-hal-uart.c

+29-9
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,16 @@ bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t
162162
}
163163

164164
//
165-
void uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold) {
165+
bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold) {
166166
if(uart == NULL) {
167-
return;
167+
return false;
168168
}
169169
// IDF will issue corresponding error message when mode or threshold are wrong and prevent crashing
170170
// IDF will check (mode > HW_FLOWCTRL_CTS_RTS || threshold >= SOC_UART_FIFO_LEN)
171-
uart_set_hw_flow_ctrl(uart->num, (uart_hw_flowcontrol_t) mode, threshold);
171+
UART_MUTEX_LOCK();
172+
bool retCode = (ESP_OK == uart_set_hw_flow_ctrl(uart->num, (uart_hw_flowcontrol_t) mode, threshold));
173+
UART_MUTEX_UNLOCK();
174+
return retCode;
172175
}
173176

174177

@@ -246,26 +249,28 @@ void uartSetFastReading(uart_t* uart)
246249
}
247250

248251

249-
void uartSetRxTimeout(uart_t* uart, uint8_t numSymbTimeout)
252+
bool uartSetRxTimeout(uart_t* uart, uint8_t numSymbTimeout)
250253
{
251254
if(uart == NULL) {
252-
return;
255+
return false;
253256
}
254257

255258
UART_MUTEX_LOCK();
256-
uart_set_rx_timeout(uart->num, numSymbTimeout);
259+
bool retCode = (ESP_OK == uart_set_rx_timeout(uart->num, numSymbTimeout));
257260
UART_MUTEX_UNLOCK();
261+
return retCode;
258262
}
259263

260-
void uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull)
264+
bool uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull)
261265
{
262266
if(uart == NULL) {
263-
return;
267+
return false;
264268
}
265269

266270
UART_MUTEX_LOCK();
267-
uart_set_rx_full_threshold(uart->num, numBytesFIFOFull);
271+
bool retCode = (ESP_OK == uart_set_rx_full_threshold(uart->num, numBytesFIFOFull));
268272
UART_MUTEX_UNLOCK();
273+
return retCode;
269274
}
270275

271276
void uartEnd(uart_t* uart)
@@ -528,6 +533,21 @@ void uart_install_putc()
528533
}
529534
}
530535

536+
// Routines that take care of UART mode in the HardwareSerial Class code
537+
// used to set UART_MODE_RS485_HALF_DUPLEX auto RTS for TXD for ESP32 chips
538+
bool uartSetMode(uart_t *uart, uint8_t mode)
539+
{
540+
if (uart == NULL || uart->num >= SOC_UART_NUM)
541+
{
542+
return false;
543+
}
544+
545+
UART_MUTEX_LOCK();
546+
bool retCode = (ESP_OK == uart_set_mode(uart->num, mode));
547+
UART_MUTEX_UNLOCK();
548+
return retCode;
549+
}
550+
531551
void uartSetDebug(uart_t* uart)
532552
{
533553
if(uart == NULL || uart->num >= SOC_UART_NUM) {

Diff for: cores/esp32/esp32-hal-uart.h

+16-3
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,15 @@ SERIAL_8O2 = 0x800003f
8787
#define HW_FLOWCTRL_CTS 0x2 // use only CTS PIN for HW Flow Control
8888
#define HW_FLOWCTRL_CTS_RTS 0x3 // use both CTS and RTS PIN for HW Flow Control
8989

90+
// These are Hardware Uart Modes possible usage
91+
// equivalent to UDF enum uart_mode_t from
92+
// https://github.com/espressif/esp-idf/blob/master/components/hal/include/hal/uart_types.h#L34-L40
93+
#define MODE_UART 0x00 // mode: regular UART mode
94+
#define MODE_RS485_HALF_DUPLEX 0x01 // mode: half duplex RS485 UART mode control by RTS pin
95+
#define MODE_IRDA 0x02 // mode: IRDA UART mode
96+
#define MODE_RS485_COLLISION_DETECT 0x03 // mode: RS485 collision detection UART mode (used for test purposes)
97+
#define MODE_RS485_APP_CTRL 0x04
98+
9099
struct uart_struct_t;
91100
typedef struct uart_struct_t uart_t;
92101

@@ -112,8 +121,8 @@ void uartSetBaudRate(uart_t* uart, uint32_t baud_rate);
112121
uint32_t uartGetBaudRate(uart_t* uart);
113122

114123
void uartSetRxInvert(uart_t* uart, bool invert);
115-
void uartSetRxTimeout(uart_t* uart, uint8_t numSymbTimeout);
116-
void uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull);
124+
bool uartSetRxTimeout(uart_t* uart, uint8_t numSymbTimeout);
125+
bool uartSetRxFIFOFull(uart_t* uart, uint8_t numBytesFIFOFull);
117126
void uartSetFastReading(uart_t* uart);
118127

119128
void uartSetDebug(uart_t* uart);
@@ -126,7 +135,11 @@ bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t
126135
void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
127136

128137
// Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins
129-
void uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);
138+
bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);
139+
140+
// Used to set RS485 function -- needs to disable HW Flow Control and set RTS pin to use
141+
// RTS pin becomes RS485 half duplex RE/DE
142+
bool uartSetMode(uart_t *uart, uint8_t mode);
130143

131144
void uartStartDetectBaudrate(uart_t *uart);
132145
unsigned long uartDetectBaudrate(uart_t *uart);

0 commit comments

Comments
 (0)