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) */

Reply via email to