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

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


The following commit(s) were added to refs/heads/master by this push:
     new 2b1b82c73b7 arch/arm/src/stm32n6: disable the USART while changing the 
line format
2b1b82c73b7 is described below

commit 2b1b82c73b742634220df0e60dceff83197d641f
Author: Swatantra Yadav <[email protected]>
AuthorDate: Mon Nov 2 19:25:20 2026 +0530

    arch/arm/src/stm32n6: disable the USART while changing the line format
    
    stm32serial_setformat() writes BRR, CR2 STOP bits, and the PCE, PS,
    and M0/M1 bits of CR1 with the USART enabled. They can only be written
    while UE = 0 per the ST Reference Manual (RM0486), so a run-time
    tcsetattr() that changes baud rate, parity, or word length returned
    success but left the hardware USART registers unchanged.
    
    Clear UE around the update and restore it inside a critical section,
    matching the approved STM32L4 (commit 47180bf5ea), STM32WB (PR #21334),
    STM32WL5 (PR #21336), STM32H7, and F7 implementations.
    
    Also fix pre-existing nxstyle alignment, declaration, and brace issues
    in stm32serial_pm_setsuspend, stm32serial_setapbclock, stm32serial_detach,
    stm32serial_interrupt, stm32serial_ioctl, and stm32serial_pmprepare.
    
    Fixes #21377
    
    Signed-off-by: Swatantra Yadav <[email protected]>
    Assisted-by: Google Gemini
---
 arch/arm/src/stm32n6/stm32_serial.c | 272 ++++++++++++++++++++----------------
 1 file changed, 148 insertions(+), 124 deletions(-)

diff --git a/arch/arm/src/stm32n6/stm32_serial.c 
b/arch/arm/src/stm32n6/stm32_serial.c
index df0dcd199b0..783c613abb4 100644
--- a/arch/arm/src/stm32n6/stm32_serial.c
+++ b/arch/arm/src/stm32n6/stm32_serial.c
@@ -435,9 +435,22 @@ static void stm32serial_setformat(struct uart_dev_s *dev)
   struct stm32_serial_s *priv =
     (struct stm32_serial_s *)dev->priv;
   uint32_t regval;
+  uint32_t cr1_ue;
   uint32_t brr;
   uint32_t cr1;
   uint32_t usartdiv8;
+  irqstate_t flags;
+
+  flags = enter_critical_section();
+
+  /* Disable UE: the baud rate, parity and word length bits can not be
+   * written while UE = 1.
+   */
+
+  regval = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET);
+  cr1_ue = regval & USART_CR1_UE;
+  stm32serial_putreg(priv, STM32_USART_CR1_OFFSET,
+                     regval & ~USART_CR1_UE);
 
   /* In case of oversampling by 8, the equation is:
    *
@@ -557,6 +570,13 @@ static void stm32serial_setformat(struct uart_dev_s *dev)
 #endif
 
   stm32serial_putreg(priv, STM32_USART_CR3_OFFSET, regval);
+
+  /* Restore UE */
+
+  regval = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET);
+  stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, regval | cr1_ue);
+
+  leave_critical_section(flags);
 }
 #endif /* CONFIG_SUPPRESS_UART_CONFIG */
 
@@ -635,7 +655,9 @@ static void stm32serial_pm_setsuspend(bool suspend)
   /* Already in desired state? */
 
   if (suspend == g_serialpm.serial_suspended)
-    return;
+    {
+      return;
+    }
 
   g_serialpm.serial_suspended = suspend;
 
@@ -677,14 +699,14 @@ static void stm32serial_setapbclock(struct uart_dev_s 
*dev, bool on)
 
   switch (priv->usartbase)
     {
-    default:
-      return;
+      default:
+        return;
 #ifdef CONFIG_STM32_USART1_SERIALDRIVER
-    case STM32_USART1_BASE:
-      rcc_en = RCC_APB2ENR_USART1EN;
-      regaddr_set = STM32_RCC_APB2ENSR;
-      regaddr_clr = STM32_RCC_APB2ENCR;
-      break;
+      case STM32_USART1_BASE:
+        rcc_en = RCC_APB2ENR_USART1EN;
+        regaddr_set = STM32_RCC_APB2ENSR;
+        regaddr_clr = STM32_RCC_APB2ENCR;
+        break;
 #endif
     }
 
