Skip to content

Change attach/detach logic on the root-port to use debounce counter - #2

Open
verylowfreq wants to merge 5 commits into
joypad-ai:ch32v307-usbfs-hostfrom
verylowfreq:verylowfreq/pr-wch-usbfs-fix
Open

Change attach/detach logic on the root-port to use debounce counter#2
verylowfreq wants to merge 5 commits into
joypad-ai:ch32v307-usbfs-hostfrom
verylowfreq:verylowfreq/pr-wch-usbfs-fix

Conversation

@verylowfreq

@verylowfreq verylowfreq commented Jun 12, 2026

Copy link
Copy Markdown

This PR updates the root-port attach/detach logic in the WCH CH32 USBFS HCD to use debounced SOF-based state confirmation.

While porting this HCD to Adafruit_TinyUSB, I found that hotplug detection on the root port was unstable. The CH32 USBFS DETECT signal can toggle during normal traffic and around bus reset, so using it as an immediate attach/detach event can cause false remove/reattach handling.

This change uses DETECT only as a hint and confirms port state with consecutive SOF samples.

In my testing, this issue was observable in Adafruit_TinyUSB. I did not observe a regression in the standalone TinyUSB examples.

Tests:

  • TinyUSB cdc_msc_hid
  • Adafruit_TinyUSB host_device_info
  • with and without a hub

[Updates]
My Adafruit_TinyUSB repository is here: https://github.com/verylowfreq/Adafruit_TinyUSB_Arduino
Changes: USBFSH -> USBOTG_H_FS, Rename Delay_Ms and Delay_Us to __Delay_Ms and __Delay_Us (to avoid conflicts)

RobertDaleSmith and others added 5 commits June 8, 2026 10:11
Rework hcd_ch32_usbfs.c into an asynchronous single-engine scheduler:
ISR-driven round-robin over a flat ep[] array keyed by (daddr,ep_num,dir),
one transaction outstanding on the USBFS host engine, interrupt EPs paced
to bInterval. This adds USB hub, multiple-simultaneous-device, and hotplug
support that the prior single-device driver (hathach#2793) lacked.

Attach and disconnect are self-driven from the SOF interrupt: hcd_init()
enables SOF generation so the 1ms tick runs even with no device attached,
and that tick polls DEV_ATTACH (a device present at power-up makes no
DETECT edge) and the no-response disconnect counter. Hot-plug also takes
the DETECT edge as a fast path. No application poll hook is required.

Control transfers go through WCH's reference transaction layer
(wch_usbfs_ll.c, USBFSH_CtrlTransfer), which reliably enumerates
bus-powered hubs and a broad range of devices. Code derived from WCH's
HOST_KM reference, (c) WCH; thin headers MIT.

Stays MCU-portable via ch32_usbfs_reg.h: it selects ch32v20x.h/ch32v30x.h
plus the matching _usb.h by CFG_TUSB_MCU, and the driver/LL include only
that selector (no hardcoded MCU header). v20x's SDK lacks RCC_USBFSCLKConfig,
so the LL defers USB clock-source setup to board_init() there (as v307 also
does). Supports CH32V20x and CH32V307 from one driver.
tusb_mcu.h auto-enables CFG_TUH_WCH_USBIP_USBFS for v307 (mirroring the
v20x block; v307 has no USBHS host IP, only USBFS). Wire the host sources
into both the make (family.mk) and cmake (family.cmake) builds: v307 adds
hcd_ch32_usbfs.c + wch_usbfs_ll.c, v20x adds wch_usbfs_ll.c (it already
built the HCD). v307 BSP also routes the USBFS IRQ to tuh_int_handler
(vector is USBFS_IRQHandler, not OTG_FS_IRQHandler) and bumps the linker
stack; v20x's USBHD_IRQHandler -> tuh_int_handler wiring is unchanged.
A failed TU_ASSERT/TU_VERIFY runs ebreak unconditionally; on WCH QingKe
cores the WCH-LinkE leaves the debug module enabled after flashing, so
that ebreak soft-resets the chip instead of returning the error value.
Since these asserts fire on recoverable events (NAK, transient enum
hiccup), host enumeration hit reboot loops. No-op the breakpoint on
CH32V20x/V307/F20x so the assert returns its error value as on ARM.
@RobertDaleSmith
RobertDaleSmith force-pushed the ch32v307-usbfs-host branch 3 times, most recently from 434051d to 34f3170 Compare June 23, 2026 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants