mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
xtensa/esp32s2: add UART RS485 support
This commit is contained in:
committed by
Petro Karashchenko
parent
2ffb72917d
commit
071fb18501
@@ -583,6 +583,31 @@ menu "UART Configuration"
|
||||
|
||||
if ESP32S2_UART0
|
||||
|
||||
config ESP32S2_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 ESP32S2_UART0_RS485_DIR_PIN
|
||||
int "UART0 RS-485 DIR pin"
|
||||
default 25
|
||||
range 0 46
|
||||
depends on ESP32S2_UART0_RS485
|
||||
---help---
|
||||
DIR pin for RS-485 on UART0. This pin will control the RS485 enable
|
||||
TX of the RS485 transceiver.
|
||||
|
||||
config ESP32S2_UART0_RS485_DIR_POLARITY
|
||||
int "UART0 RS-485 DIR pin polarity"
|
||||
default 1
|
||||
range 0 1
|
||||
depends on ESP32S2_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 ESP32S2_UART0_TXPIN
|
||||
int "UART0 Tx Pin"
|
||||
default 43
|
||||
@@ -609,6 +634,31 @@ endif # ESP32S2_UART0
|
||||
|
||||
if ESP32S2_UART1
|
||||
|
||||
config ESP32S2_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 ESP32S2_UART1_RS485_DIR_PIN
|
||||
int "UART1 RS-485 DIR pin"
|
||||
default 14
|
||||
range 0 46
|
||||
depends on ESP32S2_UART1_RS485
|
||||
---help---
|
||||
DIR pin for RS-485 on UART1. This pin will control the RS485 enable
|
||||
TX of the RS485 transceiver.
|
||||
|
||||
config ESP32S2_UART1_RS485_DIR_POLARITY
|
||||
int "UART1 RS-485 DIR pin polarity"
|
||||
default 1
|
||||
range 0 1
|
||||
depends on ESP32S2_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 ESP32S2_UART1_TXPIN
|
||||
int "UART1 Tx Pin"
|
||||
default 17
|
||||
|
||||
@@ -43,6 +43,13 @@
|
||||
# define HAVE_UART_DEVICE 1
|
||||
#endif
|
||||
|
||||
/* Is RS-485 used? */
|
||||
|
||||
#if defined(CONFIG_ESP32S2_UART0_RS485) || \
|
||||
defined(CONFIG_ESP32S2_UART1_RS485)
|
||||
# define HAVE_RS485 1
|
||||
#endif
|
||||
|
||||
/* Serial Console ***********************************************************/
|
||||
|
||||
/* Is there a serial console? There should be no more than one defined. It
|
||||
|
||||
@@ -90,6 +90,14 @@ struct esp32s2_uart_s g_uart0_config =
|
||||
.oflow = false, /* output flow control (CTS) disabled */
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_ESP32S2_UART0_RS485
|
||||
.rs485_dir_gpio = CONFIG_ESP32S2_UART0_RS485_DIR_PIN,
|
||||
#if (CONFIG_ESP32S2_UART0_RS485_DIR_POLARITY == 0)
|
||||
.rs485_dir_polarity = false,
|
||||
#else
|
||||
.rs485_dir_polarity = true,
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* CONFIG_ESP32S2_UART0 */
|
||||
@@ -129,6 +137,14 @@ struct esp32s2_uart_s g_uart1_config =
|
||||
.oflow = false, /* output flow control (CTS) disabled */
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_ESP32S2_UART1_RS485
|
||||
.rs485_dir_gpio = CONFIG_ESP32S2_UART1_RS485_DIR_PIN,
|
||||
#if (CONFIG_ESP32S2_UART1_RS485_DIR_POLARITY == 0)
|
||||
.rs485_dir_polarity = false,
|
||||
#else
|
||||
.rs485_dir_polarity = true,
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* CONFIG_ESP32S2_UART1 */
|
||||
@@ -501,6 +517,25 @@ void esp32s2_lowputc_stop_length(const struct esp32s2_uart_s *priv)
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_lowputc_set_tx_idle_time
|
||||
*
|
||||
* Description:
|
||||
* Set the idle time between transfers.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Pointer to the private driver struct.
|
||||
* time - Desired time interval between the transfers.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void esp32s2_lowputc_set_tx_idle_time(const struct esp32s2_uart_s *priv,
|
||||
uint32_t time)
|
||||
{
|
||||
modifyreg32(UART_IDLE_CONF_REG(priv->id), UART_TX_IDLE_NUM_M,
|
||||
VALUE_TO_FIELD(time, UART_TX_IDLE_NUM));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_lowputc_send_byte
|
||||
*
|
||||
@@ -716,6 +751,15 @@ void esp32s2_lowputc_config_pins(const struct esp32s2_uart_s *priv)
|
||||
esp32s2_gpio_matrix_in(priv->ctspin, priv->ctssig, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RS485
|
||||
if (priv->rs485_dir_gpio != 0)
|
||||
{
|
||||
esp32s2_configgpio(priv->rs485_dir_gpio, OUTPUT);
|
||||
esp32s2_gpio_matrix_out(priv->rs485_dir_gpio, SIG_GPIO_OUT_IDX, 0, 0);
|
||||
esp32s2_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -102,6 +102,10 @@ struct esp32s2_uart_s
|
||||
uint8_t ctssig; /* CTS signal */
|
||||
bool oflow; /* Output flow control (CTS) enabled */
|
||||
#endif
|
||||
#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
|
||||
};
|
||||
|
||||
extern struct esp32s2_uart_s g_uart0_config;
|
||||
@@ -297,6 +301,21 @@ int esp32s2_lowputc_data_length(const struct esp32s2_uart_s *priv);
|
||||
|
||||
void esp32s2_lowputc_stop_length(const struct esp32s2_uart_s *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_lowputc_set_tx_idle_time
|
||||
*
|
||||
* Description:
|
||||
* Set the idle time between transfers.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Pointer to the private driver struct.
|
||||
* time - Desired time interval between the transfers.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void esp32s2_lowputc_set_tx_idle_time(const struct esp32s2_uart_s *priv,
|
||||
uint32_t time);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_lowputc_send_byte
|
||||
*
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "esp32s2_config.h"
|
||||
#include "esp32s2_irq.h"
|
||||
#include "esp32s2_lowputc.h"
|
||||
#include "esp32s2_gpio.h"
|
||||
#include "hardware/esp32s2_uart.h"
|
||||
#include "hardware/esp32s2_system.h"
|
||||
|
||||
@@ -237,6 +238,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 &&
|
||||
esp32s2_txempty(dev))
|
||||
{
|
||||
if (dev->xmit.tail == dev->xmit.head)
|
||||
{
|
||||
esp32s2_gpiowrite(priv->rs485_dir_gpio,
|
||||
!priv->rs485_dir_polarity);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TX FIFO empty interrupt or UART TX done int */
|
||||
|
||||
if (int_status & tx_mask)
|
||||
@@ -369,6 +382,21 @@ static int esp32s2_setup(struct uart_dev_s *dev)
|
||||
esp32s2_lowputc_set_oflow(priv, false);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_RS485
|
||||
|
||||
/* Configure the idle time between transfers */
|
||||
|
||||
if (priv->rs485_dir_gpio != 0)
|
||||
{
|
||||
esp32s2_lowputc_set_tx_idle_time(priv, 1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* No Tx idle interval */
|
||||
|
||||
esp32s2_lowputc_set_tx_idle_time(priv, 0);
|
||||
}
|
||||
|
||||
/* Reset FIFOs */
|
||||
|
||||
@@ -513,6 +541,18 @@ static void esp32s2_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 FIFO is empty or
|
||||
* a transmission is done.
|
||||
*/
|
||||
@@ -658,7 +698,16 @@ static bool esp32s2_txempty(struct uart_dev_s *dev)
|
||||
|
||||
static void esp32s2_send(struct uart_dev_s *dev, int ch)
|
||||
{
|
||||
esp32s2_lowputc_send_byte(dev->priv, ch);
|
||||
struct esp32s2_uart_s *priv = dev->priv;
|
||||
|
||||
#ifdef HAVE_RS485
|
||||
if (priv->rs485_dir_gpio != 0)
|
||||
{
|
||||
esp32s2_gpiowrite(priv->rs485_dir_gpio, priv->rs485_dir_polarity);
|
||||
}
|
||||
#endif
|
||||
|
||||
esp32s2_lowputc_send_byte(priv, (char)ch);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user