Skip to content

Commit

Permalink
Reorganize RS485 Mode - FlowCtrl (#8718)
Browse files Browse the repository at this point in the history
  • Loading branch information
SuGlider committed Oct 6, 2023
1 parent 6b1933b commit b98b52a
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 82 deletions.
14 changes: 10 additions & 4 deletions cores/esp32/HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,14 +576,20 @@ bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t r
return uartSetPins(_uart_nr, rxPin, txPin, ctsPin, rtsPin);
}

// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
bool HardwareSerial::setHwFlowCtrlMode(uint8_t mode, uint8_t threshold)
// Enables or disables Hardware Flow Control using RTS and/or CTS pins
// must use setAllPins() in order to set RTS/CTS pins
// SerialHwFlowCtrl = UART_HW_FLOWCTRL_DISABLE, UART_HW_FLOWCTRL_RTS,
// UART_HW_FLOWCTRL_CTS, UART_HW_FLOWCTRL_CTS_RTS
bool HardwareSerial::setHwFlowCtrlMode(SerialHwFlowCtrl mode, uint8_t threshold)
{
return uartSetHwFlowCtrlMode(_uart, mode, threshold);
}

// Sets the uart mode in the esp32 uart for use with RS485 modes (HwFlowCtrl must be disabled and RTS pin set)
bool HardwareSerial::setMode(uint8_t mode)
// Sets the uart mode in the esp32 uart for use with RS485 modes
// HwFlowCtrl must be disabled and RTS pin set
// SerialMode = UART_MODE_UART, UART_MODE_RS485_HALF_DUPLEX, UART_MODE_IRDA,
// or testing mode: UART_MODE_RS485_COLLISION_DETECT, UART_MODE_RS485_APP_CTRL
bool HardwareSerial::setMode(SerialMode mode)
{
return uartSetMode(_uart, mode);
}
Expand Down
43 changes: 41 additions & 2 deletions cores/esp32/HardwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,36 @@
#include "freertos/task.h"
#include "freertos/semphr.h"

enum SerialConfig {
SERIAL_5N1 = 0x8000010,
SERIAL_6N1 = 0x8000014,
SERIAL_7N1 = 0x8000018,
SERIAL_8N1 = 0x800001c,
SERIAL_5N2 = 0x8000030,
SERIAL_6N2 = 0x8000034,
SERIAL_7N2 = 0x8000038,
SERIAL_8N2 = 0x800003c,
SERIAL_5E1 = 0x8000012,
SERIAL_6E1 = 0x8000016,
SERIAL_7E1 = 0x800001a,
SERIAL_8E1 = 0x800001e,
SERIAL_5E2 = 0x8000032,
SERIAL_6E2 = 0x8000036,
SERIAL_7E2 = 0x800003a,
SERIAL_8E2 = 0x800003e,
SERIAL_5O1 = 0x8000013,
SERIAL_6O1 = 0x8000017,
SERIAL_7O1 = 0x800001b,
SERIAL_8O1 = 0x800001f,
SERIAL_5O2 = 0x8000033,
SERIAL_6O2 = 0x8000037,
SERIAL_7O2 = 0x800003b,
SERIAL_8O2 = 0x800003f
};

typedef uart_mode_t SerialMode;
typedef uart_hw_flowcontrol_t SerialHwFlowCtrl;

