mirror of
https://github.com/apache/nuttx.git
synced 2026-06-08 01:42:58 +08:00
arch/xtensa/esp32s3: add UART RS485 support
This commit adds support of RS485 support in ESP32-S3 serial driver Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
This commit is contained in:
committed by
Xiang Xiao
parent
b9472129c8
commit
a003a7ea36
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user