You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/01/10 02:49:26 UTC
[incubator-nuttx] 01/02: esp32: Add support to RS485
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/incubator-nuttx.git
commit 2079cc0f6e479e93be2bf3f54c6cc85492b81752
Author: Alan C. Assis <ac...@gmail.com>
AuthorDate: Sat Jan 8 18:25:30 2022 -0300
esp32: Add support to RS485
---
arch/xtensa/src/esp32/Kconfig | 78 ++++++++++++++++++++++++++++++++++++
arch/xtensa/src/esp32/esp32_config.h | 8 ++++
arch/xtensa/src/esp32/esp32_serial.c | 78 +++++++++++++++++++++++++++++++++++-
3 files changed, 163 insertions(+), 1 deletion(-)
diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig
index 67d2894..4c0d3b1 100644
--- a/arch/xtensa/src/esp32/Kconfig
+++ b/arch/xtensa/src/esp32/Kconfig
@@ -566,6 +566,32 @@ menu "UART configuration"
if ESP32_UART0
+config ESP32_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. Currently it cannot be
+ used with UART0_RXDMA.
+
+config ESP32_UART0_RS485_DIR_PIN
+ int "UART0 RS-485 DIR pin"
+ default 4
+ range 1 39
+ depends on ESP32_UART0_RS485
+ ---help---
+ DIR pin for RS-485 on UART0. This pin will control the RS485 enable
+ TX of the RS485 transceiver.
+
+config ESP32_UART0_RS485_DIR_POLARITY
+ int "UART0 RS-485 DIR pin polarity"
+ default 1
+ range 0 1
+ depends on ESP32_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 ESP32_UART0_TXPIN
int "UART0 Tx Pin"
default 1
@@ -606,6 +632,32 @@ endif # ESP32_UART0
if ESP32_UART1
+config ESP32_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. Currently it cannot be
+ used with UART1_RXDMA.
+
+config ESP32_UART1_RS485_DIR_PIN
+ int "UART1 RS-485 DIR pin"
+ default 14
+ range 1 39
+ depends on ESP32_UART1_RS485
+ ---help---
+ DIR pin for RS-485 on UART1. This pin will control the RS485 enable
+ TX of the RS485 transceiver.
+
+config ESP32_UART1_RS485_DIR_POLARITY
+ int "UART1 RS-485 DIR pin polarity"
+ default 1
+ range 0 1
+ depends on ESP32_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 ESP32_UART1_TXPIN
int "UART1 Tx Pin"
default 10
@@ -646,6 +698,32 @@ endif # ESP32_UART1
if ESP32_UART2
+config ESP32_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. Currently it cannot be
+ used with UART2_RXDMA.
+
+config ESP32_UART2_RS485_DIR_PIN
+ int "UART2 RS-485 DIR pin"
+ default 18
+ range 1 39
+ depends on ESP32_UART2_RS485
+ ---help---
+ DIR pin for RS-485 on UART2. This pin will control the RS485 enable
+ TX of the RS485 transceiver.
+
+config ESP32_UART2_RS485_DIR_POLARITY
+ int "UART2 RS-485 DIR pin polarity"
+ default 1
+ range 0 1
+ depends on ESP32_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 ESP32_UART2_TXPIN
int "UART2 Tx Pin"
default 19
diff --git a/arch/xtensa/src/esp32/esp32_config.h b/arch/xtensa/src/esp32/esp32_config.h
index 4f16f25..47e154e 100644
--- a/arch/xtensa/src/esp32/esp32_config.h
+++ b/arch/xtensa/src/esp32/esp32_config.h
@@ -59,6 +59,14 @@
# define HAVE_UART_DEVICE 1
#endif
+/* Is RS-485 used? */
+
+#if defined(CONFIG_ESP32_UART0_RS485) || \
+ defined(CONFIG_ESP32_UART1_RS485) || \
+ defined(CONFIG_ESP32_UART2_RS485)
+# define HAVE_RS485 1
+#endif
+
/* UART Flow Control ********************************************************/
#ifndef CONFIG_ESP32_UART0
diff --git a/arch/xtensa/src/esp32/esp32_serial.c b/arch/xtensa/src/esp32/esp32_serial.c
index f56eb5a..e10e999 100644
--- a/arch/xtensa/src/esp32/esp32_serial.c
+++ b/arch/xtensa/src/esp32/esp32_serial.c
@@ -246,6 +246,10 @@ struct esp32_config_s
uint8_t dma_chan; /* DMA instance 0-1 */
sem_t * dma_sem; /* DMA semaphore */
#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
};
/* Current state of the UART */
@@ -380,6 +384,14 @@ static const struct esp32_config_s g_uart0config =
#endif
#endif
#endif
+#ifdef CONFIG_ESP32_UART0_RS485
+ .rs485_dir_gpio = CONFIG_ESP32_UART0_RS485_DIR_PIN,
+#if (CONFIG_ESP32_UART0_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+#else
+ .rs485_dir_polarity = true,
+#endif
+#endif
};
static struct esp32_dev_s g_uart0priv =
@@ -459,6 +471,14 @@ static const struct esp32_config_s g_uart1config =
#endif
#endif
#endif
+#ifdef CONFIG_ESP32_UART1_RS485
+ .rs485_dir_gpio = CONFIG_ESP32_UART1_RS485_DIR_PIN,
+#if (CONFIG_ESP32_UART1_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+#else
+ .rs485_dir_polarity = true,
+#endif
+#endif
};
static struct esp32_dev_s g_uart1priv =
@@ -538,6 +558,14 @@ static const struct esp32_config_s g_uart2config =
#endif
#endif
#endif
+#ifdef CONFIG_ESP32_UART2_RS485
+ .rs485_dir_gpio = CONFIG_ESP32_UART2_RS485_DIR_PIN,
+#if (CONFIG_ESP32_UART2_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+#else
+ .rs485_dir_polarity = true,
+#endif
+#endif
};
static struct esp32_dev_s g_uart2priv =
@@ -1345,9 +1373,26 @@ static int esp32_interrupt(int cpuint, void *context, void *arg)
regval = (UART_RXFIFO_FULL_INT_CLR | UART_FRM_ERR_INT_CLR |
UART_RXFIFO_TOUT_INT_CLR | UART_TX_DONE_INT_CLR |
- UART_TXFIFO_EMPTY_INT_CLR);
+ UART_TXFIFO_EMPTY_INT_CLR | UART_TX_BRK_IDLE_DONE_INT_CLR);
putreg32(regval, UART_INT_CLR_REG(priv->config->id));
+#ifdef HAVE_RS485
+ if ((enabled & UART_TX_BRK_IDLE_DONE_INT_ENA) != 0 &&
+ (status & UART_TX_DONE_INT_ST) != 0)
+ {
+ /* If al bytes were transmited, then we can disable the RS485
+ * transmit (TX/nTX) pin.
+ */
+
+ nfifo = REG_MASK(status, UART_TXFIFO_CNT);
+ if (nfifo == 0)
+ {
+ esp32_gpiowrite(priv->config->rs485_dir_gpio,
+ !priv->config->rs485_dir_polarity);
+ }
+ }
+#endif
+
/* Are Rx interrupts enabled? The upper layer may hold off Rx input
* by disabling the Rx interrupts if there is no place to saved the
* data, possibly resulting in an overrun error.
@@ -1697,6 +1742,14 @@ static void esp32_send(struct uart_dev_s *dev, int ch)
{
struct esp32_dev_s *priv = (struct esp32_dev_s *)dev->priv;
+#ifdef HAVE_RS485
+ if (priv->config->rs485_dir_gpio != 0)
+ {
+ esp32_gpiowrite(priv->config->rs485_dir_gpio,
+ priv->config->rs485_dir_polarity);
+ }
+#endif
+
putreg32((uint32_t)ch, AHB_UART_FIFO_REG(priv->config->id));
}
@@ -1720,6 +1773,18 @@ static void esp32_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->config->rs485_dir_gpio != 0)
+ {
+ modifyreg32(UART_INT_ENA_REG(priv->config->id),
+ 0, UART_TX_BRK_IDLE_DONE_INT_ENA);
+ }
+ #endif
+
/* Set to receive an interrupt when the TX holding register
* is empty.
*/
@@ -1829,6 +1894,17 @@ static void esp32_config_pins(struct esp32_dev_s *priv)
esp32_gpio_matrix_in(priv->config->ctspin, priv->config->ctssig, 0);
}
#endif
+
+#ifdef HAVE_RS485
+ if (priv->config->rs485_dir_gpio != 0)
+ {
+ esp32_configgpio(priv->config->rs485_dir_gpio, OUTPUT_FUNCTION_3);
+ esp32_gpio_matrix_out(priv->config->rs485_dir_gpio,
+ SIG_GPIO_OUT_IDX, 0, 0);
+ esp32_gpiowrite(priv->config->rs485_dir_gpio,
+ !priv->config->rs485_dir_polarity);
+ }
+#endif
}
/****************************************************************************