typedef enum {
UART_NO_ERROR,
UART_BREAK_ERROR,
Expand Down Expand Up @@ -169,9 +199,18 @@ class HardwareSerial: public Stream
// When pins are changed, it will detach the previous ones
bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
bool setHwFlowCtrlMode(uint8_t mode = HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
// UART_HW_FLOWCTRL_DISABLE = 0x0 disable hardware flow control
// UART_HW_FLOWCTRL_RTS = 0x1 enable RX hardware flow control (rts)
// UART_HW_FLOWCTRL_CTS = 0x2 enable TX hardware flow control (cts)
// UART_HW_FLOWCTRL_CTS_RTS = 0x3 enable hardware flow control
bool setHwFlowCtrlMode(SerialHwFlowCtrl mode = UART_HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
// Used to set RS485 modes such as UART_MODE_RS485_HALF_DUPLEX for Auto RTS function on ESP32
bool setMode(uint8_t mode);
// UART_MODE_UART = 0x00 mode: regular UART mode
// UART_MODE_RS485_HALF_DUPLEX = 0x01 mode: half duplex RS485 UART mode control by RTS pin
// UART_MODE_IRDA = 0x02 mode: IRDA UART mode
// UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes)
// UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
bool setMode(SerialMode mode);
size_t setRxBufferSize(size_t new_size);
size_t setTxBufferSize(size_t new_size);

Expand Down
6 changes: 3 additions & 3 deletions cores/esp32/esp32-hal-uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,14 +335,14 @@ bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, in
}

//
bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold) {
bool uartSetHwFlowCtrlMode(uart_t *uart, uart_hw_flowcontrol_t mode, uint8_t threshold) {
if(uart == NULL) {
return false;
}
// IDF will issue corresponding error message when mode or threshold are wrong and prevent crashing
// IDF will check (mode > HW_FLOWCTRL_CTS_RTS || threshold >= SOC_UART_FIFO_LEN)
UART_MUTEX_LOCK();
bool retCode = (ESP_OK == uart_set_hw_flow_ctrl(uart->num, (uart_hw_flowcontrol_t) mode, threshold));
bool retCode = (ESP_OK == uart_set_hw_flow_ctrl(uart->num, mode, threshold));
UART_MUTEX_UNLOCK();
return retCode;
}
Expand Down Expand Up @@ -716,7 +716,7 @@ void uart_install_putc()

// Routines that take care of UART mode in the HardwareSerial Class code
// used to set UART_MODE_RS485_HALF_DUPLEX auto RTS for TXD for ESP32 chips
bool uartSetMode(uart_t *uart, uint8_t mode)
bool uartSetMode(uart_t *uart, uart_mode_t mode)
{
if (uart == NULL || uart->num >= SOC_UART_NUM)
{
Expand Down
85 changes: 12 additions & 73 deletions cores/esp32/esp32-hal-uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,77 +27,7 @@ extern "C" {
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"

#ifdef __cplusplus
enum SerialConfig {
SERIAL_5N1 = 0x8000010,
SERIAL_6N1 = 0x8000014,
SERIAL_7N1 = 0x8000018,
SERIAL_8N1 = 0x800001c,
SERIAL_5N2 = 0x8000030,
SERIAL_6N2 = 0x8000034,
SERIAL_7N2 = 0x8000038,
SERIAL_8N2 = 0x800003c,
SERIAL_5E1 = 0x8000012,
SERIAL_6E1 = 0x8000016,
SERIAL_7E1 = 0x800001a,
SERIAL_8E1 = 0x800001e,
SERIAL_5E2 = 0x8000032,
SERIAL_6E2 = 0x8000036,
SERIAL_7E2 = 0x800003a,
SERIAL_8E2 = 0x800003e,
SERIAL_5O1 = 0x8000013,
SERIAL_6O1 = 0x8000017,
SERIAL_7O1 = 0x800001b,
SERIAL_8O1 = 0x800001f,
SERIAL_5O2 = 0x8000033,
SERIAL_6O2 = 0x8000037,
SERIAL_7O2 = 0x800003b,
SERIAL_8O2 = 0x800003f
};
#else
#define SERIAL_5N1 0x8000010
#define SERIAL_6N1 0x8000014
#define SERIAL_7N1 0x8000018
#define SERIAL_8N1 0x800001c
#define SERIAL_5N2 0x8000030
#define SERIAL_6N2 0x8000034
#define SERIAL_7N2 0x8000038
#define SERIAL_8N2 0x800003c
#define SERIAL_5E1 0x8000012
#define SERIAL_6E1 0x8000016
#define SERIAL_7E1 0x800001a
#define SERIAL_8E1 0x800001e
#define SERIAL_5E2 0x8000032
#define SERIAL_6E2 0x8000036
#define SERIAL_7E2 0x800003a
#define SERIAL_8E2 0x800003e
#define SERIAL_5O1 0x8000013
#define SERIAL_6O1 0x8000017
#define SERIAL_7O1 0x800001b
#define SERIAL_8O1 0x800001f
#define SERIAL_5O2 0x8000033
#define SERIAL_6O2 0x8000037
#define SERIAL_7O2 0x800003b
#define SERIAL_8O2 0x800003f
#endif // __cplusplus

// These are Hardware Flow Contol possible usage
// equivalent to UDF enum uart_hw_flowcontrol_t from
// https://github.com/espressif/esp-idf/blob/master/components/hal/include/hal/uart_types.h#L75-L81
#define HW_FLOWCTRL_DISABLE 0x0 // disable HW Flow Control
#define HW_FLOWCTRL_RTS 0x1 // use only RTS PIN for HW Flow Control
#define HW_FLOWCTRL_CTS 0x2 // use only CTS PIN for HW Flow Control
#define HW_FLOWCTRL_CTS_RTS 0x3 // use both CTS and RTS PIN for HW Flow Control

// These are Hardware Uart Modes possible usage
// equivalent to UDF enum uart_mode_t from
// https://github.com/espressif/esp-idf/blob/master/components/hal/include/hal/uart_types.h#L34-L40
#define MODE_UART 0x00 // mode: regular UART mode
#define MODE_RS485_HALF_DUPLEX 0x01 // mode: half duplex RS485 UART mode control by RTS pin
#define MODE_IRDA 0x02 // mode: IRDA UART mode
#define MODE_RS485_COLLISION_DETECT 0x03 // mode: RS485 collision detection UART mode (used for test purposes)
#define MODE_RS485_APP_CTRL 0x04
#include "hal/uart_types.h"

struct uart_struct_t;
typedef struct uart_struct_t uart_t;
Expand Down Expand Up @@ -145,11 +75,20 @@ void uart_init_PeriMan(void);


// Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins
bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);
// UART_HW_FLOWCTRL_DISABLE = 0x0 disable hardware flow control
// UART_HW_FLOWCTRL_RTS = 0x1 enable RX hardware flow control (rts)
// UART_HW_FLOWCTRL_CTS = 0x2 enable TX hardware flow control (cts)
// UART_HW_FLOWCTRL_CTS_RTS = 0x3 enable hardware flow control
bool uartSetHwFlowCtrlMode(uart_t *uart, uart_hw_flowcontrol_t mode, uint8_t threshold);

// Used to set RS485 function -- needs to disable HW Flow Control and set RTS pin to use
// RTS pin becomes RS485 half duplex RE/DE
bool uartSetMode(uart_t *uart, uint8_t mode);
// UART_MODE_UART = 0x00 mode: regular UART mode
// UART_MODE_RS485_HALF_DUPLEX = 0x01 mode: half duplex RS485 UART mode control by RTS pin
// UART_MODE_IRDA = 0x02 mode: IRDA UART mode
// UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes)
// UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
bool uartSetMode(uart_t *uart, uart_mode_t mode);

void uartStartDetectBaudrate(uart_t *uart);
unsigned long uartDetectBaudrate(uart_t *uart);
Expand Down

0 comments on commit b98b52a

Please sign in to comment.