@@ -942,6 +964,7 @@ static void stm32serial_detach(struct uart_dev_s *dev)
 {
   struct stm32_serial_s *priv =
     (struct stm32_serial_s *)dev->priv;
+
   up_disable_irq(priv->irq);
   irq_detach(priv->irq);
 }
@@ -961,8 +984,9 @@ static void stm32serial_detach(struct uart_dev_s *dev)
 static int stm32serial_interrupt(int irq, void *context, void *arg)
 {
   struct stm32_serial_s *priv = (struct stm32_serial_s *)arg;
-  int  passes;
+  int passes;
   bool handled;
+
   DEBUGASSERT(priv != NULL);
 
   /* Report serial activity to the power management logic */
@@ -1076,120 +1100,120 @@ static int stm32serial_ioctl(struct file *filep, int 
cmd,
   switch (cmd)
     {
 #ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
-    case TIOCSERGSTRUCT:
-      {
-        struct stm32_serial_s *user;
+      case TIOCSERGSTRUCT:
+        {
+          struct stm32_serial_s *user;
 
-        user = (struct stm32_serial_s *)arg;
+          user = (struct stm32_serial_s *)arg;
 
-        if (!user)
-          {
-            ret = -EINVAL;
-          }
-        else
-          {
-            memcpy(user, dev, sizeof(struct stm32_serial_s));
-          }
-      }
-      break;
+          if (!user)
+            {
+              ret = -EINVAL;
+            }
+          else
+            {
+              memcpy(user, dev, sizeof(struct stm32_serial_s));
+            }
+        }
+        break;
 #endif
 
 #ifdef CONFIG_SERIAL_TERMIOS
-    case TCGETS:
-      {
-        struct termios *termiosp = (struct termios *)arg;
+      case TCGETS:
+        {
+          struct termios *termiosp = (struct termios *)arg;
 
-        if (!termiosp)
-          {
-            ret = -EINVAL;
-            break;
-          }
+          if (!termiosp)
+            {
+              ret = -EINVAL;
+              break;
+            }
 
-        cfsetispeed(termiosp, priv->baud);
+          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.
-         */
+          /* Note that since we only support 8/9 bit modes and
+           * there is no way to report 9-bit mode, we always claim 8.
+           */
 
-        termiosp->c_cflag =
-          ((priv->parity != 0) ? PARENB : 0) |
-          ((priv->parity == 1) ? PARODD : 0) |
-          ((priv->stopbits2) ? CSTOPB : 0) |
+          termiosp->c_cflag =
+            ((priv->parity != 0) ? PARENB : 0) |
+            ((priv->parity == 1) ? PARODD : 0) |
+            ((priv->stopbits2) ? CSTOPB : 0) |
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
-          ((priv->oflow) ? CCTS_OFLOW : 0) |
+            ((priv->oflow) ? CCTS_OFLOW : 0) |
 #endif
 #ifdef CONFIG_SERIAL_IFLOWCONTROL
-          ((priv->iflow) ? CRTS_IFLOW : 0) |
+            ((priv->iflow) ? CRTS_IFLOW : 0) |
 #endif
-          CS8;
-      }
-      break;
+            CS8;
+        }
+        break;
 
-    case TCSETS:
-      {
-        struct termios *termiosp = (struct termios *)arg;
+      case TCSETS:
+        {
+          struct termios *termiosp = (struct termios *)arg;
 
-        if (!termiosp)
-          {
-            ret = -EINVAL;
-            break;
-          }
+          if (!termiosp)
+            {
+              ret = -EINVAL;
+              break;
+            }
 
-        /* Perform some sanity checks before accepting any changes */
+          /* Perform some sanity checks before accepting any changes */
 
-        if (((termiosp->c_cflag & CSIZE) != CS8)
+          if (((termiosp->c_cflag & CSIZE) != CS8)
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
-            || ((termiosp->c_cflag & CCTS_OFLOW) && (priv->cts_gpio == 0))
+              || ((termiosp->c_cflag & CCTS_OFLOW) && (priv->cts_gpio == 0))
 #endif
 #ifdef CONFIG_SERIAL_IFLOWCONTROL
-            || ((termiosp->c_cflag & CRTS_IFLOW) && (priv->rts_gpio == 0))
+              || ((termiosp->c_cflag & CRTS_IFLOW) && (priv->rts_gpio == 0))
 #endif
-           )
-          {
-            ret = -EINVAL;
-            break;
-          }
+             )
+            {
+              ret = -EINVAL;
+              break;
+            }
 
-        if (termiosp->c_cflag & PARENB)
-          {
-            priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2;
-          }
-        else
-          {
-            priv->parity = 0;
-          }
+          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->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0;
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
-        priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
+          priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
 #endif
 #ifdef CONFIG_SERIAL_IFLOWCONTROL
-        priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
+          priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
 #endif
 
-        /* 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 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
-         * that only one speed is supported.
-         */
+          /* Note that only cfgetispeed is used because we have knowledge
+           * that only one speed is supported.
+           */
 
-        priv->baud = cfgetispeed(termiosp);
+          priv->baud = cfgetispeed(termiosp);
 
-        /* Effect the changes immediately - note that we do not implement
-         * TCSADRAIN / TCSAFLUSH
-         */
+          /* Effect the changes immediately - note that we do not implement
+           * TCSADRAIN / TCSAFLUSH
+           */
 
-        stm32serial_setformat(dev);
-      }
-      break;
+          stm32serial_setformat(dev);
+        }
+        break;
 #endif /* CONFIG_SERIAL_TERMIOS */
 
-    default:
-      ret = -ENOTTY;
-      break;
+      default:
+        ret = -ENOTTY;
+        break;
     }
 
   return ret;
@@ -1547,54 +1571,54 @@ static int stm32serial_pmprepare(struct pm_callback_s 
*cb, int domain,
 
   switch (pmstate)
     {
-    case PM_NORMAL:
-    case PM_IDLE:
-      break;
+      case PM_NORMAL:
+      case PM_IDLE:
+        break;
 
-    case PM_STANDBY:
-    case PM_SLEEP:
+      case PM_STANDBY:
+      case PM_SLEEP:
 
-      /* Check if any of the active ports have data pending on Tx/Rx
-       * buffers.
-       */
+        /* Check if any of the active ports have data pending on Tx/Rx
+         * buffers.
+         */
 
-      for (n = 0; n < STM32_NUSART; n++)
-        {
-          struct stm32_serial_s *priv = g_uart_devs[n];
+        for (n = 0; n < STM32_NUSART; n++)
+          {
+            struct stm32_serial_s *priv = g_uart_devs[n];
 
-          if (!priv || !priv->initialized)
-            {
-              /* Not active, skip. */
+            if (!priv || !priv->initialized)
+              {
+                /* Not active, skip. */
 
-              continue;
-            }
+                continue;
+              }
 
-          if (priv->suspended)
-            {
-              /* Port already suspended, skip. */
+            if (priv->suspended)
+              {
+                /* Port already suspended, skip. */
 
-              continue;
-            }
+                continue;
+              }
 
-          /* Check if port has data pending (Rx & Tx). */
+            /* Check if port has data pending (Rx & Tx). */
 
-          if (priv->dev.xmit.head != priv->dev.xmit.tail)
-            {
-              return ERROR;
-            }
+            if (priv->dev.xmit.head != priv->dev.xmit.tail)
+              {
+                return ERROR;
+              }
 
-          if (priv->dev.recv.head != priv->dev.recv.tail)
-            {
-              return ERROR;
-            }
-        }
-      break;
+            if (priv->dev.recv.head != priv->dev.recv.tail)
+              {
+                return ERROR;
+              }
+          }
+        break;
 
-    default:
+      default:
 
-      /* Should not get here */
+        /* Should not get here */
 
-      break;
+        break;
     }
 
   return OK;

Reply via email to