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

linguini1 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 d32fdfa20b4 arch/arm/stm32: Support optional TX/RX UART GPIOs.
d32fdfa20b4 is described below

commit d32fdfa20b425b08ff5359a9524192f9cc785c4a
Author: alexcekay <[email protected]>
AuthorDate: Wed May 27 11:03:05 2026 +0200

    arch/arm/stm32: Support optional TX/RX UART GPIOs.
    
    The STM32 serial drivers already treat 0 as not present for optional
    GPIO fields (CTS, RTS), guarding each call site with a != 0 check.
    
    TX and RX GPIO fields lacked this guard, so boards that
    define GPIO_UARTx_TX or GPIO_UARTx_RX as 0 (pin not routed) caused
    stm32_configgpio(0) to be called, which silently configures PA0 as a
    floating input, corrupting any other peripheral using that pin.
    
    Having an optional TX/RX UART is useful for several cases:
    * RX-only connections: e.g. radio control input on flight-controllers where 
no TX is wired.
    * Single-wire (half-duplex) connections: e.g. ESC telemetry connections.
    * Output-only NSH which prints output but does not allow entering inputs.
    
    Without a sentinel value for these cases one must assign the unused GPIO to
    a NC pin, which is misleading when reading board configuration files.
    
    Add != 0 guards for tx_gpio and rx_gpio across all STM32 serial driver
    families.
    
    Using 0 as the sentinel is safe for TX/RX because any valid UART config 
requires
    GPIO_ALT bits set in the config word, so 0 can never represent a real
    TX or RX pin configuration.
    
    Signed-off-by: alexcekay <[email protected]>
---
 arch/arm/src/stm32/stm32_serial.c       | 74 ++++++++++++++++++++++++---------
 arch/arm/src/stm32f7/stm32_serial.c     | 56 ++++++++++++++++++-------
 arch/arm/src/stm32h5/stm32_serial.c     | 49 +++++++++++++++-------
 arch/arm/src/stm32h7/stm32_serial.c     | 56 ++++++++++++++++++-------
 arch/arm/src/stm32l4/stm32l4_serial.c   | 55 +++++++++++++++++-------
 arch/arm/src/stm32l5/stm32l5_serial.c   | 56 ++++++++++++++++++-------
 arch/arm/src/stm32n6/stm32_serial.c     | 15 +++++--
 arch/arm/src/stm32u5/stm32_serial.c     | 56 ++++++++++++++++++-------
 arch/arm/src/stm32wb/stm32wb_serial.c   | 55 +++++++++++++++++-------
 arch/arm/src/stm32wl5/stm32wl5_serial.c | 56 ++++++++++++++++++-------
 10 files changed, 387 insertions(+), 141 deletions(-)

diff --git a/arch/arm/src/stm32/stm32_serial.c 
b/arch/arm/src/stm32/stm32_serial.c
index 9c30f1d5a81..09cbe58c2fc 100644
--- a/arch/arm/src/stm32/stm32_serial.c
+++ b/arch/arm/src/stm32/stm32_serial.c
@@ -1958,8 +1958,15 @@ static int up_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32_configgpio(priv->tx_gpio);
-  stm32_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -2185,8 +2192,15 @@ static void up_shutdown(struct uart_dev_s *dev)
    * then this may need to be a configuration option.
    */
 
-  stm32_unconfiggpio(priv->tx_gpio);
-  stm32_unconfiggpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_unconfiggpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_unconfiggpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -2543,14 +2557,22 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
 #if defined(CONFIG_STM32_STM32F10XX)
         if ((arg & SER_SINGLEWIRE_ENABLED) != 0)
           {
-            stm32_configgpio((priv->tx_gpio & ~(GPIO_CNF_MASK)) |
-                             GPIO_CNF_AFOD);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio & ~(GPIO_CNF_MASK)) |
+                                 GPIO_CNF_AFOD);
+              }
+
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32_configgpio((priv->tx_gpio & ~(GPIO_CNF_MASK)) |
-                             GPIO_CNF_AFPP);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio & ~(GPIO_CNF_MASK)) |
+                                 GPIO_CNF_AFPP);
+              }
+
             cr &= ~USART_CR3_HDSEL;
           }
 #else
