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 b8321d16d09ae5cc1e7cedc3c16ca29be5e18f04 Author: Brijesh Thakkar <[email protected]> AuthorDate: Tue Oct 20 18:15:41 2026 +0530 drivers/serial/uart_16550: Allow UARTs without an interrupt A negative priv->irq now means that the UART has no interrupt. In that case the default attach and detach do not touch the interrupt controller, and txint() sends the buffered data by polling, like it already does with CONFIG_16550_POLLING. This lets a board use a UART whose interrupt is unreliable or not available and poll it instead. Ports with a non-negative irq, which is every port configured by Kconfig, behave as before. Assisted-by: Claude:claude-sonnet-5-5 Signed-off-by: Brijesh Thakkar <[email protected]> --- drivers/serial/uart_16550.c | 38 ++++++++++++++++++++++++-------------- include/nuttx/serial/uart_16550.h | 2 +- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/serial/uart_16550.c b/drivers/serial/uart_16550.c index 81309a84117..ea2000a760d 100644 --- a/drivers/serial/uart_16550.c +++ b/drivers/serial/uart_16550.c @@ -987,6 +987,12 @@ static int u16550_attach(struct uart_dev_s *dev) { ret = priv->ops->attach(priv, dev); } + else if (priv->irq < 0) + { + /* No interrupt: the board polls the UART */ + + ret = OK; + } else { ret = irq_attach(priv->irq, priv->ops->isr, dev); @@ -1037,7 +1043,7 @@ static void u16550_detach(FAR struct uart_dev_s *dev) { priv->ops->detach(priv, dev); } - else + else if (priv->irq >= 0) { up_disable_irq(priv->irq); irqchain_detach(priv->irq, priv->ops->isr, dev); @@ -1636,7 +1642,23 @@ static void u16550_txint(struct uart_dev_s *dev, bool enable) if (enable) { -#ifdef CONFIG_16550_POLLING +#ifndef CONFIG_16550_POLLING + if (priv->irq >= 0) + { + flags = enter_critical_section(); + priv->ier |= UART_IER_ETBEI; + u16550_serialout(priv, UART_IER_OFFSET, priv->ier); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); + leave_critical_section(flags); + return; + } +#endif + /* In polling mode, we loop until the buffer is empty */ while (dev->xmit.head != dev->xmit.tail) @@ -1647,18 +1669,6 @@ static void u16550_txint(struct uart_dev_s *dev, bool enable) uart_xmitchars(dev); } -#else - flags = enter_critical_section(); - priv->ier |= UART_IER_ETBEI; - u16550_serialout(priv, UART_IER_OFFSET, priv->ier); - - /* Fake a TX interrupt here by just calling uart_xmitchars() with - * interrupts disabled (note this may recurse). - */ - - uart_xmitchars(dev); - leave_critical_section(flags); -#endif } else { diff --git a/include/nuttx/serial/uart_16550.h b/include/nuttx/serial/uart_16550.h index 6367e694113..b58f8e6a8fd 100644 --- a/include/nuttx/serial/uart_16550.h +++ b/include/nuttx/serial/uart_16550.h @@ -376,7 +376,7 @@ struct u16550_s FAR struct clk_s *mclk; /* UART clock descriptor */ #endif uart_datawidth_t ier; /* Saved IER value */ - int irq; /* IRQ associated with this UART */ + int irq; /* IRQ associated with this UART, <0: none (polled) */ #ifndef CONFIG_16550_SUPRESS_CONFIG uint8_t parity; /* 0=none, 1=odd, 2=even */ uint8_t bits; /* Number of bits (7 or 8) */
