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 2021/06/02 02:37:34 UTC
[incubator-nuttx] branch master updated: risc-v/esp32-c3: Add
support for HW flow control.
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
The following commit(s) were added to refs/heads/master by this push:
new b54be4e risc-v/esp32-c3: Add support for HW flow control.
b54be4e is described below
commit b54be4e946b3d9bf0bdf55207abc11dec78bdd76
Author: Sara Souza <sa...@espressif.com>
AuthorDate: Fri May 28 14:42:24 2021 -0300
risc-v/esp32-c3: Add support for HW flow control.
---
arch/risc-v/src/esp32c3/Kconfig | 28 +++++-
arch/risc-v/src/esp32c3/esp32c3_lowputc.c | 119 ++++++++++++++++++++++++
arch/risc-v/src/esp32c3/esp32c3_lowputc.h | 42 +++++++++
arch/risc-v/src/esp32c3/esp32c3_serial.c | 150 +++++++++++++++++++++++++++++-
4 files changed, 332 insertions(+), 7 deletions(-)
diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig
index 2222e6a..e102dcb 100644
--- a/arch/risc-v/src/esp32c3/Kconfig
+++ b/arch/risc-v/src/esp32c3/Kconfig
@@ -413,17 +413,41 @@ config ESP32C3_UART0_RXPIN
int "UART0 RX Pin"
default 20
+config ESP32C3_UART0_RTSPIN
+ int "UART0 RTS Pin"
+ depends on SERIAL_IFLOWCONTROL
+ default 16
+ range 0 21
+
+config ESP32C3_UART0_CTSPIN
+ int "UART0 CTS Pin"
+ depends on SERIAL_OFLOWCONTROL
+ default 15
+ range 0 21
+
endif # ESP32C3_UART0
if ESP32C3_UART1
config ESP32C3_UART1_TXPIN
int "UART1 TX Pin"
- default 6
+ default 8
config ESP32C3_UART1_RXPIN
int "UART1 RX Pin"
- default 7
+ default 9
+
+config ESP32C3_UART1_RTSPIN
+ int "UART1 RTS Pin"
+ depends on SERIAL_IFLOWCONTROL
+ default 1
+ range 0 21
+
+config ESP32C3_UART1_CTSPIN
+ int "UART1 CTS Pin"
+ depends on SERIAL_OFLOWCONTROL
+ default 2
+ range 0 21
endif # ESP32C3_UART1
diff --git a/arch/risc-v/src/esp32c3/esp32c3_lowputc.c b/arch/risc-v/src/esp32c3/esp32c3_lowputc.c
index 1aa4fdd..18e3842 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_lowputc.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_lowputc.c
@@ -74,6 +74,24 @@ struct esp32c3_uart_s g_uart0_config =
.txsig = U0TXD_OUT_IDX,
.rxpin = CONFIG_ESP32C3_UART0_RXPIN,
.rxsig = U0RXD_IN_IDX,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+ .rtspin = CONFIG_ESP32C3_UART0_RTSPIN,
+ .rtssig = U0RTS_OUT_IDX,
+#ifdef CONFIG_UART0_IFLOWCONTROL
+ .iflow = true, /* input flow control (RTS) enabled */
+#else
+ .iflow = false, /* input flow control (RTS) disabled */
+#endif
+#endif
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+ .ctspin = CONFIG_ESP32C3_UART0_CTSPIN,
+ .ctssig = U0CTS_IN_IDX,
+#ifdef CONFIG_UART0_OFLOWCONTROL
+ .oflow = true, /* output flow control (CTS) enabled */
+#else
+ .oflow = false, /* output flow control (CTS) disabled */
+#endif
+#endif
};
#endif /* CONFIG_ESP32C3_UART0 */
@@ -95,6 +113,24 @@ struct esp32c3_uart_s g_uart1_config =
.txsig = U1TXD_OUT_IDX,
.rxpin = CONFIG_ESP32C3_UART1_RXPIN,
.rxsig = U1RXD_IN_IDX,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+ .rtspin = CONFIG_ESP32C3_UART1_RTSPIN,
+ .rtssig = U1RTS_OUT_IDX,
+#ifdef CONFIG_UART1_IFLOWCONTROL
+ .iflow = true, /* input flow control (RTS) enabled */
+#else
+ .iflow = false, /* input flow control (RTS) disabled */
+#endif
+#endif
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+ .ctspin = CONFIG_ESP32C3_UART1_CTSPIN,
+ .ctssig = U1CTS_IN_IDX,
+#ifdef CONFIG_UART1_OFLOWCONTROL
+ .oflow = true, /* output flow control (CTS) enabled */
+#else
+ .oflow = false, /* output flow control (CTS) disabled */
+#endif
+#endif
};
#endif /* CONFIG_ESP32C3_UART1 */
@@ -105,6 +141,72 @@ struct esp32c3_uart_s g_uart1_config =
****************************************************************************/
/****************************************************************************
+ * Name: esp32c3_lowputc_set_iflow
+ *
+ * Description:
+ * Configure the input hardware flow control.
+ *
+ * Parameters:
+ * priv - Pointer to the private driver struct.
+ * threshold - RX FIFO value from which RST will automatically be
+ * asserted.
+ * enable - true = enable, false = disable
+ *
+ ****************************************************************************/
+
+void esp32c3_lowputc_set_iflow(const struct esp32c3_uart_s *priv,
+ uint8_t threshold, bool enable)
+{
+ uint32_t mask;
+ if (enable)
+ {
+ /* Enable RX flow control */
+
+ modifyreg32(UART_CONF1_REG(priv->id), 0, UART_RX_FLOW_EN);
+
+ /* Configure the threshold */
+
+ mask = VALUE_TO_FIELD(threshold, UART_RX_FLOW_THRHD);
+ modifyreg32(UART_MEM_CONF_REG(priv->id), UART_RX_FLOW_THRHD_M, mask);
+ }
+ else
+ {
+ /* Disable RX flow control */
+
+ modifyreg32(UART_CONF1_REG(priv->id), UART_RX_FLOW_EN, 0);
+ }
+}
+
+/****************************************************************************
+ * Name: esp32c3_lowputc_set_oflow
+ *
+ * Description:
+ * Configure the output hardware flow control.
+ *
+ * Parameters:
+ * priv - Pointer to the private driver struct.
+ * enable - true = enable, false = disable
+ *
+ ****************************************************************************/
+
+void esp32c3_lowputc_set_oflow(const struct esp32c3_uart_s *priv,
+ bool enable)
+{
+ if (enable)
+ {
+ /* Enable TX flow control */
+
+ modifyreg32(UART_CONF0_REG(priv->id), 0, UART_TX_FLOW_EN);
+ }
+ else
+ {
+ /* Disable TX flow control */
+
+ modifyreg32(UART_CONF0_REG(priv->id), UART_TX_FLOW_EN, 0);
+ }
+}
+
+/****************************************************************************
* Name: esp32c3_lowputc_reset_core
*
* Description:
@@ -642,6 +744,23 @@ void esp32c3_lowputc_config_pins(const struct esp32c3_uart_s *priv)
esp32c3_configgpio(priv->rxpin, INPUT_FUNCTION_1);
esp32c3_gpio_matrix_in(priv->rxpin, priv->rxsig, 0);
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+ if (priv->iflow)
+ {
+ esp32c3_configgpio(priv->rtspin, OUTPUT_FUNCTION_1);
+ esp32c3_gpio_matrix_out(priv->rtspin, priv->rtssig,
+ 0, 0);
+ }
+
+#endif
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+ if (priv->oflow)
+ {
+ esp32c3_configgpio(priv->ctspin, INPUT_FUNCTION_1);
+ esp32c3_gpio_matrix_in(priv->ctspin, priv->ctssig, 0);
+ }
+#endif
}
/****************************************************************************
diff --git a/arch/risc-v/src/esp32c3/esp32c3_lowputc.h b/arch/risc-v/src/esp32c3/esp32c3_lowputc.h
index d429571..e8455ca 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_lowputc.h
+++ b/arch/risc-v/src/esp32c3/esp32c3_lowputc.h
@@ -105,6 +105,16 @@ struct esp32c3_uart_s
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 */
+#endif
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+ uint8_t ctspin; /* CTS pin number */
+ uint8_t ctssig; /* CTS signal */
+ bool oflow; /* Output flow control (CTS) enabled */
+#endif
};
extern struct esp32c3_uart_s g_uart0_config;
@@ -115,6 +125,38 @@ extern struct esp32c3_uart_s g_uart1_config;
****************************************************************************/
/****************************************************************************
+ * Name: esp32c3_lowputc_set_iflow
+ *
+ * Description:
+ * Configure the input hardware flow control.
+ *
+ * Parameters:
+ * priv - Pointer to the private driver struct.
+ * threshold - RX FIFO value from which RST will automatically be
+ * asserted.
+ * enable - true = enable, false = disable
+ *
+ ****************************************************************************/
+
+void esp32c3_lowputc_set_iflow(const struct esp32c3_uart_s *priv,
+ uint8_t threshold, bool enable);
+
+/****************************************************************************
+ * Name: esp32c3_lowputc_set_oflow
+ *
+ * Description:
+ * Configure the output hardware flow control.
+ *
+ * Parameters:
+ * priv - Pointer to the private driver struct.
+ * enable - true = enable, false = disable
+ *
+ ****************************************************************************/
+
+void esp32c3_lowputc_set_oflow(const struct esp32c3_uart_s *priv,
+ bool enable);
+
+/****************************************************************************
* Name: esp32c3_lowputc_reset_core
*
* Description:
diff --git a/arch/risc-v/src/esp32c3/esp32c3_serial.c b/arch/risc-v/src/esp32c3/esp32c3_serial.c
index 196a8b0..4670d20 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_serial.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_serial.c
@@ -122,6 +122,10 @@ static bool esp32c3_txempty(struct uart_dev_s *dev);
static void esp32c3_send(struct uart_dev_s *dev, int ch);
static int esp32c3_receive(struct uart_dev_s *dev, unsigned int *status);
static int esp32c3_ioctl(struct file *filep, int cmd, unsigned long arg);
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+static bool esp32c3_rxflowcontrol(struct uart_dev_s *dev,
+ unsigned int nbuffered, bool upper);
+#endif
/****************************************************************************
* Private Data
@@ -144,7 +148,7 @@ static struct uart_ops_s g_uart_ops =
.receive = esp32c3_receive,
.ioctl = esp32c3_ioctl,
#ifdef CONFIG_SERIAL_IFLOWCONTROL
- .rxflowcontrol = NULL,
+ .rxflowcontrol = esp32c3_rxflowcontrol,
#endif
};
@@ -244,16 +248,16 @@ static int uart_handler(int irq, FAR void *context, FAR void *arg)
if (int_status & tx_mask)
{
- uart_xmitchars(dev);
- modifyreg32(UART_INT_CLR_REG(priv->id), tx_mask, tx_mask);
+ uart_xmitchars(dev);
+ modifyreg32(UART_INT_CLR_REG(priv->id), tx_mask, tx_mask);
}
/* Rx fifo timeout interrupt or rx fifo full interrupt */
if (int_status & rx_mask)
{
- uart_recvchars(dev);
- modifyreg32(UART_INT_CLR_REG(priv->id), rx_mask, rx_mask);
+ uart_recvchars(dev);
+ modifyreg32(UART_INT_CLR_REG(priv->id), rx_mask, rx_mask);
}
return OK;
@@ -332,6 +336,44 @@ static int esp32c3_setup(struct uart_dev_s *dev)
esp32c3_lowputc_stop_length(priv);
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+ /* Configure the input flow control */
+
+ if (priv->iflow)
+ {
+ /* Enable input flow control and set the RX FIFO threshold
+ * to assert the RTS line to half the RX FIFO buffer.
+ * It will then save some space on the hardware fifo to
+ * remaining bytes that may arrive after RTS be asserted
+ * and before the transmitter stops sending data.
+ */
+
+ esp32c3_lowputc_set_iflow(priv, (uint8_t)(UART_RX_FIFO_SIZE / 2),
+ true);
+ }
+ else
+ {
+ /* Just disable input flow control, threshold parameter
+ * will be discarded.
+ */
+
+ esp32c3_lowputc_set_iflow(priv, 0 , false);
+ }
+
+#endif
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+ /* Configure the ouput flow control */
+
+ if (priv->oflow)
+ {
+ esp32c3_lowputc_set_oflow(priv, true);
+ }
+ else
+ {
+ esp32c3_lowputc_set_oflow(priv, false);
+ }
+#endif
+
/* No Tx idle interval */
esp32c3_lowputc_set_tx_idle_time(priv, 0);
@@ -725,6 +767,13 @@ static int esp32c3_ioctl(struct file *filep, int cmd, unsigned long arg)
termiosp->c_cflag |= (priv->stop_b2) ? CSTOPB : 0;
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+ termiosp->c_cflag |= (priv->oflow) ? CCTS_OFLOW : 0;
+#endif
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+ termiosp->c_cflag |= (priv->iflow) ? CRTS_IFLOW : 0;
+#endif
+
/* Set the baud rate in ther termiosp using the
* cfsetispeed interface.
*/
@@ -764,6 +813,12 @@ static int esp32c3_ioctl(struct file *filep, int cmd, unsigned long arg)
uint8_t parity;
uint8_t bits;
uint8_t stop2;
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+ bool iflow;
+#endif
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+ bool oflow;
+#endif
if (!termiosp)
{
@@ -815,6 +870,13 @@ static int esp32c3_ioctl(struct file *filep, int cmd, unsigned long arg)
stop2 = (termiosp->c_cflag & CSTOPB) ? 1 : 0;
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+ iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
+#endif
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+ oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
+#endif
+
/* Verify that all settings are valid before
* performing the changes.
*/
@@ -827,6 +889,12 @@ static int esp32c3_ioctl(struct file *filep, int cmd, unsigned long arg)
priv->parity = parity;
priv->bits = bits;
priv->stop_b2 = stop2;
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+ priv->iflow = iflow;
+#endif
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+ priv->oflow = oflow;
+#endif
/* Effect the changes immediately - note that we do not
* implement TCSADRAIN or TCSAFLUSH, only TCSANOW option.
@@ -853,6 +921,78 @@ static int esp32c3_ioctl(struct file *filep, int cmd, unsigned long arg)
}
/****************************************************************************
+ * Name: esp32c3_rxflowcontrol
+ *
+ * Description:
+ * Called when upper half RX buffer is full (or exceeds configured
+ * watermark levels if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is defined).
+ * Return true if UART activated RX flow control to block more incoming
+ * data.
+ * NOTE: ESP32-C3 has a hardware RX FIFO threshold mechanism to control
+ * RTS line and to stop receiving data. This is very similar to the concept
+ * behind upper watermark level. The hardware threshold is used here
+ * to control the RTS line. When setting the threshold to zero, RTS will
+ * immediately be asserted. If nbuffered = 0 or the lower watermark is
+ * crossed and the serial driver decides to disable RX flow control, the
+ * threshold will be changed to UART_RX_FLOW_THRHD_VALUE, which is almost
+ * half the HW RX FIFO capacity. It keeps some space to keep the data
+ * received between the RTS assertion and the stop by the sender.
+ *
+ * Input Parameters:
+ * dev - UART device instance
+ * nbuffered - the number of characters currently buffered
+ * (if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is
+ * not defined the value will be 0 for an empty buffer or the
+ * defined buffer size for a full buffer)
+ * upper - true indicates the upper watermark was crossed where
+ * false indicates the lower watermark has been crossed
+ *
+ * Returned Value:
+ * true if RX flow control activated.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+static bool esp32c3_rxflowcontrol(struct uart_dev_s *dev,
+ unsigned int nbuffered, bool upper)
+{
+ bool ret = false;
+ struct esp32c3_uart_s *priv = dev->priv;
+ if (priv->iflow)
+ {
+ if (nbuffered == 0 || upper == false)
+ {
+ /* Empty buffer, RTS should be de-asserted and logic in above
+ * layers should re-enable RX interrupt.
+ */
+
+ esp32c3_lowputc_set_iflow(priv, (uint8_t)(UART_RX_FIFO_SIZE / 2),
+ true);
+ esp32c3_rxint(dev, true);
+ ret = false;
+ }
+ else
+ {
+ /* If the RX buffer is not zero and watermarks are not enabled,
+ * then this function is called to announce RX buffer is full.
+ * The first thing it should do is to immediately assert RTS.
+ * Software RX FIFO is full, so besides asserting RTS, it's
+ * necessary to disable RX interrupts to prevent remaining bytes
+ * (that arrive after asserting RTS) to be pushed to the
+ * SW RX FIFO.
+ */
+
+ esp32c3_lowputc_set_iflow(priv, 0 , true);
+ esp32c3_rxint(dev, false);
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/