aboutsummaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/stm32/stm32_serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/arch/arm/src/stm32/stm32_serial.c')
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_serial.c340
1 files changed, 185 insertions, 155 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_serial.c b/nuttx/arch/arm/src/stm32/stm32_serial.c
index 0868c3cd3..c7f97b25a 100644
--- a/nuttx/arch/arm/src/stm32/stm32_serial.c
+++ b/nuttx/arch/arm/src/stm32/stm32_serial.c
@@ -96,6 +96,19 @@
# endif
# endif
+/* Currently RS-485 support cannot be enabled when RXDMA is in use due to lack
+ * of testing - RS-485 support was developed on STM32F1x
+ */
+
+# if (defined(CONFIG_USART1_RXDMA) && defined(CONFIG_USART1_RS485)) || \
+ (defined(CONFIG_USART2_RXDMA) && defined(CONFIG_USART2_RS485)) || \
+ (defined(CONFIG_USART3_RXDMA) && defined(CONFIG_USART3_RS485)) || \
+ (defined(CONFIG_UART4_RXDMA) && defined(CONFIG_UART4_RS485)) || \
+ (defined(CONFIG_UART5_RXDMA) && defined(CONFIG_UART5_RS485)) || \
+ (defined(CONFIG_USART6_RXDMA) && defined(CONFIG_USART6_RS485))
+# error "RXDMA and RS-485 cannot be enabled at the same time for the same U[S]ART"
+# endif
+
/* For the F4, there are alternate DMA channels for USART1 and 6.
* Logic in the board.h file make the DMA channel selection by defining
* the following in the board.h file.
@@ -185,15 +198,11 @@ struct up_dev_s
uint8_t parity; /* 0=none, 1=odd, 2=even */
uint8_t bits; /* Number of bits (7 or 8) */
bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */
- bool iflow; /* input flow control (RTS) enabled */
- bool oflow; /* output flow control (CTS) enabled */
uint32_t baud; /* Configured baud */
#else
const uint8_t parity; /* 0=none, 1=odd, 2=even */
const uint8_t bits; /* Number of bits (7 or 8) */
const bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */
- const bool iflow; /* input flow control (RTS) enabled */
- const bool oflow; /* output flow control (CTS) enabled */
const uint32_t baud; /* Configured baud */
#endif
@@ -219,13 +228,18 @@ struct up_dev_s
uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
char *const rxfifo; /* Receive DMA buffer */
#endif
+
+#ifdef HAVE_RS485
+ const uint32_t rs485_dir_gpio; /* U[S]ART RS-485 DIR GPIO pin configuration */
+ const bool rs485_dir_polarity; /* U[S]ART RS-485 DIR pin state for TX enabled */
+#endif
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
-static void up_set_format(struct uart_dev_s *dev);
+static void up_setspeed(struct uart_dev_s *dev);
static int up_setup(struct uart_dev_s *dev);
static void up_shutdown(struct uart_dev_s *dev);
static int up_attach(struct uart_dev_s *dev);
@@ -397,8 +411,6 @@ static struct up_dev_s g_usart1priv =
.parity = CONFIG_USART1_PARITY,
.bits = CONFIG_USART1_BITS,
.stopbits2 = CONFIG_USART1_2STOP,
- .iflow = false,
- .oflow = false,
.baud = CONFIG_USART1_BAUD,
.apbclock = STM32_PCLK2_FREQUENCY,
.usartbase = STM32_USART1_BASE,
@@ -415,6 +427,15 @@ static struct up_dev_s g_usart1priv =
.rxfifo = g_usart1rxfifo,
#endif
.vector = up_interrupt_usart1,
+
+#ifdef CONFIG_USART1_RS485
+ .rs485_dir_gpio = GPIO_USART1_RS485_DIR,
+# if (CONFIG_USART1_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+# else
+ .rs485_dir_polarity = true,
+# endif
+#endif
};
#endif
@@ -450,8 +471,6 @@ static struct up_dev_s g_usart2priv =
.parity = CONFIG_USART2_PARITY,
.bits = CONFIG_USART2_BITS,
.stopbits2 = CONFIG_USART2_2STOP,
- .iflow = false,
- .oflow = false,
.baud = CONFIG_USART2_BAUD,
.apbclock = STM32_PCLK1_FREQUENCY,
.usartbase = STM32_USART2_BASE,
@@ -468,6 +487,15 @@ static struct up_dev_s g_usart2priv =
.rxfifo = g_usart2rxfifo,
#endif
.vector = up_interrupt_usart2,
+
+#ifdef CONFIG_USART2_RS485
+ .rs485_dir_gpio = GPIO_USART2_RS485_DIR,
+# if (CONFIG_USART2_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+# else
+ .rs485_dir_polarity = true,
+# endif
+#endif
};
#endif
@@ -503,8 +531,6 @@ static struct up_dev_s g_usart3priv =
.parity = CONFIG_USART3_PARITY,
.bits = CONFIG_USART3_BITS,
.stopbits2 = CONFIG_USART3_2STOP,
- .iflow = false,
- .oflow = false,
.baud = CONFIG_USART3_BAUD,
.apbclock = STM32_PCLK1_FREQUENCY,
.usartbase = STM32_USART3_BASE,
@@ -521,6 +547,15 @@ static struct up_dev_s g_usart3priv =
.rxfifo = g_usart3rxfifo,
#endif
.vector = up_interrupt_usart3,
+
+#ifdef CONFIG_USART3_RS485
+ .rs485_dir_gpio = GPIO_USART3_RS485_DIR,
+# if (CONFIG_USART3_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+# else
+ .rs485_dir_polarity = true,
+# endif
+#endif
};
#endif
@@ -556,20 +591,31 @@ static struct up_dev_s g_uart4priv =
.parity = CONFIG_UART4_PARITY,
.bits = CONFIG_UART4_BITS,
.stopbits2 = CONFIG_UART4_2STOP,
- .iflow = false,
- .oflow = false,
.baud = CONFIG_UART4_BAUD,
.apbclock = STM32_PCLK1_FREQUENCY,
.usartbase = STM32_UART4_BASE,
.tx_gpio = GPIO_UART4_TX,
.rx_gpio = GPIO_UART4_RX,
- .cts_gpio = 0, /* flow control not supported on this port */
- .rts_gpio = 0, /* flow control not supported on this port */
+#ifdef GPIO_UART4_CTS
+ .cts_gpio = GPIO_UART4_CTS,
+#endif
+#ifdef GPIO_UART4_RTS
+ .rts_gpio = GPIO_UART4_RTS,
+#endif
#ifdef CONFIG_UART4_RXDMA
.rxdma_channel = DMAMAP_UART4_RX,
.rxfifo = g_uart4rxfifo,
#endif
.vector = up_interrupt_uart4,
+
+#ifdef CONFIG_UART4_RS485
+ .rs485_dir_gpio = GPIO_UART4_RS485_DIR,
+# if (CONFIG_UART4_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+# else
+ .rs485_dir_polarity = true,
+# endif
+#endif
};
#endif
@@ -605,20 +651,31 @@ static struct up_dev_s g_uart5priv =
.parity = CONFIG_UART5_PARITY,
.bits = CONFIG_UART5_BITS,
.stopbits2 = CONFIG_UART5_2STOP,
- .iflow = false,
- .oflow = false,
.baud = CONFIG_UART5_BAUD,
.apbclock = STM32_PCLK1_FREQUENCY,
.usartbase = STM32_UART5_BASE,
.tx_gpio = GPIO_UART5_TX,
.rx_gpio = GPIO_UART5_RX,
- .cts_gpio = 0, /* flow control not supported on this port */
- .rts_gpio = 0, /* flow control not supported on this port */
+#ifdef GPIO_UART5_CTS
+ .cts_gpio = GPIO_UART5_CTS,
+#endif
+#ifdef GPIO_UART5_RTS
+ .rts_gpio = GPIO_UART5_RTS,
+#endif
#ifdef CONFIG_UART5_RXDMA
.rxdma_channel = DMAMAP_UART5_RX,
.rxfifo = g_uart5rxfifo,
#endif
.vector = up_interrupt_uart5,
+
+#ifdef CONFIG_UART5_RS485
+ .rs485_dir_gpio = GPIO_UART5_RS485_DIR,
+# if (CONFIG_UART5_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+# else
+ .rs485_dir_polarity = true,
+# endif
+#endif
};
#endif
@@ -654,8 +711,6 @@ static struct up_dev_s g_usart6priv =
.parity = CONFIG_USART6_PARITY,
.bits = CONFIG_USART6_BITS,
.stopbits2 = CONFIG_USART6_2STOP,
- .iflow = false,
- .oflow = false,
.baud = CONFIG_USART6_BAUD,
.apbclock = STM32_PCLK2_FREQUENCY,
.usartbase = STM32_USART6_BASE,
@@ -672,6 +727,15 @@ static struct up_dev_s g_usart6priv =
.rxfifo = g_usart6rxfifo,
#endif
.vector = up_interrupt_usart6,
+
+#ifdef CONFIG_USART6_RS485
+ .rs485_dir_gpio = GPIO_USART6_RS485_DIR,
+# if (CONFIG_USART6_RS485_DIR_POLARITY == 0)
+ .rs485_dir_polarity = false,
+# else
+ .rs485_dir_polarity = true,
+# endif
+#endif
};
#endif
@@ -744,8 +808,8 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
/* And restore the interrupt state (see the interrupt enable/usage table above) */
cr = up_serialin(priv, STM32_USART_CR1_OFFSET);
- cr &= ~(USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE);
- cr |= (ie & (USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE));
+ cr &= ~(USART_CR1_USED_INTS);
+ cr |= (ie & (USART_CR1_USED_INTS));
up_serialout(priv, STM32_USART_CR1_OFFSET, cr);
cr = up_serialin(priv, STM32_USART_CR3_OFFSET);
@@ -772,7 +836,7 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
* USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used)
* USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read
* " " USART_SR_ORE Overrun Error Detected
- * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used)
+ * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (used only for RS-485)
* USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty
* USART_CR1_PEIE 8 USART_SR_PE Parity Error
*
@@ -791,7 +855,7 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
* overlap. This logic would fail if we needed the break interrupt!
*/
- *ie = (cr1 & (USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE)) | (cr3 & USART_CR3_EIE);
+ *ie = (cr1 & (USART_CR1_USED_INTS)) | (cr3 & USART_CR3_EIE);
}
/* Disable all interrupts */
@@ -820,22 +884,21 @@ static int up_dma_nextrx(struct up_dev_s *priv)
#endif
/****************************************************************************
- * Name: up_set_format
+ * Name: up_setspeed
*
* Description:
- * Set the serial line format and speed.
+ * Set the serial line speed.
*
****************************************************************************/
#ifndef CONFIG_SUPPRESS_UART_CONFIG
-static void up_set_format(struct uart_dev_s *dev)
+static void up_setspeed(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
uint32_t usartdiv32;
uint32_t mantissa;
uint32_t fraction;
uint32_t brr;
- uint32_t regval;
/* Configure the USART Baud Rate. The baud rate for the receiver and
* transmitter (Rx and Tx) are both set to the same value as programmed
@@ -853,64 +916,20 @@ static void up_set_format(struct uart_dev_s *dev)
* usartdiv32 = 32 * usartdiv = fCK / (baud/2)
*/
- usartdiv32 = priv->apbclock / (priv->baud >> 1);
-
- /* The mantissa part is then */
-
- mantissa = usartdiv32 >> 5;
- brr = mantissa << USART_BRR_MANT_SHIFT;
-
- /* The fractional remainder (with rounding) */
-
- fraction = (usartdiv32 - (mantissa << 5) + 1) >> 1;
- brr |= fraction << USART_BRR_FRAC_SHIFT;
- up_serialout(priv, STM32_USART_BRR_OFFSET, brr);
-
- /* Configure parity mode */
-
- regval = up_serialin(priv, STM32_USART_CR1_OFFSET);
- regval &= ~(USART_CR1_PCE|USART_CR1_PS);
+ usartdiv32 = priv->apbclock / (priv->baud >> 1);
- if (priv->parity == 1) /* Odd parity */
- {
- regval |= (USART_CR1_PCE|USART_CR1_PS);
- }
- else if (priv->parity == 2) /* Even parity */
- {
- regval |= USART_CR1_PCE;
- }
+ /* The mantissa part is then */
- up_serialout(priv, STM32_USART_CR1_OFFSET, regval);
-
- /* Configure STOP bits */
-
- regval = up_serialin(priv, STM32_USART_CR2_OFFSET);
- regval &= ~(USART_CR2_STOP_MASK);
-
- if (priv->stopbits2)
- {
- regval |= USART_CR2_STOP2;
- }
- up_serialout(priv, STM32_USART_CR2_OFFSET, regval);
-
- /* Configure hardware flow control */
-
- regval = up_serialin(priv, STM32_USART_CR3_OFFSET);
- regval &= ~(USART_CR3_CTSE|USART_CR3_RTSE);
-
- if (priv->iflow && (priv->rts_gpio != 0))
- {
- regval |= USART_CR3_RTSE;
- }
- if (priv->oflow && (priv->cts_gpio != 0))
- {
- regval |= USART_CR3_CTSE;
- }
+ mantissa = usartdiv32 >> 5;
+ brr = mantissa << USART_BRR_MANT_SHIFT;
- up_serialout(priv, STM32_USART_CR3_OFFSET, regval);
+ /* The fractional remainder (with rounding) */
+ fraction = (usartdiv32 - (mantissa << 5) + 1) >> 1;
+ brr |= fraction << USART_BRR_FRAC_SHIFT;
+ up_serialout(priv, STM32_USART_BRR_OFFSET, brr);
}
-#endif /* CONFIG_SUPPRESS_UART_CONFIG */
+#endif
/****************************************************************************
* Name: up_setup
@@ -946,29 +965,52 @@ static int up_setup(struct uart_dev_s *dev)
stm32_configgpio(priv->rts_gpio);
}
+#if HAVE_RS485
+ if (priv->rs485_dir_gpio != 0)
+ {
+ stm32_configgpio(priv->rs485_dir_gpio);
+ stm32_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity);
+ }
+#endif
+
/* Configure CR2 */
- /* Clear CLKEN, CPOL, CPHA, LBCL, and interrupt enable bits */
+ /* Clear STOP, CLKEN, CPOL, CPHA, LBCL, and interrupt enable bits */
regval = up_serialin(priv, STM32_USART_CR2_OFFSET);
- regval &= ~(USART_CR2_CLKEN|USART_CR2_CPOL|
+ regval &= ~(USART_CR2_STOP_MASK|USART_CR2_CLKEN|USART_CR2_CPOL|
USART_CR2_CPHA|USART_CR2_LBCL|USART_CR2_LBDIE);
+ /* Configure STOP bits */
+
+ if (priv->stopbits2)
+ {
+ regval |= USART_CR2_STOP2;
+ }
up_serialout(priv, STM32_USART_CR2_OFFSET, regval);
/* Configure CR1 */
- /* Clear M, TE, REm and all interrupt enable bits */
+ /* Clear M, PCE, PS, TE, REm and all interrupt enable bits */
regval = up_serialin(priv, STM32_USART_CR1_OFFSET);
- regval &= ~(USART_CR1_M|USART_CR1_TE|
+ regval &= ~(USART_CR1_M|USART_CR1_PCE|USART_CR1_PS|USART_CR1_TE|
USART_CR1_RE|USART_CR1_ALLINTS);
- /* Configure word length */
+ /* Configure word length and parity mode */
if (priv->bits == 9) /* Default: 1 start, 8 data, n stop */
{
regval |= USART_CR1_M; /* 1 start, 9 data, n stop */
}
+ if (priv->parity == 1) /* Odd parity */
+ {
+ regval |= (USART_CR1_PCE|USART_CR1_PS);
+ }
+ else if (priv->parity == 2) /* Even parity */
+ {
+ regval |= USART_CR1_PCE;
+ }
+
up_serialout(priv, STM32_USART_CR1_OFFSET, regval);
/* Configure CR3 */
@@ -981,22 +1023,20 @@ static int up_setup(struct uart_dev_s *dev)
up_serialout(priv, STM32_USART_CR3_OFFSET, regval);
- /* Configure the USART line format and speed. */
+ /* Configure the USART Baud Rate. */
- up_set_format(dev);
+ up_setspeed(dev);
/* Enable Rx, Tx, and the USART */
regval = up_serialin(priv, STM32_USART_CR1_OFFSET);
regval |= (USART_CR1_UE|USART_CR1_TE|USART_CR1_RE);
up_serialout(priv, STM32_USART_CR1_OFFSET, regval);
-
-#endif /* CONFIG_SUPPRESS_UART_CONFIG */
+#endif
/* Set up the cached interrupt enables value */
- up_restoreusartint(priv, 0);
-
+ priv->ie = 0;
return OK;
}
@@ -1016,15 +1056,12 @@ static int up_dma_setup(struct uart_dev_s *dev)
int result;
uint32_t regval;
- /* Do the basic UART setup first, unless we are the console */
+ /* Do the basic UART setup first */
- if (!dev->isconsole)
- {
- result = up_setup(dev);
- if (result != OK)
- {
- return result;
- }
+ result = up_setup(dev);
+ if (result != OK)
+ {
+ return result;
}
/* Acquire the DMA channel. This should always succeed. */
@@ -1217,7 +1254,7 @@ static int up_interrupt_common(struct up_dev_s *priv)
* USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used)
* USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read
* " " USART_SR_ORE Overrun Error Detected
- * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used)
+ * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (used only for RS-485)
* USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty
* USART_CR1_PEIE 8 USART_SR_PE Parity Error
*
@@ -1232,6 +1269,21 @@ static int up_interrupt_common(struct up_dev_s *priv)
* being used.
*/
+#ifdef HAVE_RS485
+ /* Transmission of whole buffer is over - TC is set, TXEIE is cleared.
+ * Note - this should be first, to have the most recent TC bit value from
+ * SR register - sending data affects TC, but without refresh we will not
+ * know that...
+ */
+
+ if ((priv->sr & USART_SR_TC) != 0 && (priv->ie & USART_CR1_TCIE) != 0 &&
+ (priv->ie & USART_CR1_TXEIE) == 0)
+ {
+ stm32_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity);
+ up_restoreusartint(priv, priv->ie & ~USART_CR1_TCIE);
+ }
+#endif
+
/* Handle incoming, receive bytes. */
if ((priv->sr & USART_SR_RXNE) != 0 && (priv->ie & USART_CR1_RXNEIE) != 0)
@@ -1265,13 +1317,14 @@ static int up_interrupt_common(struct up_dev_s *priv)
if ((priv->sr & USART_SR_TXE) != 0 && (priv->ie & USART_CR1_TXEIE) != 0)
{
- /* Transmit data regiser empty ... process outgoing bytes */
+ /* Transmit data register empty ... process outgoing bytes */
uart_xmitchars(&priv->dev);
handled = true;
}
}
- return OK;
+
+ return OK;
}
/****************************************************************************
@@ -1318,21 +1371,12 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
break;
}
- cfsetispeed(termiosp, priv->baud);
-
- /* Note that since we only support 8/9 bit modes and
- * there is no way to report 9-bit mode, we always claim 8.
+ /* TODO: Other termios fields are not yet returned.
+ * Note that only cfsetospeed is not necessary because we have
+ * knowledge that only one speed is supported.
*/
- termiosp->c_cflag =
- ((priv->parity != 0) ? PARENB : 0) |
- ((priv->parity == 1) ? PARODD : 0) |
- ((priv->stopbits2) ? CSTOPB : 0) |
- ((priv->oflow) ? CCTS_OFLOW : 0) |
- ((priv->iflow) ? CRTS_IFLOW : 0) |
- CS8;
-
- /* TODO: CCTS_IFLOW, CCTS_OFLOW */
+ cfsetispeed(termiosp, priv->baud);
}
break;
@@ -1346,48 +1390,16 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
break;
}
- /* Perform some sanity checks before accepting any changes */
-
- if (((termiosp->c_cflag & CSIZE) != CS8) ||
- ((termiosp->c_cflag & CCTS_OFLOW) && (priv->cts_gpio == 0)) ||
- ((termiosp->c_cflag & CRTS_IFLOW) && (priv->rts_gpio == 0)))
- {
- ret = -EINVAL;
- break;
- }
-
- if (termiosp->c_cflag & PARENB)
- {
- priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2;
- }
- else
- {
- priv->parity = 0;
- }
-
- priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0;
- priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
- priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
-
- /* Note that since there is no way to request 9-bit mode
- * and no way to support 5/6/7-bit modes, we ignore them
- * all here.
- */
-
- /* Note that only cfgetispeed is used because we have knowledge
+ /* TODO: Handle other termios settings.
+ * Note that only cfgetispeed is used besued we have knowledge
* that only one speed is supported.
*/
priv->baud = cfgetispeed(termiosp);
-
- /* effect the changes immediately - note that we do not implement
- * TCSADRAIN / TCSAFLUSH
- */
-
- up_set_format(dev);
+ up_setspeed(dev);
}
break;
-#endif /* CONFIG_SERIAL_TERMIOS */
+#endif
#ifdef CONFIG_USART_BREAKS
case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
@@ -1611,6 +1623,10 @@ static bool up_dma_rxavailable(struct uart_dev_s *dev)
static void up_send(struct uart_dev_s *dev, int ch)
{
struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+#ifdef HAVE_RS485
+ if (priv->rs485_dir_gpio != 0)
+ stm32_gpiowrite(priv->rs485_dir_gpio, priv->rs485_dir_polarity);
+#endif
up_serialout(priv, STM32_USART_DR_OFFSET, (uint32_t)ch);
}
@@ -1631,7 +1647,7 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
*
* Enable Bit Status Meaning Usage
* ------------------ --- --------------- ---------------------------- ----------
- * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used)
+ * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (used only for RS-485)
* USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty
* USART_CR3_CTSIE 10 USART_SR_CTS CTS flag (not used)
*/
@@ -1642,7 +1658,20 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
/* Set to receive an interrupt when the TX data register is empty */
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
- up_restoreusartint(priv, priv->ie | USART_CR1_TXEIE);
+ uint16_t ie = priv->ie | USART_CR1_TXEIE;
+
+ /* If RS-485 is supported on this U[S]ART, then also enable the
+ * transmission complete interrupt.
+ */
+
+# ifdef HAVE_RS485
+ if (priv->rs485_dir_gpio != 0)
+ {
+ ie |= USART_CR1_TCIE;
+ }
+# endif
+
+ up_restoreusartint(priv, ie);
/* Fake a TX interrupt here by just calling uart_xmitchars() with
* interrupts disabled (note this may recurse).
@@ -1657,6 +1686,7 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
up_restoreusartint(priv, priv->ie & ~USART_CR1_TXEIE);
}
+
irqrestore(flags);
}