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);
 }
 
 /****************************************************************************

Reply via email to