This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch releases/13.1
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 39f3447bbde17328662f11692acf75273f6e4679
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Oct 11 20:14:13 2026 +0200

    drivers/serial/uart_pl011.c: Send the TX buffer with interrupts disabled.
    
    pl011_txint() enabled the TX interrupt and then called uart_xmitchars()
    with interrupts enabled.  uart_write() calls it from a task, so the TX
    interrupt could run uart_xmitchars() in the middle of that call.  Both
    moved xmit.tail, the tail passed the head, and the driver sent the
    whole TX buffer again: on the console, a program that echoed each key
    printed the last 256 bytes of output again with each key.
    
    Call uart_xmitchars() in a critical section, as uart_16550.c does.  The
    spinlock still covers only the register access.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 drivers/serial/uart_pl011.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/serial/uart_pl011.c b/drivers/serial/uart_pl011.c
index f89ad19c9fc..4583343a075 100644
--- a/drivers/serial/uart_pl011.c
+++ b/drivers/serial/uart_pl011.c
@@ -743,17 +743,24 @@ static void pl011_txint(FAR struct uart_dev_s *dev, bool 
enable)
   FAR struct pl011_uart_port_s *sport = dev->priv;
   irqstate_t flags;
 
-  flags = spin_lock_irqsave(&sport->lock);
-
   if (enable)
     {
+      /* Fake a TX interrupt with interrupts disabled, so that the TX
+       * interrupt cannot run uart_xmitchars() during this call.
+       */
+
+      flags = enter_critical_section();
+
+      spin_lock(&sport->lock);
       pl011_irq_tx_enable(sport);
-      spin_unlock_irqrestore(&sport->lock, flags);
+      spin_unlock(&sport->lock);
 
       uart_xmitchars(dev);
+      leave_critical_section(flags);
     }
   else
     {
+      flags = spin_lock_irqsave(&sport->lock);
       pl011_irq_tx_disable(sport);
       spin_unlock_irqrestore(&sport->lock, flags);
     }

Reply via email to