@@ -2565,16 +2587,24 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
             gpio_val |= ((arg & SER_SINGLEWIRE_PULL_MASK) ==
                          SER_SINGLEWIRE_PULLDOWN) ? GPIO_PULLDOWN
                                                   : GPIO_FLOAT;
-            stm32_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
-                                                GPIO_OPENDRAIN)) |
-                             gpio_val);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
+                                                    GPIO_OPENDRAIN)) |
+                                 gpio_val);
+              }
+
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
-                                                GPIO_OPENDRAIN)) |
-                             GPIO_PUSHPULL);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
+                                                    GPIO_OPENDRAIN)) |
+                                 GPIO_PUSHPULL);
+              }
+
             cr &= ~USART_CR3_HDSEL;
           }
 #endif
@@ -2684,7 +2714,6 @@ static int up_ioctl(struct file *filep, int cmd, unsigned 
long arg)
     case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
       {
         irqstate_t flags;
-        uint32_t tx_break;
 
         flags = enter_critical_section();
 
@@ -2696,9 +2725,13 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
 
         /* Configure TX as a GPIO output pin and Send a break signal */
 
-        tx_break = GPIO_OUTPUT | (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) &
-                                  priv->tx_gpio);
-        stm32_configgpio(tx_break);
+        if (priv->tx_gpio != 0)
+          {
+            uint32_t tx_break = GPIO_OUTPUT |
+                    (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) &
+                     priv->tx_gpio);
+            stm32_configgpio(tx_break);
+          }
 
         leave_critical_section(flags);
       }
@@ -2712,7 +2745,10 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
 
         /* Configure TX back to U(S)ART */
 
-        stm32_configgpio(priv->tx_gpio);
+        if (priv->tx_gpio != 0)
+          {
+            stm32_configgpio(priv->tx_gpio);
+          }
 
         priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
 
diff --git a/arch/arm/src/stm32f7/stm32_serial.c 
b/arch/arm/src/stm32f7/stm32_serial.c
index 3779335ad05..dd5a10c0ee0 100644
--- a/arch/arm/src/stm32f7/stm32_serial.c
+++ b/arch/arm/src/stm32f7/stm32_serial.c
@@ -1916,8 +1916,15 @@ static int up_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32_configgpio(priv->tx_gpio);
-  stm32_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -2129,8 +2136,15 @@ static void up_shutdown(struct uart_dev_s *dev)
    * then this may need to be a configuration option.
    */
 
-  stm32_unconfiggpio(priv->tx_gpio);
-  stm32_unconfiggpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_unconfiggpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_unconfiggpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -2454,15 +2468,24 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
             gpio_val |= (arg & SER_SINGLEWIRE_PULL_MASK) ==
                                SER_SINGLEWIRE_PULLDOWN ?
                                GPIO_PULLDOWN : GPIO_FLOAT;
-            stm32_configgpio((priv->tx_gpio &
-                            ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) | gpio_val);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio &
+                                  ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                  gpio_val);
+              }
+
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
-                                                GPIO_OPENDRAIN)) |
-                                                GPIO_PUSHPULL);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
+                                                    GPIO_OPENDRAIN)) |
+                                                    GPIO_PUSHPULL);
+              }
+
             cr &= ~USART_CR3_HDSEL;
           }
 
@@ -2669,7 +2692,6 @@ static int up_ioctl(struct file *filep, int cmd, unsigned 
long arg)
     case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
       {
         irqstate_t flags;
-        uint32_t tx_break;
 
         flags = enter_critical_section();
 
@@ -2681,9 +2703,12 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
 
         /* Configure TX as a GPIO output pin and Send a break signal */
 
-        tx_break = GPIO_OUTPUT |
-                   (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
-        stm32_configgpio(tx_break);
+        if (priv->tx_gpio != 0)
+          {
+            uint32_t tx_break = GPIO_OUTPUT |
+                    (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
+            stm32_configgpio(tx_break);
+          }
 
         leave_critical_section(flags);
       }
@@ -2697,7 +2722,10 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
 
         /* Configure TX back to U(S)ART */
 
-        stm32_configgpio(priv->tx_gpio);
+        if (priv->tx_gpio != 0)
+          {
+            stm32_configgpio(priv->tx_gpio);
+          }
 
         priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
 
diff --git a/arch/arm/src/stm32h5/stm32_serial.c 
b/arch/arm/src/stm32h5/stm32_serial.c
index f166a51b3e0..4d2e94ad577 100644
--- a/arch/arm/src/stm32h5/stm32_serial.c
+++ b/arch/arm/src/stm32h5/stm32_serial.c
@@ -2171,8 +2171,15 @@ static int stm32serial_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32_configgpio(priv->tx_gpio);
-  stm32_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -2434,12 +2441,12 @@ static void stm32serial_shutdown(struct uart_dev_s *dev)
    * then this may need to be a configuration option.
    */
 
-  if (priv->unconfigure & USART_UNCONFIGURE_TX)
+  if ((priv->unconfigure & USART_UNCONFIGURE_TX) && (priv->tx_gpio != 0))
     {
       stm32_unconfiggpio(priv->tx_gpio);
     }
 
-  if (priv->unconfigure & USART_UNCONFIGURE_RX)
+  if ((priv->unconfigure & USART_UNCONFIGURE_RX) && (priv->rx_gpio != 0))
     {
       stm32_unconfiggpio(priv->rx_gpio);
     }
@@ -2874,17 +2881,24 @@ static int stm32serial_ioctl(struct file *filep, int 
cmd,
                 gpio_val |= GPIO_FLOAT;
               }
 
-            stm32_configgpio((priv->tx_gpio &
-                                ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
-                               gpio_val);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio &
+                                  ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                  gpio_val);
+              }
 
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32_configgpio((priv->tx_gpio &
-                                ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
-                               GPIO_PUSHPULL);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio &
+                                  ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                  GPIO_PUSHPULL);
+              }
+
             cr &= ~USART_CR3_HDSEL;
           }
 
