While working on a Daisy project that involves a REPL over the USB-Serial link, Claude Fable discovered that src/usbd/usbd_conf.c’s PCD_SuspendCallback calls __HAL_PCD_GATE_PHYCLOCK(hpcd) on every bus suspend. The resume callback does not call __HAL_PCD_UNGATE_PHYCLOCK, and there is no wakeup interrupt handler — so after the first transient bus suspend (hosts issue them routinely around driver attach and selective-suspend of idle ports), the USB data path is dead in both directions until the MCU resets. The device stays enumerated, which makes it look like an application or host problem.
Evidence gathered on a Daisy Patch, JTAG reads on a running core: within ~440 ms of app boot, PCGCCTL reads 0x00000001 (STOPCLK set) and never clears; DSTS.SUSPSTS is 0 (the bus resumed); exactly one armed IN transfer sits forever with EPENA=1 while the host polls into NAKs. Reproduced identically from macOS and Windows hosts.
The ST reference templates ungate in the resume path. Restoring that counterpart (or making the gating conditional, as it already is for the low_power_enable branch) fixes it. We currently work around it from application code by clearing PCGCCTL.STOPCLK whenever it is found set, which took our CDC console from dead-after-seconds to passing a 50 KB full-speed paste test.
Happy to submit a PR for the resume-side ungate.
While working on a Daisy project that involves a REPL over the USB-Serial link, Claude Fable discovered that
src/usbd/usbd_conf.c’s PCD_SuspendCallbackcalls__HAL_PCD_GATE_PHYCLOCK(hpcd)on every bus suspend. The resume callback does not call__HAL_PCD_UNGATE_PHYCLOCK, and there is no wakeup interrupt handler — so after the first transient bus suspend (hosts issue them routinely around driver attach and selective-suspend of idle ports), the USB data path is dead in both directions until the MCU resets. The device stays enumerated, which makes it look like an application or host problem.Evidence gathered on a Daisy Patch, JTAG reads on a running core: within ~440 ms of app boot,
PCGCCTL reads 0x00000001 (STOPCLK set)and never clears;DSTS.SUSPSTSis 0 (the bus resumed); exactly one armed IN transfer sits forever withEPENA=1while the host polls into NAKs. Reproduced identically from macOS and Windows hosts.The ST reference templates ungate in the resume path. Restoring that counterpart (or making the gating conditional, as it already is for the low_power_enable branch) fixes it. We currently work around it from application code by clearing
PCGCCTL.STOPCLKwhenever it is found set, which took our CDC console from dead-after-seconds to passing a 50 KB full-speed paste test.Happy to submit a PR for the resume-side ungate.