This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new a003a7ea36 arch/xtensa/esp32s3: add UART RS485 support
a003a7ea36 is described below
commit a003a7ea3671318d206d0bbf4b780a28585aa895
Author: Petro Karashchenko <[email protected]>
AuthorDate: Wed Sep 6 16:56:38 2023 +0300
arch/xtensa/esp32s3: add UART RS485 support
This commit adds support of RS485 support in ESP32-S3 serial driver
Signed-off-by: Petro Karashchenko <[email protected]>
---
arch/xtensa/src/esp32s3/Kconfig | 83 +++++++++++++++++++++++++++++--
arch/xtensa/src/esp32s3/esp32s3_config.h | 8 +++
arch/xtensa/src/esp32s3/esp32s3_lowputc.c | 33 ++++++++++++
arch/xtensa/src/esp32s3/esp32s3_lowputc.h | 46 +++++++++--------
arch/xtensa/src/esp32s3/esp32s3_serial.c | 49 ++++++++++++++++--
5 files changed, 191 insertions(+), 28 deletions(-)
diff --git a/arch/xtensa/src/esp32s3/Kconfig b/arch/xtensa/src/esp32s3/Kconfig
index 9de68c92b2..3129dcb9c7 100644
--- a/arch/xtensa/src/esp32s3/Kconfig
+++ b/arch/xtensa/src/esp32s3/Kconfig
@@ -979,6 +979,31 @@ menu "UART Configuration"
if ESP32S3_UART0
+config ESP32S3_UART0_RS485
+ bool "RS-485 on UART0"
+ default n
+ ---help---
+ Enable RS-485 interface on UART0. Your board config will have to
+ provide GPIO_UART0_RS485_DIR pin definition.
+
+config ESP32S3_UART0_RS485_DIR_PIN
+ int "UART0 RS-485 DIR pin"
+ default 25
+ range 0 48
+ depends on ESP32S3_UART0_RS485
+ ---help---
+ DIR pin for RS-485 on UART0. This pin will control the RS485
enable
+ TX of the RS485 transceiver.
+
+config ESP32S3_UART0_RS485_DIR_POLARITY
+ int "UART0 RS-485 DIR pin polarity"
+ default 1
+ range 0 1
+ depends on ESP32S3_UART0_RS485
+ ---help---
+ Polarity of DIR pin for RS-485 on UART0. Set to state on DIR
pin which
+ enables TX (0 - low / nTXEN, 1 - high / TXEN).
+
config ESP32S3_UART0_TXPIN
int "UART0 Tx Pin"
default 43
@@ -1005,6 +1030,31 @@ endif # ESP32S3_UART0
if ESP32S3_UART1
+config ESP32S3_UART1_RS485
+ bool "RS-485 on UART1"
+ default n
+ ---help---
+ Enable RS-485 interface on UART1. Your board config will have to
+ provide GPIO_UART1_RS485_DIR pin definition.
+
+config ESP32S3_UART1_RS485_DIR_PIN
+ int "UART1 RS-485 DIR pin"
+ default 26
+ range 0 48
+ depends on ESP32S3_UART1_RS485
+ ---help---
+ DIR pin for RS-485 on UART1. This pin will control the RS485
enable
+ TX of the RS485 transceiver.
+
+config ESP32S3_UART1_RS485_DIR_POLARITY
+ int "UART1 RS-485 DIR pin polarity"
+ default 1
+ range 0 1
+ depends on ESP32S3_UART1_RS485
+ ---help---
+ Polarity of DIR pin for RS-485 on UART1. Set to state on DIR
pin which
+ enables TX (0 - low / nTXEN, 1 - high / TXEN).
+
config ESP32S3_UART1_TXPIN
int "UART1 Tx Pin"
default 17
@@ -1031,26 +1081,51 @@ endif # ESP32S3_UART1
if ESP32S3_UART2
+config ESP32S3_UART2_RS485
+ bool "RS-485 on UART2"
+ default n
+ ---help---
+ Enable RS-485 interface on UART2. Your board config will have to
+ provide GPIO_UART2_RS485_DIR pin definition.
+
+config ESP32S3_UART2_RS485_DIR_PIN
+ int "UART2 RS-485 DIR pin"
+ default 27
+ range 0 48
+ depends on ESP32S3_UART2_RS485
+ ---help---
+ DIR pin for RS-485 on UART2. This pin will control the RS485
enable
+ TX of the RS485 transceiver.
+
+config ESP32S3_UART2_RS485_DIR_POLARITY
+ int "UART2 RS-485 DIR pin polarity"
+ default 1
+ range 0 1
+ depends on ESP32S3_UART2_RS485
+ ---help---
+ Polarity of DIR pin for RS-485 on UART2. Set to state on DIR
pin which
+ enables TX (0 - low / nTXEN, 1 - high / TXEN).
+
config ESP32S3_UART2_TXPIN
int "UART2 Tx Pin"
- default 17
+ default 21
range 0 48
config ESP32S3_UART2_RXPIN
int "UART2 Rx Pin"
- default 16
+ default 22
range 0 48
config ESP32S3_UART2_RTSPIN
int "UART2 RTS Pin"
depends on SERIAL_IFLOWCONTROL
- default 35
+ default 23
range 0 48
config ESP32S3_UART2_CTSPIN
int "UART2 CTS Pin"
depends on SERIAL_OFLOWCONTROL
- default 36
+ default 24
range 0 48
endif # ESP32S3_UART2
diff --git a/arch/xtensa/src/esp32s3/esp32s3_config.h
b/arch/xtensa/src/esp32s3/esp32s3_config.h
index 17fcc7c09b..7ed128210a 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_config.h
+++ b/arch/xtensa/src/esp32s3/esp32s3_config.h
@@ -43,6 +43,14 @@
# define HAVE_UART_DEVICE 1
#endif
+/* Is RS-485 used? */
+
+#if defined(CONFIG_ESP32S3_UART0_RS485) || \
+ defined(CONFIG_ESP32S3_UART1_RS485) || \
+ defined(CONFIG_ESP32S3_UART2_RS485)
+# define HAVE_RS485 1
+#endif
+
/* Serial Console ***********************************************************/
/* Is there a serial console? There should be no more than one defined. It
diff --git a/arch/xtensa/src/esp32s3/esp32s3_lowputc.c
b/arch/xtensa/src/esp32s3/esp32s3_lowputc.c
index 34bd8da912..0ae6ba6576 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_lowputc.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_lowputc.c
@@ -101,6 +101,14 @@ struct esp32s3_uart_s g_uart0_config =
.oflow = false, /* output flow control (CTS) disabled */
#endif
#endif
+#ifdef CONFIG_ESP32S3_UART0_RS485
+ .rs485_dir_gpio = CONFIG_ESP32S3_UART0_RS485_DIR_PIN,
+#if (CONFIG_ESP32S3_UART0_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+#else
+ .rs485_dir_polarity = true,
+#endif
+#endif
};
#endif /* CONFIG_ESP32S3_UART0 */
@@ -140,6 +148,14 @@ struct esp32s3_uart_s g_uart1_config =
.oflow = false, /* output flow control (CTS) disabled */
#endif
#endif
+#ifdef CONFIG_ESP32S3_UART1_RS485
+ .rs485_dir_gpio = CONFIG_ESP32S3_UART1_RS485_DIR_PIN,
+#if (CONFIG_ESP32S3_UART1_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+#else
+ .rs485_dir_polarity = true,
+#endif
+#endif
};
#endif /* CONFIG_ESP32S3_UART1 */
@@ -179,6 +195,14 @@ struct esp32s3_uart_s g_uart2_config =
.oflow = false, /* output flow control (CTS) disabled */
#endif
#endif
+#ifdef CONFIG_ESP32S3_UART2_RS485
+ .rs485_dir_gpio = CONFIG_ESP32S3_UART2_RS485_DIR_PIN,
+#if (CONFIG_ESP32S3_UART2_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+#else
+ .rs485_dir_polarity = true,
+#endif
+#endif
};
#endif /* CONFIG_ESP32S3_UART2 */
@@ -900,6 +924,15 @@ void esp32s3_lowputc_config_pins(const struct
esp32s3_uart_s *priv)
}
#endif
}
+
+#ifdef HAVE_RS485
+ if (priv->rs485_dir_gpio != 0)
+ {
+ esp32s3_configgpio(priv->rs485_dir_gpio, OUTPUT);
+ esp32s3_gpio_matrix_out(priv->rs485_dir_gpio, SIG_GPIO_OUT_IDX, 0, 0);
+ esp32s3_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity);
+ }
+#endif
}
/****************************************************************************
diff --git a/arch/xtensa/src/esp32s3/esp32s3_lowputc.h
b/arch/xtensa/src/esp32s3/esp32s3_lowputc.h
index 02ccd75eb5..8680dd09dd 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_lowputc.h
+++ b/arch/xtensa/src/esp32s3/esp32s3_lowputc.h
@@ -94,31 +94,35 @@ enum uart_stop_length
struct esp32s3_uart_s
{
- uint8_t periph; /* UART peripheral ID */
- int cpuint; /* CPU interrupt assigned to this UART */
- uint8_t id; /* UART ID */
- uint8_t irq; /* IRQ associated with this UART */
- uint8_t cpu; /* CPU ID */
- uint32_t baud; /* Configured baud rate */
- uint8_t bits; /* Data length (5 to 8 bits). */
- uint8_t parity; /* 0=no parity, 1=odd parity, 2=even parity */
- uint8_t stop_b2; /* Use 2 stop bits? 0 = no (use 1) 1 = yes (use 2)
*/
- uint8_t int_pri; /* UART Interrupt Priority */
- uint8_t txpin; /* TX pin */
- uint8_t txsig; /* TX signal */
- uint8_t rxpin; /* RX pin */
- uint8_t rxsig; /* RX signal */
+ uint8_t periph; /* UART peripheral ID */
+ uint8_t id; /* UART ID */
+ uint8_t irq; /* IRQ associated with this UART */
+ uint8_t cpu; /* CPU ID */
+ int cpuint; /* CPU interrupt assigned to this UART */
+ uint32_t baud; /* Configured baud rate */
+ uint8_t bits; /* Data length (5 to 8 bits). */
+ uint8_t parity; /* 0=no parity, 1=odd parity, 2=even parity */
+ uint8_t stop_b2; /* Use 2 stop bits? 0 = no (use 1) 1 = yes (use
2) */
+ uint8_t int_pri; /* UART Interrupt Priority */
+ uint8_t txpin; /* TX pin */
+ uint8_t txsig; /* TX signal */
+ uint8_t rxpin; /* RX pin */
+ uint8_t rxsig; /* RX signal */
#ifdef CONFIG_SERIAL_IFLOWCONTROL
- uint8_t rtspin; /* RTS pin number */
- uint8_t rtssig; /* RTS signal */
- bool iflow; /* Input flow control (RTS) enabled */
+ uint8_t rtspin; /* RTS pin number */
+ uint8_t rtssig; /* RTS signal */
+ bool iflow; /* Input flow control (RTS) enabled */
#endif
#ifdef CONFIG_SERIAL_OFLOWCONTROL
- uint8_t ctspin; /* CTS pin number */
- uint8_t ctssig; /* CTS signal */
- bool oflow; /* Output flow control (CTS) enabled */
+ uint8_t ctspin; /* CTS pin number */
+ uint8_t ctssig; /* CTS signal */
+ bool oflow; /* Output flow control (CTS) enabled */
#endif
- spinlock_t lock; /* Device-specific lock */
+#ifdef HAVE_RS485
+ uint8_t rs485_dir_gpio; /* UART RS-485 DIR GPIO pin cfg */
+ bool rs485_dir_polarity; /* UART RS-485 DIR TXEN polarity */
+#endif
+ spinlock_t lock; /* Device-specific lock */
};
extern struct esp32s3_uart_s g_uart0_config;
diff --git a/arch/xtensa/src/esp32s3/esp32s3_serial.c
b/arch/xtensa/src/esp32s3/esp32s3_serial.c
index b948bc0dac..b4f13f2512 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_serial.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_serial.c
@@ -45,6 +45,7 @@
#include "esp32s3_config.h"
#include "esp32s3_irq.h"
#include "esp32s3_lowputc.h"
+#include "esp32s3_gpio.h"
#include "hardware/esp32s3_uart.h"
#include "hardware/esp32s3_system.h"
@@ -315,6 +316,18 @@ static int uart_handler(int irq, void *context, void *arg)
int_status = getreg32(UART_INT_ST_REG(priv->id));
+#ifdef HAVE_RS485
+ if ((int_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) != 0 &&
+ esp32s3_txempty(dev))
+ {
+ if (dev->xmit.tail == dev->xmit.head)
+ {
+ esp32s3_gpiowrite(priv->rs485_dir_gpio,
+ !priv->rs485_dir_polarity);
+ }
+ }
+#endif
+
/* Tx fifo empty interrupt or UART tx done int */
if ((int_status & tx_mask) != 0)
@@ -445,9 +458,18 @@ static int esp32s3_setup(struct uart_dev_s *dev)
}
#endif
- /* No Tx idle interval */
+#ifdef HAVE_RS485
+ if (priv->rs485_dir_gpio != 0)
+ {
+ esp32s3_lowputc_set_tx_idle_time(priv, 1);
+ }
+ else
+#endif
+ {
+ /* No Tx idle interval */
- esp32s3_lowputc_set_tx_idle_time(priv, 0);
+ esp32s3_lowputc_set_tx_idle_time(priv, 0);
+ }
/* Enable cores */
@@ -590,6 +612,18 @@ static void esp32s3_txint(struct uart_dev_s *dev, bool
enable)
if (enable)
{
+ /* After all bytes physically transmitted in the RS485 bus
+ * the TX_BRK_IDLE will indicate we can disable the TX pin.
+ */
+
+#ifdef HAVE_RS485
+ if (priv->rs485_dir_gpio != 0)
+ {
+ modifyreg32(UART_INT_ENA_REG(priv->id),
+ 0, UART_TX_BRK_IDLE_DONE_INT_ENA);
+ }
+#endif
+
/* Set to receive an interrupt when the TX holding register register
* is empty
*/
@@ -740,7 +774,16 @@ static bool esp32s3_txempty(struct uart_dev_s *dev)
static void esp32s3_send(struct uart_dev_s *dev, int ch)
{
- esp32s3_lowputc_send_byte(dev->priv, (char)ch);
+ struct esp32s3_uart_s *priv = dev->priv;
+
+#ifdef HAVE_RS485
+ if (priv->rs485_dir_gpio != 0)
+ {
+ esp32s3_gpiowrite(priv->rs485_dir_gpio, priv->rs485_dir_polarity);
+ }
+#endif
+
+ esp32s3_lowputc_send_byte(priv, (char)ch);
}
/****************************************************************************