@@ -3091,7 +3105,6 @@ static int stm32serial_ioctl(struct file *filep, int cmd,
     case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
       {
         irqstate_t flags;
-        uint32_t tx_break;
 
         flags = enter_critical_section();
 
@@ -3103,9 +3116,12 @@ static int stm32serial_ioctl(struct file *filep, int cmd,
 
         /* Configure TX as a GPIO output pin and Send a break signal */
 
-        tx_break = GPIO_OUTPUT |
-                   (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
-        stm32_configgpio(tx_break);
+        if (priv->tx_gpio != 0)
+          {
+            uint32_t tx_break = GPIO_OUTPUT |
+                    (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
+            stm32_configgpio(tx_break);
+          }
 
         leave_critical_section(flags);
       }
@@ -3119,7 +3135,10 @@ static int stm32serial_ioctl(struct file *filep, int cmd,
 
         /* Configure TX back to U(S)ART */
 
-        stm32_configgpio(priv->tx_gpio);
+        if (priv->tx_gpio != 0)
+          {
+            stm32_configgpio(priv->tx_gpio);
+          }
 
         priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
 
diff --git a/arch/arm/src/stm32h7/stm32_serial.c 
b/arch/arm/src/stm32h7/stm32_serial.c
index 5d2b54f0d48..7860667a245 100644
--- a/arch/arm/src/stm32h7/stm32_serial.c
+++ b/arch/arm/src/stm32h7/stm32_serial.c
@@ -2082,8 +2082,15 @@ static int up_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32_configgpio(priv->tx_gpio);
-  stm32_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -2314,8 +2321,15 @@ static void up_shutdown(struct uart_dev_s *dev)
    *  If not, then this may need to be a configuration option.
    */
 
-  stm32_unconfiggpio(priv->tx_gpio);
-  stm32_unconfiggpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_unconfiggpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_unconfiggpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -2644,15 +2658,24 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
             gpio_val |= (arg & SER_SINGLEWIRE_PULL_MASK) ==
                          SER_SINGLEWIRE_PULLDOWN ?
                          GPIO_PULLDOWN : GPIO_FLOAT;
-            stm32_configgpio((priv->tx_gpio &
-                            ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) | gpio_val);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio &
+                                  ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                  gpio_val);
+              }
+
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32_configgpio((priv->tx_gpio &
-                            ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
-                              GPIO_PUSHPULL);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio &
+                                  ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                  GPIO_PUSHPULL);
+              }
+
             cr &= ~USART_CR3_HDSEL;
           }
 
@@ -2859,7 +2882,6 @@ static int up_ioctl(struct file *filep, int cmd, unsigned 
long arg)
     case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
       {
         irqstate_t flags;
-        uint32_t tx_break;
 
         flags = enter_critical_section();
 
@@ -2871,9 +2893,12 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
 
         /* Configure TX as a GPIO output pin and Send a break signal */
 
-        tx_break = GPIO_OUTPUT |
-                (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
-        stm32_configgpio(tx_break);
+        if (priv->tx_gpio != 0)
+          {
+            uint32_t tx_break = GPIO_OUTPUT |
+                    (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
+            stm32_configgpio(tx_break);
+          }
 
         leave_critical_section(flags);
       }
@@ -2887,7 +2912,10 @@ static int up_ioctl(struct file *filep, int cmd, 
unsigned long arg)
 
         /* Configure TX back to U(S)ART */
 
-        stm32_configgpio(priv->tx_gpio);
+        if (priv->tx_gpio != 0)
+          {
+            stm32_configgpio(priv->tx_gpio);
+          }
 
         priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
 
diff --git a/arch/arm/src/stm32l4/stm32l4_serial.c 
b/arch/arm/src/stm32l4/stm32l4_serial.c
index 1b611901861..bf78be0ddf8 100644
--- a/arch/arm/src/stm32l4/stm32l4_serial.c
+++ b/arch/arm/src/stm32l4/stm32l4_serial.c
@@ -1472,8 +1472,15 @@ static int stm32l4serial_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32l4_configgpio(priv->tx_gpio);
-  stm32l4_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32l4_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32l4_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -1698,8 +1705,15 @@ static void stm32l4serial_shutdown(struct uart_dev_s 
*dev)
    * then this may need to be a configuration option.
    */
 
-  stm32l4_unconfiggpio(priv->tx_gpio);
-  stm32l4_unconfiggpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32l4_unconfiggpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32l4_unconfiggpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -2015,17 +2029,23 @@ static int stm32l4serial_ioctl(struct file *filep, int 
cmd,
               (arg & SER_SINGLEWIRE_PULL_MASK) == SER_SINGLEWIRE_PULLDOWN ?
                                                   GPIO_PULLDOWN : GPIO_FLOAT;
 
-            stm32l4_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
-                                                  GPIO_OPENDRAIN)) |
-                                                  gpio_val);
+            if (priv->tx_gpio != 0)
+              {
+                stm32l4_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
+                                                      GPIO_OPENDRAIN)) |
+                                                      gpio_val);
+              }
 
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32l4_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
-                                                  GPIO_OPENDRAIN)) |
-                                                  GPIO_PUSHPULL);
+            if (priv->tx_gpio != 0)
+              {
+                stm32l4_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
+                                                      GPIO_OPENDRAIN)) |
+                                                      GPIO_PUSHPULL);
+              }
 
             cr &= ~USART_CR3_HDSEL;
           }
@@ -2233,7 +2253,6 @@ static int stm32l4serial_ioctl(struct file *filep, int 
cmd,
     case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
       {
         irqstate_t flags;
-        uint32_t tx_break;
 
         flags = enter_critical_section();
 
@@ -2245,9 +2264,12 @@ static int stm32l4serial_ioctl(struct file *filep, int 
cmd,
 
         /* Configure TX as a GPIO output pin and Send a break signal */
 
-        tx_break = GPIO_OUTPUT |
-                   (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
-        stm32l4_configgpio(tx_break);
+        if (priv->tx_gpio != 0)
+          {
+            uint32_t tx_break = GPIO_OUTPUT |
+                    (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
+            stm32l4_configgpio(tx_break);
+          }
 
         leave_critical_section(flags);
       }
@@ -2261,7 +2283,10 @@ static int stm32l4serial_ioctl(struct file *filep, int 
cmd,
 
         /* Configure TX back to U(S)ART */
 
-        stm32l4_configgpio(priv->tx_gpio);
+        if (priv->tx_gpio != 0)
+          {
+            stm32l4_configgpio(priv->tx_gpio);
+          }
 
         priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
 
diff --git a/arch/arm/src/stm32l5/stm32l5_serial.c 
b/arch/arm/src/stm32l5/stm32l5_serial.c
index 26bf1bc2b47..514c57477d5 100644
--- a/arch/arm/src/stm32l5/stm32l5_serial.c
+++ b/arch/arm/src/stm32l5/stm32l5_serial.c
@@ -1392,8 +1392,15 @@ static int stm32l5serial_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32l5_configgpio(priv->tx_gpio);
-  stm32l5_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32l5_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32l5_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -1618,8 +1625,15 @@ static void stm32l5serial_shutdown(struct uart_dev_s 
*dev)
    * then this may need to be a configuration option.
    */
 
-  stm32l5_unconfiggpio(priv->tx_gpio);
-  stm32l5_unconfiggpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32l5_unconfiggpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32l5_unconfiggpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -1942,17 +1956,24 @@ static int stm32l5serial_ioctl(struct file *filep, int 
cmd,
                 gpio_val |= GPIO_FLOAT;
               }
 
-            stm32l5_configgpio((priv->tx_gpio &
-                                ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
-                               gpio_val);
+            if (priv->tx_gpio != 0)
+              {
+                stm32l5_configgpio((priv->tx_gpio &
+                                    ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                    gpio_val);
+              }
 
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32l5_configgpio((priv->tx_gpio &
-                                ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
-                               GPIO_PUSHPULL);
+            if (priv->tx_gpio != 0)
+              {
+                stm32l5_configgpio((priv->tx_gpio &
+                                    ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                    GPIO_PUSHPULL);
+              }
+
             cr &= ~USART_CR3_HDSEL;
           }
 
@@ -2159,7 +2180,6 @@ static int stm32l5serial_ioctl(struct file *filep, int 
cmd,
     case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
       {
         irqstate_t flags;
-        uint32_t tx_break;
 
         flags = enter_critical_section();
 
@@ -2171,9 +2191,12 @@ static int stm32l5serial_ioctl(struct file *filep, int 
cmd,
 
         /* Configure TX as a GPIO output pin and Send a break signal */
 
-        tx_break = GPIO_OUTPUT |
-                   (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
-        stm32l5_configgpio(tx_break);
+        if (priv->tx_gpio != 0)
+          {
+            uint32_t tx_break = GPIO_OUTPUT |
+                    (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
+            stm32l5_configgpio(tx_break);
+          }
 
         leave_critical_section(flags);
       }
@@ -2187,7 +2210,10 @@ static int stm32l5serial_ioctl(struct file *filep, int 
cmd,
 
         /* Configure TX back to U(S)ART */
 
-        stm32l5_configgpio(priv->tx_gpio);
+        if (priv->tx_gpio != 0)
+          {
+            stm32l5_configgpio(priv->tx_gpio);
+          }
 
         priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
 
diff --git a/arch/arm/src/stm32n6/stm32_serial.c 
b/arch/arm/src/stm32n6/stm32_serial.c
index d6972700da6..220a34dc3ac 100644
--- a/arch/arm/src/stm32n6/stm32_serial.c
+++ b/arch/arm/src/stm32n6/stm32_serial.c
@@ -730,8 +730,15 @@ static int stm32serial_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32_configgpio(priv->tx_gpio);
-  stm32_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -858,12 +865,12 @@ static void stm32serial_shutdown(struct uart_dev_s *dev)
    * not, then this may need to be a configuration option.
    */
 
-  if (priv->unconfigure & USART_UNCONFIGURE_TX)
+  if ((priv->unconfigure & USART_UNCONFIGURE_TX) && (priv->tx_gpio != 0))
     {
       stm32_unconfiggpio(priv->tx_gpio);
     }
 
-  if (priv->unconfigure & USART_UNCONFIGURE_RX)
+  if ((priv->unconfigure & USART_UNCONFIGURE_RX) && (priv->rx_gpio != 0))
     {
       stm32_unconfiggpio(priv->rx_gpio);
     }
diff --git a/arch/arm/src/stm32u5/stm32_serial.c 
b/arch/arm/src/stm32u5/stm32_serial.c
index 7dd49c27b13..a5aea799e96 100644
--- a/arch/arm/src/stm32u5/stm32_serial.c
+++ b/arch/arm/src/stm32u5/stm32_serial.c
@@ -1406,8 +1406,15 @@ static int stm32serial_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32_configgpio(priv->tx_gpio);
-  stm32_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -1632,8 +1639,15 @@ static void stm32serial_shutdown(struct uart_dev_s *dev)
    * then this may need to be a configuration option.
    */
 
-  stm32_unconfiggpio(priv->tx_gpio);
-  stm32_unconfiggpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32_unconfiggpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32_unconfiggpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -1956,17 +1970,24 @@ static int stm32serial_ioctl(struct file *filep, int 
cmd,
                 gpio_val |= GPIO_FLOAT;
               }
 
-            stm32_configgpio((priv->tx_gpio &
-                                ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
-                               gpio_val);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio &
+                                  ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                  gpio_val);
+              }
 
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32_configgpio((priv->tx_gpio &
-                                ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
-                               GPIO_PUSHPULL);
+            if (priv->tx_gpio != 0)
+              {
+                stm32_configgpio((priv->tx_gpio &
+                                  ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                  GPIO_PUSHPULL);
+              }
+
             cr &= ~USART_CR3_HDSEL;
           }
 
@@ -2173,7 +2194,6 @@ static int stm32serial_ioctl(struct file *filep, int cmd,
     case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
       {
         irqstate_t flags;
-        uint32_t tx_break;
 
         flags = enter_critical_section();
 
@@ -2185,9 +2205,12 @@ static int stm32serial_ioctl(struct file *filep, int cmd,
 
         /* Configure TX as a GPIO output pin and Send a break signal */
 
-        tx_break = GPIO_OUTPUT |
-                   (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
-        stm32_configgpio(tx_break);
+        if (priv->tx_gpio != 0)
+          {
+            uint32_t tx_break = GPIO_OUTPUT |
+                    (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
+            stm32_configgpio(tx_break);
+          }
 
         leave_critical_section(flags);
       }
@@ -2201,7 +2224,10 @@ static int stm32serial_ioctl(struct file *filep, int cmd,
 
         /* Configure TX back to U(S)ART */
 
-        stm32_configgpio(priv->tx_gpio);
+        if (priv->tx_gpio != 0)
+          {
+            stm32_configgpio(priv->tx_gpio);
+          }
 
         priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
 
diff --git a/arch/arm/src/stm32wb/stm32wb_serial.c 
b/arch/arm/src/stm32wb/stm32wb_serial.c
index 83e90867924..e657d7435de 100644
--- a/arch/arm/src/stm32wb/stm32wb_serial.c
+++ b/arch/arm/src/stm32wb/stm32wb_serial.c
@@ -1096,8 +1096,15 @@ static int stm32wb_serial_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32wb_configgpio(priv->tx_gpio);
-  stm32wb_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32wb_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32wb_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -1320,8 +1327,15 @@ static void stm32wb_serial_shutdown(struct uart_dev_s 
*dev)
    * then this may need to be a configuration option.
    */
 
-  stm32wb_unconfiggpio(priv->tx_gpio);
-  stm32wb_unconfiggpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32wb_unconfiggpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32wb_unconfiggpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -1632,17 +1646,23 @@ static int stm32wb_serial_ioctl(struct file *filep, int 
cmd,
               (arg & SER_SINGLEWIRE_PULL_MASK) == SER_SINGLEWIRE_PULLDOWN ?
                                                   GPIO_PULLDOWN : GPIO_FLOAT;
 
-            stm32wb_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
-                                                  GPIO_OPENDRAIN)) |
-                                                  gpio_val);
+            if (priv->tx_gpio != 0)
+              {
+                stm32wb_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
+                                                      GPIO_OPENDRAIN)) |
+                                                      gpio_val);
+              }
 
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32wb_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
-                                                  GPIO_OPENDRAIN)) |
-                                                  GPIO_PUSHPULL);
+            if (priv->tx_gpio != 0)
+              {
+                stm32wb_configgpio((priv->tx_gpio & ~(GPIO_PUPD_MASK |
+                                                      GPIO_OPENDRAIN)) |
+                                                      GPIO_PUSHPULL);
+              }
 
             cr &= ~USART_CR3_HDSEL;
           }
@@ -1850,7 +1870,6 @@ static int stm32wb_serial_ioctl(struct file *filep, int 
cmd,
     case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
       {
         irqstate_t flags;
-        uint32_t tx_break;
 
         flags = enter_critical_section();
 
@@ -1862,9 +1881,12 @@ static int stm32wb_serial_ioctl(struct file *filep, int 
cmd,
 
         /* Configure TX as a GPIO output pin and Send a break signal */
 
-        tx_break = GPIO_OUTPUT |
-                   (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
-        stm32wb_configgpio(tx_break);
+        if (priv->tx_gpio != 0)
+          {
+            uint32_t tx_break = GPIO_OUTPUT |
+                    (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
+            stm32wb_configgpio(tx_break);
+          }
 
         leave_critical_section(flags);
       }
@@ -1878,7 +1900,10 @@ static int stm32wb_serial_ioctl(struct file *filep, int 
cmd,
 
         /* Configure TX back to U(S)ART */
 
-        stm32wb_configgpio(priv->tx_gpio);
+        if (priv->tx_gpio != 0)
+          {
+            stm32wb_configgpio(priv->tx_gpio);
+          }
 
         priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
 
diff --git a/arch/arm/src/stm32wl5/stm32wl5_serial.c 
b/arch/arm/src/stm32wl5/stm32wl5_serial.c
index 219de08b36c..524483ef5cb 100644
--- a/arch/arm/src/stm32wl5/stm32wl5_serial.c
+++ b/arch/arm/src/stm32wl5/stm32wl5_serial.c
@@ -1155,8 +1155,15 @@ static int stm32wl5serial_setup(struct uart_dev_s *dev)
 
   /* Configure pins for USART use */
 
-  stm32wl5_configgpio(priv->tx_gpio);
-  stm32wl5_configgpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32wl5_configgpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32wl5_configgpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -1381,8 +1388,15 @@ static void stm32wl5serial_shutdown(struct uart_dev_s 
*dev)
    * then this may need to be a configuration option.
    */
 
-  stm32wl5_unconfiggpio(priv->tx_gpio);
-  stm32wl5_unconfiggpio(priv->rx_gpio);
+  if (priv->tx_gpio != 0)
+    {
+      stm32wl5_unconfiggpio(priv->tx_gpio);
+    }
+
+  if (priv->rx_gpio != 0)
+    {
+      stm32wl5_unconfiggpio(priv->rx_gpio);
+    }
 
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   if (priv->cts_gpio != 0)
@@ -1707,17 +1721,24 @@ static int stm32wl5serial_ioctl(struct file *filep, int 
cmd,
                 gpio_val |= GPIO_FLOAT;
               }
 
-            stm32wl5_configgpio((priv->tx_gpio &
-                                ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
-                               gpio_val);
+            if (priv->tx_gpio != 0)
+              {
+                stm32wl5_configgpio((priv->tx_gpio &
+                                     ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                     gpio_val);
+              }
 
             cr |= USART_CR3_HDSEL;
           }
         else
           {
-            stm32wl5_configgpio((priv->tx_gpio &
-                                ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
-                               GPIO_PUSHPULL);
+            if (priv->tx_gpio != 0)
+              {
+                stm32wl5_configgpio((priv->tx_gpio &
+                                     ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) |
+                                     GPIO_PUSHPULL);
+              }
+
             cr &= ~USART_CR3_HDSEL;
           }
 
@@ -1924,7 +1945,6 @@ static int stm32wl5serial_ioctl(struct file *filep, int 
cmd,
     case TIOCSBRK:  /* BSD compatibility: Turn break on, unconditionally */
       {
         irqstate_t flags;
-        uint32_t tx_break;
 
         flags = enter_critical_section();
 
@@ -1936,9 +1956,12 @@ static int stm32wl5serial_ioctl(struct file *filep, int 
cmd,
 
         /* Configure TX as a GPIO output pin and Send a break signal */
 
-        tx_break = GPIO_OUTPUT |
-                   (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
-        stm32wl5_configgpio(tx_break);
+        if (priv->tx_gpio != 0)
+          {
+            uint32_t tx_break = GPIO_OUTPUT |
+                    (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio);
+            stm32wl5_configgpio(tx_break);
+          }
 
         leave_critical_section(flags);
       }
@@ -1952,7 +1975,10 @@ static int stm32wl5serial_ioctl(struct file *filep, int 
cmd,
 
         /* Configure TX back to U(S)ART */
 
-        stm32wl5_configgpio(priv->tx_gpio);
+        if (priv->tx_gpio != 0)
+          {
+            stm32wl5_configgpio(priv->tx_gpio);
+          }
 
         priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
 


Reply via email to