fix(dcd_ch32_usbfs): fix dropped bulk OUT packets by properly re-arming EP_RX_CTRL state#3622
Conversation
…ng EP_RX_CTRL state
|
| target | .text | .rodata | .data | .bss | total | % diff |
|---|---|---|---|---|---|---|
| ch32v307v_r1_1v0/net_lwip_webserver | 52,120 → 56,304 (+4,184) | — | — | 18,276 → 26,492 (+8,216) | 73,388 → 85,792 (+12,404) | +16.9% |
| ch32v307v_r1_1v0/dfu_runtime | 8,908 → 9,360 (+452) | — | — | 1,056 → 1,092 (+36) | 12,556 → 13,048 (+492) | +3.9% |
| ch32v307v_r1_1v0/hid_generic_inout | 10,032 → 10,500 (+468) | — | — | 1,260 → 1,296 (+36) | 13,884 → 14,388 (+504) | +3.6% |
| ch32v307v_r1_1v0/hid_multiple_interface | 10,852 → 11,316 (+464) | — | — | 1,136 → 1,172 (+36) | 14,580 → 15,084 (+504) | +3.5% |
| ch32v307v_r1_1v0/hid_boot_interface | 10,876 → 11,340 (+464) | — | — | 1,136 → 1,172 (+36) | 14,604 → 15,108 (+504) | +3.5% |
| ch32v307v_r1_1v0/hid_composite | 11,224 → 11,692 (+468) | — | — | 1,160 → 1,196 (+36) | 14,976 → 15,484 (+508) | +3.4% |
| ch32f205r-r0/dfu_runtime | 7,580 → 7,928 (+348) | — | — | 1,416 → 1,452 (+36) | 11,440 → 11,824 (+384) | +3.4% |
| ch32f205r-r0/hid_generic_inout | 8,588 → 8,944 (+356) | — | — | 1,620 → 1,656 (+36) | 12,480 → 12,872 (+392) | +3.1% |
| ch32v307v_r1_1v0/audio_test | 12,508 → 12,984 (+476) | — | — | 1,712 → 1,748 (+36) | 16,844 → 17,360 (+516) | +3.1% |
| ch32f205r-r0/hid_multiple_interface | 9,200 → 9,556 (+356) | — | — | 1,496 → 1,532 (+36) | 13,140 → 13,532 (+392) | +3.0% |
There was a problem hiding this comment.
Pull request overview
This PR targets reliability of bulk OUT transfers on WCH CH32 USBFS device controller by ensuring OUT endpoints are properly re-armed via EP_RX_CTRL, preventing missed receive callbacks and dropped packets during sustained high-rate transfers.
Changes:
- Update
update_out()to programEP_RX_CTRL(ACK/NAK) for non-EP0 OUT endpoints based on whether an OUT transfer is still active. - Update
dcd_edpt_xfer()to explicitly re-enable OUT endpoint RX ACK when a new OUT transfer is queued.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| if (ep == 0) { | ||
| EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; | ||
| } else { | ||
| EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | | ||
| (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); | ||
| } |
| if (dir == TUSB_DIR_IN) { | ||
| update_in(rhport, ep, true); | ||
| } else { | ||
| EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | USBFS_EP_R_RES_ACK; |
|
Thank you, I think we should also remove ACK enablement in I don't have CH30V20x at hand but surprised by their USB IP implementation, if CPU load is high setting NAK after packet received can still missing data. |
Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
OUT is still buggy Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
It would casue race condition, SETUP packet is always acked. Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
Refactor the driver to follow USBFS style for easier maintenance. Replace the old packet/response helpers with explicit queue and update paths for IN and OUT transfers. Introduce transfer validity tracking and per-endpoint data toggle state. Reset toggle state on init, close-all, endpoint close, clear-stall, and bus reset. Initialize endpoint controls consistently in NAK + TOG_0 mode. Tighten EP0 setup/status handling and route transfer IRQ processing through the transfer-flag path. Stop enabling ISO_ACT in INT_EN and clear unhandled interrupt flags explicitly. Signed-off-by: HiFiPhile <admin@hifiphile.com>
Signed-off-by: HiFiPhile <admin@hifiphile.com>
|
I've included a large transfer reliability patch for both USBFS/USBHS driver.
Tested on CH32V203/CH32V305 with Concurrent ISO transfer is not working yet, eg |

When stress-testing a custom Vendor interface with lots of fast bulk transfers on CH32V30x (which use the USBFS controller), I noticed that a lot of data was dropped because
tud_vendor_rx_cb()would not always fire.After investigating, it seemed like
dcd_ch32_usbfswasn't updating theEP_RX_CTRLregister after a transfer completed or when a new one was queued.update_out()now properly setsEP_RX_CTRLto ACK or NAK for all endpoints based on transfer state, anddcd_edpt_xfer()explicitly re-enables ACK when re-queuing an OUT transfer.Bulk transfers now complete reliably without data loss or missed callbacks.