This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 45c38d8592bc8efd2ed2a661e204920dc4119811 Author: yinshengkai <[email protected]> AuthorDate: Thu Feb 26 16:33:12 2026 +0800 drivers/serial/16550: add polling mode support for serial drivers Adds CONFIG_16550_POLLING options to enable polling mode for transmission. This avoids TX interrupts and reduces interrupt latency at the cost of blocking during TX. Implements sendbuf() method for efficient buffer transmission in polling mode. Signed-off-by: yinshengkai <[email protected]> Signed-off-by: chao an <[email protected]> --- drivers/serial/Kconfig-16550 | 8 ++++++++ drivers/serial/uart_16550.c | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/serial/Kconfig-16550 b/drivers/serial/Kconfig-16550 index 183e9618170..dea015830b1 100644 --- a/drivers/serial/Kconfig-16550 +++ b/drivers/serial/Kconfig-16550 @@ -5,6 +5,14 @@ if 16550_UART +config 16550_POLLING + bool "Force polling mode for TX" + default n + ---help--- + Force using polling mode for transmission. This avoids using TX interrupts + and potentially reduces interrupt latency, at the cost of blocking execution + during transmission. + config 16550_SERIAL_DISABLE_REORDERING bool "Disable reordering of ttySx devices." default n diff --git a/drivers/serial/uart_16550.c b/drivers/serial/uart_16550.c index c7ad45f3f67..fd4557dbbcc 100644 --- a/drivers/serial/uart_16550.c +++ b/drivers/serial/uart_16550.c @@ -108,6 +108,8 @@ static void u16550_dmarxfree(FAR struct uart_dev_s *dev); static void u16550_dmarxconfig(FAR struct uart_dev_s *dev); #endif static void u16550_send(FAR struct uart_dev_s *dev, int ch); +static ssize_t u16550_sendbuf(struct uart_dev_s *dev, + const void *buffer, size_t size); static void u16550_txint(FAR struct uart_dev_s *dev, bool enable); static bool u16550_txready(FAR struct uart_dev_s *dev); static bool u16550_txempty(FAR struct uart_dev_s *dev); @@ -154,6 +156,7 @@ static const struct uart_ops_s g_uart_ops = .txint = u16550_txint, .txready = u16550_txready, .txempty = u16550_txempty, + .sendbuf = u16550_sendbuf, }; /* I/O buffers */ @@ -1568,6 +1571,26 @@ static void u16550_send(struct uart_dev_s *dev, int ch) u16550_serialout(priv, UART_THR_OFFSET, (uart_datawidth_t)ch); } +/**************************************************************************** + * Name: u16550_sendbuf + * + * Description: + * This method will send a buffer of bytes on the UART + * + ****************************************************************************/ + +static ssize_t u16550_sendbuf(struct uart_dev_s *dev, + const void *buffer, size_t size) +{ + for (size_t i = 0; i < size; i++) + { + while (!u16550_txready(dev)); + u16550_send(dev, ((const unsigned char *)buffer)[i]); + } + + return (ssize_t)size; +} + /**************************************************************************** * Name: u16550_txint * @@ -1588,9 +1611,14 @@ static void u16550_txint(struct uart_dev_s *dev, bool enable) } #endif - flags = enter_critical_section(); if (enable) { +#ifdef CONFIG_16550_POLLING + /* In polling mode, we loop until the buffer is empty */ + + uart_xmitchars(dev); +#else + flags = enter_critical_section(); priv->ier |= UART_IER_ETBEI; u16550_serialout(priv, UART_IER_OFFSET, priv->ier); @@ -1599,14 +1627,16 @@ static void u16550_txint(struct uart_dev_s *dev, bool enable) */ uart_xmitchars(dev); + leave_critical_section(flags); +#endif } else { + flags = enter_critical_section(); priv->ier &= ~UART_IER_ETBEI; u16550_serialout(priv, UART_IER_OFFSET, priv->ier); + leave_critical_section(flags); } - - leave_critical_section(flags); } /****************************************************************************
