Skip to content

arm/stm32: Fix USB device driver handling on M0 parts. - #19903

Merged
xiaoxiang781216 merged 4 commits into
apache:masterfrom
ArrestedLightning:usb/m0-driver-fixes
Aug 20, 2026
Merged

arm/stm32: Fix USB device driver handling on M0 parts.#19903
xiaoxiang781216 merged 4 commits into
apache:masterfrom
ArrestedLightning:usb/m0-driver-fixes

Conversation

@jsanchez-2g

Copy link
Copy Markdown
Contributor

Summary

Fix four defects in the shared STM32 M0 USB device driver:

  • Correct packet memory area addressing. The M0 PMA is a linear 16-bit
    memory, but the driver used STM32F1-style offset scaling and 32-bit
    descriptor accesses.
  • Route endpoint 0 correct-transfer events to the control-endpoint handler
    instead of the generic endpoint handler.
  • Enable and acknowledge USB controller error and PMA-overrun interrupts.
  • Issue the correct USB peripheral reset pulse in arm_usbinitialize().

The combined defects prevented correct control transfers and USB enumeration on
STM32 M0 USB device parts.

Impact

  • New feature added: NO. Bug fixes only.
  • User adaptation required: NO.
  • Build impact: NO.
  • Hardware impact: YES. The driver is shared by STM32 F0, L0, G0, C0, and
    related M0 USB device implementations.
  • Documentation update required: NO.
  • Security impact: NO.
  • Compatibility impact: Existing working configurations retain the same public
    API and behavior; broken USB device paths become functional.

Testing

Build host:

  • Linux 6.18.33.2-microsoft-standard-WSL2
  • arm-none-eabi-gcc 13.2.1

Hardware:

  • ST NUCLEO-F072RB
  • ST NUCLEO-L073RZ

Before:

  • Both board USB-device configurations built but failed to enumerate as USB
    devices when tested from pristine apache/master plus board support.

After:

  • NUCLEO-F072RB: build, flash, NSH on USART2, and USB CDC/ACM enumeration pass.
  • NUCLEO-L073RZ: build, flash, NSH on USART2, and USB CDC/ACM enumeration pass.

Validation:

  • ./tools/checkpatch.sh -g apache/master...usb/m0-driver-fixes
  • File-mode checkpatch passed for all changed files.
  • Clean-room build and hardware test passed with matching upstream NuttX Apps.

PR verification Self-Check

  • This PR introduces one functional area: STM32 M0 USB device driver fixes.
  • All commits include a description, Signed-off-by, and Assisted-by trailers.
  • Source passes checkpatch.
  • Real hardware build and runtime testing was completed.
  • This PR is ready for review.

The packet memory area (PMA) accessors in the M0 USB device driver were
carried over from the STM32F1 implementation, where the PMA is seen by
the CPU as 16-bit values placed on 32-bit boundaries.  On the STM32F0,
STM32L0 and other M0 parts the PMA is a linear 16-bit memory, so the
F1 scaling is wrong:

- STM32_USB_BTABLE_RADDR() shifted the computed buffer descriptor offset
  left by one, addressing every second descriptor entry.
- The buffer descriptor accessors declared the descriptor entries as
  uint32_t and accessed them 32 bits at a time, so each write clobbered
  the adjacent entry.
- stm32_copytopma() and stm32_copyfrompma() scaled the PMA offset by two
  when computing the packet buffer address.

The result is that endpoint buffer descriptors and packet data are
written to the wrong offsets in packet memory, and no transfer completes
correctly.

Drop the F1 scaling and use 16-bit accesses throughout.  Note that the
sibling stm32_usbfs.h defines STM32_USB_BTABLE_RADDR() without the shift
already, so this brings the M0 header in line with it.

Assisted-by: GitHub Copilot:claude-opus-5
Signed-off-by: jsanchez-2g <jsanchez@2g-eng.com>
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 <jsanchez@2g-eng.com>
The initial interrupt mask enabled only reset, suspend and correct
transfer.  Error conditions reported by the controller, USB_ISTR_ERR and
USB_ISTR_PMAOVRN, were neither enabled nor acknowledged.

Because the status bits are never cleared, an error condition latched in
USB_ISTR remains set and is re-evaluated on every subsequent interrupt,
which makes the reported status misleading when debugging transfer
problems.

Add ERRM and PMAOVRN to the initial mask and clear the corresponding
status bits when they are seen.

Assisted-by: GitHub Copilot:claude-opus-5
Signed-off-by: jsanchez-2g <jsanchez@2g-eng.com>
The code that claimed to "enable clocking to the USB peripheral" cleared
RCC_APB1ENR_USBEN inside RCC_APB1RSTR.  That is both the wrong register
and the wrong bit: USBEN belongs to RCC_APB1ENR, while APB1RSTR holds
RCC_APB1RSTR_USBRST.  The peripheral clock is enabled by the RCC setup
performed at boot, so the write had no useful effect and merely cleared
an unrelated reset bit.

Issue a proper reset pulse on RCC_APB1RSTR_USBRST instead, so the
controller starts from a known state.

On STM32L0 the D+/D- lines are connected to the USB transceiver
automatically once the peripheral is enabled and there is no alternate
function to select, so skip the GPIO configuration on that chip.  The
board GPIO_USB_DM/GPIO_USB_DP definitions do not exist there.

Assisted-by: GitHub Copilot:claude-opus-5
Signed-off-by: jsanchez-2g <jsanchez@2g-eng.com>
@github-actions github-actions Bot added Arch: arm Issues related to ARM (32-bit) architecture Size: S The size of the change in this PR is small labels Aug 20, 2026
@github-actions

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

@xiaoxiang781216
xiaoxiang781216 merged commit d70725e into apache:master Aug 20, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants