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

commit ce0038f2bc3ef2ba336ab132fb4a78ce59c15b6f
Author: Jacob Dahl <[email protected]>
AuthorDate: Sat Aug 22 10:48:54 2026 -0600

    {arm,xtensa}/otg: unmask WKUP so USB resume reaches the class driver.
    
    Every DWC2-derived USB device driver enables USBSUSP in GINTMSK but not
    WKUP, and every one of them ANDs GINTSTS with GINTMSK before dispatch.
    The resume handler is therefore unreachable: CLASS_SUSPEND is delivered
    on suspend, CLASS_RESUME never is.
    
    For CDC/ACM that is fatal. cdcacm_suspend() calls uart_connected(false),
    after which serial.c refuses every open() and write() with -ENOTCONN,
    and the cdcacm_resume() that would clear it never runs. On a Linux host
    with the default USB autosuspend (power/control=auto, 2000 ms) simply
    closing the tty is enough to trip it, and the port stays dead for the
    rest of the boot while the device remains enumerated.
    
    Verified on STM32H7 (ARK FMU v6X): before, one host suspend leaves the
    CDC/ACM port permanently -ENOTCONN; after, ten forced suspend/resume
    cycles all recover with the MAVLink stream intact. The remaining
    drivers carry a line-for-line copy of the same initialisation.
    
    Assisted-by: Claude:claude-fable-5
    Signed-off-by: Jacob Dahl <[email protected]>
---
 arch/arm/src/at32/at32_otgfsdev.c                  | 5 +++--
 arch/arm/src/common/stm32/stm32_otgfsdev_m3m4_v1.c | 5 +++--
 arch/arm/src/common/stm32/stm32_otghsdev_m3m4_v1.c | 5 +++--
 arch/arm/src/efm32/efm32_usbdev.c                  | 5 +++--
 arch/arm/src/stm32f7/stm32_otgdev.c                | 5 +++--
 arch/arm/src/stm32h7/stm32_otgdev.c                | 7 ++++---
 arch/arm/src/stm32l4/stm32l4_otgfsdev.c            | 5 +++--
 arch/xtensa/src/esp32s3/esp32s3_otg_device.c       | 5 +++--
 8 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/arch/arm/src/at32/at32_otgfsdev.c 
b/arch/arm/src/at32/at32_otgfsdev.c
index 613ed8b34f2..068124bdaad 100644
--- a/arch/arm/src/at32/at32_otgfsdev.c
+++ b/arch/arm/src/at32/at32_otgfsdev.c
@@ -5539,8 +5539,9 @@ static void at32_hwinitialize(struct at32_usbdev_s *priv)
 
   /* Enable the interrupts in the INTMSK */
 
-  regval = (OTGFS_GINT_RXFLVL | OTGFS_GINT_USBSUSP | OTGFS_GINT_ENUMDNE |
-            OTGFS_GINT_IEP | OTGFS_GINT_OEP | OTGFS_GINT_USBRST);
+  regval = (OTGFS_GINT_RXFLVL | OTGFS_GINT_USBSUSP | OTGFS_GINT_WKUP |
+            OTGFS_GINT_ENUMDNE | OTGFS_GINT_IEP | OTGFS_GINT_OEP |
+            OTGFS_GINT_USBRST);
 
 #ifdef CONFIG_USBDEV_ISOCHRONOUS
   regval |= (OTGFS_GINT_IISOIXFR | OTGFS_GINT_IISOOXFR);
diff --git a/arch/arm/src/common/stm32/stm32_otgfsdev_m3m4_v1.c 
b/arch/arm/src/common/stm32/stm32_otgfsdev_m3m4_v1.c
index af02d027c98..bc75e664f4a 100644
--- a/arch/arm/src/common/stm32/stm32_otgfsdev_m3m4_v1.c
+++ b/arch/arm/src/common/stm32/stm32_otgfsdev_m3m4_v1.c
@@ -5533,8 +5533,9 @@ static void stm32_hwinitialize(struct stm32_usbdev_s 
*priv)
 
   /* Enable the interrupts in the INTMSK */
 
-  regval = (OTGFS_GINT_RXFLVL | OTGFS_GINT_USBSUSP | OTGFS_GINT_ENUMDNE |
-            OTGFS_GINT_IEP | OTGFS_GINT_OEP | OTGFS_GINT_USBRST);
+  regval = (OTGFS_GINT_RXFLVL | OTGFS_GINT_USBSUSP | OTGFS_GINT_WKUP |
+            OTGFS_GINT_ENUMDNE | OTGFS_GINT_IEP | OTGFS_GINT_OEP |
+            OTGFS_GINT_USBRST);
 
 #ifdef CONFIG_USBDEV_ISOCHRONOUS
   regval |= (OTGFS_GINT_IISOIXFR | OTGFS_GINT_IISOOXFR);
diff --git a/arch/arm/src/common/stm32/stm32_otghsdev_m3m4_v1.c 
b/arch/arm/src/common/stm32/stm32_otghsdev_m3m4_v1.c
index 4a0e61a2132..cec826ab19f 100644
--- a/arch/arm/src/common/stm32/stm32_otghsdev_m3m4_v1.c
+++ b/arch/arm/src/common/stm32/stm32_otghsdev_m3m4_v1.c
@@ -5426,8 +5426,9 @@ static void stm32_hwinitialize(struct stm32_usbdev_s 
*priv)
 
   /* Enable the interrupts in the INTMSK */
 
-  regval  = (OTGHS_GINT_RXFLVL | OTGHS_GINT_USBSUSP | OTGHS_GINT_ENUMDNE |
-             OTGHS_GINT_IEP | OTGHS_GINT_OEP | OTGHS_GINT_USBRST);
+  regval  = (OTGHS_GINT_RXFLVL | OTGHS_GINT_USBSUSP | OTGHS_GINT_WKUP |
+             OTGHS_GINT_ENUMDNE | OTGHS_GINT_IEP | OTGHS_GINT_OEP |
+             OTGHS_GINT_USBRST);
 
 #ifdef CONFIG_USBDEV_ISOCHRONOUS
   regval |= (OTGHS_GINT_IISOIXFR | OTGHS_GINT_IISOOXFR);
diff --git a/arch/arm/src/efm32/efm32_usbdev.c 
b/arch/arm/src/efm32/efm32_usbdev.c
index 8d0af3ebfff..c8545bd184e 100644
--- a/arch/arm/src/efm32/efm32_usbdev.c
+++ b/arch/arm/src/efm32/efm32_usbdev.c
@@ -5488,8 +5488,9 @@ static void efm32_hwinitialize(struct efm32_usbdev_s 
*priv)
   /* Enable the interrupts in the INTMSK */
 
   regval  = (USB_GINTMSK_RXFLVLMSK | USB_GINTMSK_USBSUSPMSK |
-             USB_GINTMSK_ENUMDONEMSK | USB_GINTMSK_IEPINTMSK |
-             USB_GINTMSK_OEPINTMSK | USB_GINTMSK_USBRSTMSK);
+             USB_GINTMSK_WKUPINTMSK | USB_GINTMSK_ENUMDONEMSK |
+             USB_GINTMSK_IEPINTMSK | USB_GINTMSK_OEPINTMSK |
+             USB_GINTMSK_USBRSTMSK);
 
 #ifdef CONFIG_USBDEV_ISOCHRONOUS
   regval |= (USB_GINTMSK_INCOMPISOINMSK | USB_GINTMSK_INCOMPLPMSK);
diff --git a/arch/arm/src/stm32f7/stm32_otgdev.c 
b/arch/arm/src/stm32f7/stm32_otgdev.c
index 96be757e9e3..fe2ce48008f 100644
--- a/arch/arm/src/stm32f7/stm32_otgdev.c
+++ b/arch/arm/src/stm32f7/stm32_otgdev.c
@@ -5666,8 +5666,9 @@ static void stm32_hwinitialize(struct stm32_usbdev_s 
*priv)
 
   /* Enable the interrupts in the INTMSK */
 
-  regval = (OTG_GINT_RXFLVL | OTG_GINT_USBSUSP | OTG_GINT_ENUMDNE |
-            OTG_GINT_IEP | OTG_GINT_OEP | OTG_GINT_USBRST);
+  regval = (OTG_GINT_RXFLVL | OTG_GINT_USBSUSP | OTG_GINT_WKUP |
+            OTG_GINT_ENUMDNE | OTG_GINT_IEP | OTG_GINT_OEP |
+            OTG_GINT_USBRST);
 
 #  ifdef CONFIG_USBDEV_ISOCHRONOUS
   regval |= (OTG_GINT_IISOIXFR | OTG_GINT_IISOOXFR);
diff --git a/arch/arm/src/stm32h7/stm32_otgdev.c 
b/arch/arm/src/stm32h7/stm32_otgdev.c
index d185b987a03..9a14ad87665 100644
--- a/arch/arm/src/stm32h7/stm32_otgdev.c
+++ b/arch/arm/src/stm32h7/stm32_otgdev.c
@@ -3362,7 +3362,7 @@ static inline void stm32_rxinterrupt(struct 
stm32_usbdev_s *priv)
                 regval  = stm32_getreg(STM32_OTG_DOEPCTL(0));
                 regval |= OTG_DOEPCTL0_CNAK;
                 stm32_putreg(regval, STM32_OTG_DOEPCTL(0));
-            }
+              }
           }
           break;
 
@@ -5565,8 +5565,9 @@ static void stm32_hwinitialize(struct stm32_usbdev_s 
*priv)
 
   /* Enable the interrupts in the INTMSK */
 
-  regval = (OTG_GINT_RXFLVL | OTG_GINT_USBSUSP | OTG_GINT_ENUMDNE |
-            OTG_GINT_IEP | OTG_GINT_OEP | OTG_GINT_USBRST);
+  regval = (OTG_GINT_RXFLVL | OTG_GINT_USBSUSP | OTG_GINT_WKUP |
+            OTG_GINT_ENUMDNE | OTG_GINT_IEP | OTG_GINT_OEP |
+            OTG_GINT_USBRST);
 
 #ifdef CONFIG_USBDEV_ISOCHRONOUS
   regval |= (OTG_GINT_IISOIXFR | OTG_GINT_IISOOXFR);
diff --git a/arch/arm/src/stm32l4/stm32l4_otgfsdev.c 
b/arch/arm/src/stm32l4/stm32l4_otgfsdev.c
index af2df0c32ad..0e84582f5a3 100644
--- a/arch/arm/src/stm32l4/stm32l4_otgfsdev.c
+++ b/arch/arm/src/stm32l4/stm32l4_otgfsdev.c
@@ -5594,8 +5594,9 @@ static void stm32_hwinitialize(struct stm32_usbdev_s 
*priv)
 
   /* Enable the interrupts in the INTMSK */
 
-  regval = (OTGFS_GINT_RXFLVL | OTGFS_GINT_USBSUSP | OTGFS_GINT_ENUMDNE |
-            OTGFS_GINT_IEP | OTGFS_GINT_OEP | OTGFS_GINT_USBRST);
+  regval = (OTGFS_GINT_RXFLVL | OTGFS_GINT_USBSUSP | OTGFS_GINT_WKUP |
+            OTGFS_GINT_ENUMDNE | OTGFS_GINT_IEP | OTGFS_GINT_OEP |
+            OTGFS_GINT_USBRST);
 
 #ifdef CONFIG_USBDEV_ISOCHRONOUS
   regval |= (OTGFS_GINT_IISOIXFR | OTGFS_GINT_IISOOXFR);
diff --git a/arch/xtensa/src/esp32s3/esp32s3_otg_device.c 
b/arch/xtensa/src/esp32s3/esp32s3_otg_device.c
index 6d9386652dd..ac4139c0149 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_otg_device.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_otg_device.c
@@ -5540,8 +5540,9 @@ static void esp32s3_hwinitialize(struct esp32s3_usbdev_s 
*priv)
 
   /* Enable the interrupts in the INTMSK */
 
-  regval = (OTG_GINT_RXFLVL | OTG_GINT_USBSUSP | OTG_GINT_ENUMDNE |
-            OTG_GINT_IEP | OTG_GINT_OEP | OTG_GINT_USBRST);
+  regval = (OTG_GINT_RXFLVL | OTG_GINT_USBSUSP | OTG_GINT_WKUP |
+            OTG_GINT_ENUMDNE | OTG_GINT_IEP | OTG_GINT_OEP |
+            OTG_GINT_USBRST);
 
 #ifdef CONFIG_USBDEV_ISOCHRONOUS
   regval |= (OTG_GINT_IISOIXFR | OTG_GINT_IISOOXFR);

Reply via email to