Skip to content

dcd/ch32hs: bus speed detection and data toggle gate#3727

Open
HiFiPhile wants to merge 3 commits into
masterfrom
dcd_ch32hs_spd
Open

dcd/ch32hs: bus speed detection and data toggle gate#3727
HiFiPhile wants to merge 3 commits into
masterfrom
dcd_ch32hs_spd

Conversation

@HiFiPhile

@HiFiPhile HiFiPhile commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

This pull request improves the handling of USB bus reset and OUT packet processing in the dcd_ch32_usbhs.c driver. The main changes include deferring the bus reset event until the actual device speed can be determined and filtering OUT packets based on the data toggle status.

Bus Reset Handling Improvements:

  • Bus reset events are now deferred until the next setup packet, allowing accurate detection of the actual USB speed before signaling the reset event. This replaces the previous approach, which always reported high speed on reset. (reset_evt_pending flag and related logic) [1] [2] [3]

OUT Packet Processing:

  • OUT packets are now only processed if the data toggle matches expectations, preventing handling of retransmitted or out-of-sequence packets.

Speed selection in dcd_init()

These changes improve the reliability and standards-compliance of the USB device controller implementation.

Copilot AI review requested due to automatic review settings June 23, 2026 08:09
@HiFiPhile

Copy link
Copy Markdown
Collaborator Author

@claude review

@claude

claude Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @HiFiPhile's task in 2m 20s —— View job


Code Review

  • Gather context
  • Read changed file and diff
  • Analyze changes
  • Post review findings

Summary

Two well-motivated changes to the CH32 USBHS driver. The approach is sound, and the OUT-toggle gate aligns with the pattern already established for USBFS variants (cca6fe6). One real bug found in the deferred-reset path.


Change 1 — Defer bus reset for speed detection (10f6d7e)

Why this is correct: The original code had a TODO acknowledging the USBHS interrupt fires at the start of bus reset before speed negotiation finishes, then hardcoded TUSB_SPEED_HIGH. Deferring to the first SETUP packet gives the hardware time to complete speed negotiation, and USBHSD->SPEED_TYPE is stable by then.

Bug: uninitialized actual_speed in release builds (src/portable/wch/dcd_ch32_usbhs.c:444)

tusb_speed_t actual_speed;
switch(USBHSD->SPEED_TYPE & USBHS_SPEED_TYPE_MASK){
  ...
  default:
    TU_ASSERT(0,);
    break;          // <-- falls through with actual_speed uninitialized
}
dcd_event_bus_reset(0, actual_speed, true);  // UB in release

TU_ASSERT(0,) expands to nothing in release builds, so the default branch leaves actual_speed uninitialized and dcd_event_bus_reset() is called with an indeterminate value. Add a return after the assert (or a safe default before the break):

default:
  TU_ASSERT(0,);
  return;   // don't fire a reset with unknown speed

Fix this →

Minor: reset_evt_pending not cleared in dcd_init() (dcd_ch32_usbhs.c:177)

The flag is a static bool (zero-initialized at program start), but dcd_init() doesn't reset it explicitly. If the stack ever reinitializes without a power cycle (e.g., a soft-reset flow), a stale true value would inject a spurious bus reset event at the next SETUP. One-liner fix in dcd_init():

reset_evt_pending = false;

Observation: dcd_event_bus_reset(0, ...) hardcodes rhport=0 — this is pre-existing (the old code did the same), just noting it for completeness.


Change 2 — Drop OUT packets with mismatched data toggle (1f7a8e8)

} else if (token == USBHS_TOKEN_PID_OUT && (int_status & USBHS_DEV_UIS_TOG_OK)) {

Correct. USBHS_DEV_UIS_TOG_OK indicates the received toggle matched the expected value. Ignoring mismatched packets is the right behavior: the hardware already ACKed the packet (with USBHS_INT_BUSY_EN set, the ACK is sent when INT_FG is cleared), and the driver correctly discards the data without advancing queued_len or toggling ep_data_tog. The endpoint remains armed for the next (correct) packet because queue_out_packet() had previously set EP_RX_CTRL to ACK, which is restored after INT_FG is cleared. Consistent with the USBFS fix.


Verdict

The logic is correct and the approach is an improvement over the hardcoded TUSB_SPEED_HIGH. The only blocking issue is the uninitialized actual_speed in the default case — please add return; after the assert. The dcd_init() clear is a nice-to-have.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the CH32 USBHS device controller driver (dcd_ch32_usbhs.c) to improve correctness around bus reset handling and OUT packet processing, aiming to better align behavior with actual negotiated bus speed and to avoid consuming retransmitted/out-of-sequence OUT data.

Changes:

  • Defer DCD_EVENT_BUS_RESET emission until a subsequent SETUP packet so the driver can report the actual detected speed rather than assuming high-speed.
  • Gate OUT packet processing on the controller’s toggle-valid indication to drop packets with unexpected DATA0/DATA1 state.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/portable/wch/dcd_ch32_usbhs.c
Comment thread src/portable/wch/dcd_ch32_usbhs.c
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

Size Difference Report

Because TinyUSB code size varies by port and configuration, the metrics below represent the averaged totals across all example builds.

Note: If there is no change, only one value is shown.

Changes >1% in size

file .text .bss size % diff
dcd_ch32_usbhs.c 1892 ➙ 1977 (+85) 481 ➙ 482 (+1) 2373 ➙ 2459 (+86) +3.6%
TOTAL 1892 ➙ 1977 (+85) 481 ➙ 482 (+1) 2373 ➙ 2459 (+86) +3.6%
Changes <1% in size

No entries.

No changes
file .text .rodata .data .bss size % diff
audio_device.c 2890 0 1259 1623 4508 +0.0%
cdc_device.c 1236 16 1092 728 1963 +0.0%
cdc_host.c 6399 487 15 971 7594 +0.0%
dcd_ch32_usbfs.c 1659 0 0 2444 4103 +0.0%
dcd_ci_fs.c 1924 0 0 1290 3214 +0.0%
dcd_ci_hs.c 1756 0 0 1344 2534 +0.0%
dcd_da146xx.c 3067 0 0 144 3211 +0.0%
dcd_dwc2.c 4223 19 0 265 4506 +0.0%
dcd_eptri.c 2273 0 0 259 2532 +0.0%
dcd_ft9xx.c 3284 0 0 172 3456 +0.0%
dcd_khci.c 1952 0 0 1290 3242 +0.0%
dcd_lpc17_40.c 1481 0 0 648 1805 +0.0%
dcd_lpc_ip3511.c 1463 0 0 264 1683 +0.0%
dcd_mm32f327x_otg.c 1477 0 0 1290 2767 +0.0%
dcd_msp430x5xx.c 1801 0 0 176 1977 +0.0%
dcd_musb.c 2595 0 0 179 2773 +0.0%
dcd_nrf5x.c 2939 0 0 292 3231 +0.0%
dcd_nuc120.c 1096 0 0 78 1174 +0.0%
dcd_nuc121.c 1170 0 0 101 1270 +0.0%
dcd_nuc505.c 0 0 1533 157 1690 +0.0%
dcd_rp2040.c 840 0 764 653 2257 +0.0%
dcd_rusb2.c 2918 0 0 156 3074 +0.0%
dcd_samd.c 1036 0 0 266 1302 +0.0%
dcd_samg.c 1322 0 0 72 1394 +0.0%
dcd_stm32_fsdev.c 2534 0 0 291 2825 +0.0%
dfu_device.c 776 28 712 136 912 +0.0%
dfu_rt_device.c 157 0 134 0 157 +0.0%
dwc2_common.c 603 22 0 0 615 +0.0%
ecm_rndis_device.c 1059 0 1 2759 3818 +0.0%
ehci.c 2763 0 0 6274 7783 +0.0%
fsdev_common.c 180 0 0 0 180 +0.0%
hcd_ch32_usbfs.c 2491 0 0 502 2993 +0.0%
hcd_ci_hs.c 181 0 0 0 181 +0.0%
hcd_dwc2.c 5070 25 1 545 5640 +0.0%
hcd_khci.c 2443 0 0 454 2897 +0.0%
hcd_musb.c 3071 0 0 157 3228 +0.0%
hcd_pio_usb.c 262 0 240 0 502 +0.0%
hcd_rp2040.c 1996 17 4 321 2338 +0.0%
hcd_rusb2.c 2923 0 0 245 3168 +0.0%
hcd_samd.c 2220 0 0 324 2544 +0.0%
hcd_stm32_fsdev.c 3248 0 1 420 3670 +0.0%
hid_device.c 1123 44 997 119 1242 +0.0%
hid_host.c 1241 0 0 1270 2511 +0.0%
hub.c 1384 8 8 30 1419 +0.0%
midi2_device.c 2628 52 1175 561 3211 +0.0%
midi2_host.c 1802 0 0 5921 7723 +0.0%
midi_device.c 1149 0 1007 619 1765 +0.0%
midi_host.c 1339 7 7 3538 4880 +0.0%
msc_device.c 2513 108 2281 804 3318 +0.0%
msc_host.c 1633 0 0 395 2028 +0.0%
mtp_device.c 1713 22 743 589 2309 +0.0%
ncm_device.c 1761 28 819 4393 6167 +0.0%
ohci.c 1925 0 0 2503 4428 +0.0%
printer_device.c 828 0 706 560 1387 +0.0%
rp2040_usb.c 386 35 619 11 1051 +0.0%
rusb2_common.c 160 0 16 0 176 +0.0%
tusb.c 455 0 387 3 457 +0.0%
tusb_fifo.c 855 0 486 0 850 +0.0%
typec_stm32.c 820 8 2 12 842 +0.0%
usbc.c 420 2 20 166 608 +0.0%
usbd.c 3530 57 90 355 3948 +0.0%
usbh.c 4967 57 82 1165 6238 +0.0%
usbtmc_device.c 2194 24 68 313 2539 +0.0%
vendor_device.c 639 0 534 559 1197 +0.0%
video_device.c 4433 5 1235 480 4905 +0.0%
TOTAL 122676 1071 17038 51656 175910 +0.0%

@claude

claude Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

Top 10 targets by memory change (%) (out of 2403 targets) View Project Dashboard →

target .text .rodata .data .bss total % diff
ch32v307v_r1_1v0/dfu_runtime 9,380 → 9,476 (+96) 9,876 → 9,972 (+96) +1.0%
ch32v307v_r1_1v0/hid_generic_inout 10,520 → 10,616 (+96) 11,016 → 11,112 (+96) +0.9%
ch32f205r-r0/dfu_runtime 7,940 → 8,016 (+76) 8,812 → 8,888 (+76) +0.9%
ch32f205r-r0/hid_generic_inout 8,956 → 9,032 (+76) 9,656 → 9,732 (+76) +0.8%
ch32v307v_r1_1v0/hid_composite 11,712 → 11,808 (+96) 12,208 → 12,304 (+96) +0.8%
ch32v307v_r1_1v0/midi_test 11,848 → 11,944 (+96) 12,344 → 12,440 (+96) +0.8%
ch32v307v_r1_1v0/hid_multiple_interface 11,340 → 11,432 (+92) 11,836 → 11,928 (+92) +0.8%
ch32v307v_r1_1v0/hid_boot_interface 11,364 → 11,456 (+92) 11,860 → 11,952 (+92) +0.8%
ch32f205r-r0/hid_multiple_interface 9,568 → 9,644 (+76) 10,440 → 10,516 (+76) +0.7%
ch32f205r-r0/hid_boot_interface 9,624 → 9,700 (+76) 10,452 → 10,528 (+76) +0.7%

Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

Hardware-in-the-loop (HIL) Test Report

hfp-iar

Board cdc_dual_ports cdc_msc dfu cdc_msc_throughput audio_test_freertos dfu_runtime cdc_msc_freertos hid_boot_interface msc_dual_lun hid_generic_inout printer_to_cdc midi_test mtp
stm32l412nucleo ✅ CDC 636k/401k MSC 814k/750k
stm32f746disco ✅ CDC 12.7M/8.4M MSC 16.5M/22.8M
stm32f746disco-DMA ✅ CDC 12.6M/10.6M MSC 15.7M/31.3M
lpcxpresso43s67 ✅ CDC 10.2M/9.2M MSC 20.8M/21.2M

Legend: ✅ pass · ❌ fail · ⚪ skipped · blank not run

hfp.json

Board cdc_dual_ports cdc_msc dfu cdc_msc_throughput audio_test_freertos dfu_runtime cdc_msc_freertos hid_boot_interface msc_dual_lun hid_generic_inout printer_to_cdc midi_test mtp
stm32l412nucleo ✅ CDC 630k/412k MSC 836k/748k
stm32f746disco ✅ CDC 13.7M/9.7M MSC 15.6M/28.5M
stm32f746disco-DMA ✅ CDC 13.3M/10.7M MSC 16M/30.8M
lpcxpresso43s67 ✅ CDC 11.4M/12.3M MSC 29.5M/34.6M

Legend: ✅ pass · ❌ fail · ⚪ skipped · blank not run

tinyusb.json

Board cdc_dual_ports cdc_msc dfu cdc_msc_throughput audio_test_freertos dfu_runtime cdc_msc_freertos hid_boot_interface msc_dual_lun hid_generic_inout printer_to_cdc midi_test mtp host_info_to_device_cdc cdc_msc_hid msc_file_explorer msc_file_explorer_freertos device_info hid_composite_freertos
ek_tm4c123gxl ✅ CDC 847k/977k MSC 960k/1M
espressif_p4_function_ev rd 409KB/s
espressif_p4_function_ev-DMA rd 409KB/s
espressif_s3_devkitm rd 409KB/s
espressif_s3_devkitm-DMA rd 409KB/s
feather_nrf52840_express ✅ CDC 482k/517k MSC 539k/554k
max32666fthr ✅ CDC 7M/13.5M MSC 13M/12.8M
metro_m4_express ✅ CDC 404k/430k MSC 344k/486k
mimxrt1015_evk ✅ CDC 14.7M/8.8M MSC 21.1M/15.9M
mimxrt1064_evk ✅ CDC 11.4M/4.2M MSC 23.1M/18.3M rd 1365KB/s rd 1365KB/s
lpcxpresso11u37 ✅ CDC 353k/293k MSC 559k/560k
ra4m1_ek ✅ CDC 405k/467k MSC 332k/470k
raspberry_pi_pico ✅ CDC 392k/467k MSC 333k/468k rd 62KB/s rd 62KB/s
raspberry_pi_pico_w rd 1106KB/s rd 1022KB/s
raspberry_pi_pico2 rd 1110KB/s rd 1022KB/s
adafruit_fruit_jam ✅ CDC 557k/579k MSC 444k/331k rd 62KB/s rd 62KB/s
stm32f072disco ✅ CDC 386k/355k MSC 409k/423k
stm32f407disco ✅ CDC 576k/539k MSC 848k/1M
stm32f723disco ✅ CDC 464k/790k MSC 442k/593k rd 17476KB/s rd 4096KB/s
stm32f723disco-DMA ✅ CDC 920k/907k MSC 1.1M/1M rd 20164KB/s rd 4096KB/s
stm32h743nucleo ✅ CDC 984k/745k MSC 879k/1M
stm32h743nucleo-DMA ✅ CDC 534k/886k MSC 622k/894k
stm32g0b1nucleo ✅ CDC 426k/472k MSC 463k/524k
stm32l476disco ✅ CDC 570k/504k MSC 524k/723k
stm32u083nucleo ✅ CDC 427k/453k MSC 499k/551k
nanoch32v203-fsdev ✅ CDC 658k/738k MSC 751k/633k
nanoch32v203-usbfs ✅ CDC 883k/569k MSC 1.1M/981k
ch32v103r_r1_1v0
ch582m_evt ✅ CDC 195k/223k MSC 382k/476k

Legend: ✅ pass · ❌ fail · ⚪ skipped · blank not run

Signed-off-by: HiFiPhile <admin@hifiphile.com>
@HiFiPhile HiFiPhile changed the title cdc/ch32hs: bus speed detection and data toggle gate dcd/ch32hs: bus speed detection and data toggle gate Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants