From 432d21a11611e4bb7ea15cedf9f6bf1e4ddea63e Mon Sep 17 00:00:00 2001 From: jsanchez-2g Date: Tue, 18 Aug 2026 16:12:18 -0500 Subject: [PATCH] arm/stm32: Route EP0 completions to the EP0 handler on M0 parts. The correct transfer loop in stm32_usb_interrupt() dispatched every completion to stm32_epdone(), including those for endpoint 0. stm32_epdone() implements the generic bulk/interrupt endpoint completion path. It does not decode the SETUP stage, does not maintain the EP0 state machine, and does not apply the EP0 specific RX/TX status rules. Control transfers therefore never completed correctly and the device could not be enumerated. Dispatch endpoint 0 to stm32_ep0done(), which is the control endpoint handler and is already used for the same purpose by the low priority transfer path in stm32_lptransfer(). Assisted-by: GitHub Copilot:claude-opus-5 Signed-off-by: jsanchez-2g --- arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c b/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c index b39b0ad76a1..a63f5b9c06f 100644 --- a/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c +++ b/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c @@ -2390,7 +2390,14 @@ static int stm32_usb_interrupt(int irq, void *context, void *arg) /* And handle the completion event */ - stm32_epdone(priv, epno); + if (epno == EP0) + { + stm32_ep0done(priv, istr); + } + else + { + stm32_epdone(priv, epno); + } /* Fetch the status again for the next time through the loop */