summaryrefslogtreecommitdiff
path: root/src/portable
AgeCommit message (Collapse)Author
2026-06-23dcd/ch32hs: implement speed selectiondcd_ch32hs_spdHiFiPhile
Signed-off-by: HiFiPhile <[email protected]>
2026-06-23dcd/ch32hs: drop OUT packet whose data toggle doesn't matchHiFiPhile
Signed-off-by: HiFiPhile <[email protected]>
2026-06-23dcd/ch32hs: defer bus reset event for proper speed detectionHiFiPhile
Signed-off-by: HiFiPhile <[email protected]>
2026-06-22Merge remote-tracking branch 'origin/master' into add-ch58x-usbfshathach
2026-06-22hw/bsp+wch: rename the CH58x family to ch583 and OPT_MCU_CH58X to OPT_MCU_CH583hathach
The BSP family and MCU option were named "ch58x"/"CH58X", but the supported part is the CH583/CH582 (and the SDK repo is openwch/ch583); CH585 is a separate MCU family, so the CH58x umbrella was misleading. Rename to the specific family: - hw/bsp/ch58x -> hw/bsp/ch583 (dir), and the BSP-local files ch58x_it.* -> ch583_it.*, system_ch58x.* -> system_ch583.* (include guards/refs updated). The vendor SDK files (CH58x_common.h, CH58x_*.c in hw/mcu/wch/ch583) keep their names. - OPT_MCU_CH58X -> OPT_MCU_CH583 in tusb_option.h, tusb_mcu.h, and the shared WCH USBFS driver (ch32_usbfs_reg.h, dcd_ch32_usbfs.c). OPT_MCU_CH582 is kept as an alias (same value), so either name selects the same code. - FAMILY_MCUS CH58X -> CH583, CFG_TUSB_MCU=OPT_MCU_CH583, mcu:CH58X -> mcu:CH583 in the example skip lists, the CI build matrix (ci_set_matrix.py), the get_deps family tag, and docs/reference/boards.rst. Board names (ch582m_evt, yd-ch582m) are unchanged. Verified: make + cmake build for ch582m_evt, and ci.lan HIL (all device examples pass). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-20dcd/wch: drop toggle-mismatched OUT packets on all USBFS variantshathach
The OUT data-toggle check -- drop a packet whose DATA0/DATA1 doesn't match the expected toggle (a host retransmit after a lost ACK, or a host that doesn't alternate the toggle) -- only ran on CH58x. The auto-toggle parts (V103/V20x/V307/ X035) never checked it, so a duplicate/retransmitted OUT was processed twice. HiFiPhile confirmed it: a host patched to send DATA0-only had CH32V305 accept every packet. Move the TOG_OK gate out of the CH58x-only block so it runs on every variant; the manual toggle flip stays CH58x-only. EP0 keeps its own toggle via the SETUP/status flow and is exempt. Verified on ci.lan HIL: ch582m_evt (CH58x), ch32v103r_r1_1v0 (V103), nanoch32v203 (V203) all pass. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-19dcd/ch58x: preserve the DEV_ADDR general-purpose bit on SET_ADDRESShathach
dcd_edpt0_status_complete() wrote the full SET_ADDRESS wValue into R8_USB_DEV_AD, clobbering bit 7, which on CH58x is a user general-purpose flag (only bits [6:0] are the device address). Mask to 7 bits and preserve bit 7, matching the removed dcd_ch58x_usbfs.c. CH58x-scoped; other parts keep the full write. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-19dcd/ch58x: drop stale EP0 transfer state on SETUPhathach
The PID_SETUP handler armed the new control transfer but left any in-flight EP0 transfer from the previous request marked valid, so a spurious EP0 IN/OUT could run update_in()/update_out() against stale state (the removed dcd_ch58x_usbfs.c invalidated both EP0 directions on every SETUP). Clear xfer[0] IN/OUT validity when a SETUP arrives. Applies to all WCH USBFS parts -- a new SETUP always supersedes a pending control xfer. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-19dcd/ch58x: report bus resume instead of a second suspendhathach
The USBFS SUSPEND interrupt fires on both the suspend and the resume edge, but the handler unconditionally posted DCD_EVENT_SUSPEND. On CH58x tud_resume_cb() therefore never ran, and a device that lowered clocks/power in tud_suspend_cb() was never told to restore them. Read MIS_ST's suspend bit (1 while suspended, 0 once resumed) to emit DCD_EVENT_RESUME on the wake edge -- what the removed dcd_ch58x_usbfs.c did. Scoped to CH58x via #if; the CH32 parts keep their existing behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-19dcd/ch58x: advance EP0 OUT data toggle for multi-packet control transfershathach
The manual-toggle ISR skipped EP0 entirely (if (ep != 0)), so EP0's RX data toggle was set to DATA1 once at SETUP and never advanced. A control-OUT whose data stage exceeds the EP0 packet size (a vendor/WebUSB OUT, a large HID SET_REPORT, or an HS DFU download) desynced on the second packet and stalled. EP0 has no hardware auto-toggle on CH58x (per the datasheet RB_UEP_AUTO_TOG applies only to EP1/2/3/5/6/7), so flip its RX toggle on every OUT and always process the packet -- restoring what the removed dcd_ch58x_usbfs.c did. The HIL examples keep their control-OUT data stages within a single packet, so this was latent. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-19dcd/ch58x: keep IRQ masked across the EP-arming RMW in dcd_edpt_xferhathach
dcd_edpt_xfer() re-enabled the USB interrupt before update_in() / ep_rx_set_response(), which read-modify-write the (combined) EP control register. On CH58x the ISR RMWs that same register to flip the manual data toggle, so a transfer interrupt landing mid-RMW could drop the toggle flip and desync the endpoint. Move dcd_int_enable() to after the arming so the whole sequence is atomic w.r.t. the ISR (matching the CH32X035 port #3703). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-19dcd/ch58x: complete the EP register map and right-size EP buffershathach
Tidy the CH58x register/buffer layout the initial port left rough. Register map (USBOTG_FS_TypeDef): - Extend the struct to the full CH583/582 datasheet Table 17-2 map instead of stopping at UEP567_MOD (0x0E) with the per-endpoint registers living only in raw-address macros. - Express the per-endpoint DMA/length/control registers as arrays of 4-byte slots (ch58x_ep_dma_t / ch58x_ep_ctrl_t): EP0-3 DMA at 0x10, EP0-4 ctrl at 0x20, EP5-7 DMA/ctrl split to 0x54/0x64 (EP4 has no DMA register of its own; it shares EP0's). TU_VERIFY_STATIC pins the slot sizes and block offsets, so the EP_TX_LEN/EP_CTRL/EP_DMA macros walk each block by the 4-byte stride (pointer arithmetic off slot 0, so the unused ternary branch can't trip -Warray-bounds). - Gate the two driver sites on CFG_TUSB_MCU == OPT_MCU_CH58X directly rather than the CH32_USBFS_EP_REGS_CUSTOM alias, which was only ever defined in the CH58x branch. EP buffers (the data struct): - Replace buffer[EP_MAX][2][64] on CH58x with named per-endpoint buffers: EP0/EP4 use the dedicated 192B ep0_ep4_buffer, so the old array left buffer[0]/buffer[4] allocated-but-unused. - Drop EP3's oversized iso buffer (out[64] + in[1023]); EP3 is bulk-only on CH58x, so it uses a plain 128-byte buffer like the others. The data struct shrinks from ~2636 to 1292 bytes. - Keep the now uniformly-64-byte buffers safe: dcd_edpt_iso_alloc()/iso_activate() refuse isochronous on CH58x (no iso support; 8-bit T_LEN caps a packet at 255B), and update_in()/update_out() additionally cap each packet copy to 64 bytes so a class that ignores the iso-alloc result cannot run a memcpy past a buffer into a neighbour's. Non-CH58x parts (e.g. ch32v103) keep the struct-based macros, buffer[EP_MAX], and the iso buffer unchanged. Verified on ch582m_evt HIL (ci.lan): all device examples pass; ch32v103 build unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-18Merge pull request #3701 from hathach/claude/issue-3696-20260612-0344Ha Thach
fix(stm32_fsdev): don't enable the unused USB wakeup EXTI IRQ (F1/F3/G4/L1)
2026-06-18fix(stm32_fsdev): don't enable the unused USB wakeup EXTI IRQ (F1/F3/G4/L1)hathach
The classic-USB STM32 fsdev driver enabled the EXTI-line USB wakeup interrupt (USBWakeUp_IRQn, and USBWakeUp_RMP_IRQn on the F3 remap path) in the NVIC, but never uses it: resume is serviced in-band via ISTR.WKUP in the USB_LP/HP ISR, and the driver never arms or clears that EXTI line. The wakeup EXTI interrupt is only needed to wake the core from STOP mode, which TinyUSB does not implement. Leaving its NVIC vector enabled lets it fire spuriously into an unhandled or looping vector -- the freeze reported in #3696 on STM32G473. USBWakeUp_IRQn is a valid, dedicated USB-wakeup-via-EXTI interrupt (e.g. stm32g473xx.h: =42 "USB Wakeup through EXTI line"), not an "unrelated interrupt"; it is simply unused here. - Comment out USBWakeUp_IRQn for F1/F3/G4/L1 and USBWakeUp_RMP_IRQn on the F3 remap path, kept in place so STOP-mode wakeup is a one-line re-enable. - Keep the STM32L1 USBWakeUp_IRQn -> USB_FS_WKUP_IRQn alias for that re-enable. - Document the rationale in fsdev_stm32.h with a TODO. - Comment out the matching USBWakeUp(_RMP)_IRQHandler in the F1/F3/G4 BSPs, and the FreeRTOS NVIC_SetPriority(USBWakeUp_IRQn) on F1/G4. Fixes #3696 Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-18dcd/ch58x: drive CH582/583 with shared dcd_ch32_usbfs.chathach
Replace PR #3515's separate dcd_ch58x_usbfs.c / hcd_ch58x_usbfs.c with the shared WCH USBFS device driver (combined per-endpoint control, like CH32V103), adding two CH58x-specific behaviors guarded so CH32V103/V20x/V307 are unchanged: - CH32_USBFS_EP_MANUAL_TOG: CH58x's hardware AUTO_TOG does not stay in sync, so the ISR toggles DATA0/DATA1 manually and discards toggle-mismatched OUT packets. Fixes multi-packet bulk-IN (e.g. MSC READ10) that otherwise hung. - CH32_USBFS_EP4_SHARES_EP0: EP4 has no DMA register and overlays EP0's region (EP0[0:63] + EP4 OUT[64:127] + EP4 IN[128:191]); add a 192-byte shared buffer and buffer-pointer helpers (transparent for the other parts). Fixes cdc_dual_ports (Port1 is on EP4). Add the ch582m_evt board. Device only on USB0 (rhport 0): the shared hcd_ch32_usbfs.c is CH32V20x-specific and cannot drive CH58x, so host / USB2 (rhport 1) is left commented out in the BSP for easy re-add. Verified on ch582m_evt via local HIL: all device examples pass. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-18Merge remote-tracking branch 'origin/master' into add-ch58x-usbfshathach
2026-06-18dcd/ch32_usbfs: support CH32V103 combined endpoint control registerhathach
CH32V103 uses the older USBFS IP: a single combined UEPn_CTRL register per endpoint (IN response in bits [1:0], OUT response in [3:2], shared auto-toggle, separate IN/OUT toggles) instead of the separate UEPn_TX_CTRL/UEPn_RX_CTRL bytes of the newer IP (CH32V20x/V307). The shared driver was written for the newer IP, so EP0 control transfers never worked on V103: the OUT response was written to a reserved byte and the IN write clobbered the OUT bits. - ch32_usbfs_reg.h: annotate the V103 register struct with byte offsets and add a union exposing the combined UEPn_CTRL at the UEPn_TX_CTRL offset; define CH32_USBFS_EP_CTRL_COMBINED and the combined-register bit positions. - dcd_ch32_usbfs.c: abstract EP control access behind ep_tx/rx_ctrl_set() (full write) and ep_tx/rx_set_response() (response-only RMW). The newer-IP path is unchanged; the combined path read-modify-writes the single register and arms the post-SETUP data stage at DATA1. - bsp/ch32v10x: implement board_get_unique_id() (real chip UID) and drop the CSR 0x800 writes that corrupted the QingKe V3 interrupt config and left all interrupts disabled (the USB ISR never ran). Verified on ch32v103r_r1_1v0: enumerates and passes HIL for cdc_msc, hid, msc, midi, mtp, dfu, etc. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-16dcd/musb: extract pipe0_data_stage_done() and fix two EP0 commentshathach
Cleanup from a code-review pass, no behavior change: - Replace the open-coded "last DATA packet" test (remain_wlength == 0 || len < CFG_TUD_ENDPOINT0_SIZE), duplicated in the edpt0_xfer DATA IN arm, pipe0_process_xfer_state_isr, and the DATA OUT drain, with one inline pipe0_data_stage_done() so IN and OUT can't drift. - Correct the xact_len comment (only the IN path reports it; OUT reports count0) and the dcd_edpt_stall comment (a deferred SETUP means the old transfer ended on the wire, not that its status stage was "seen"). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-15dcd/musb: rename pipe0_process_status_isr -> pipe0_process_xfer_state_isrhathach
The helper advances the whole EP0 control state machine on a completion/confirmation IRQ — it dispatches on pipe0->state and also fires the DATA_IN completion, not just the status stage — so "process_status" undersold it. Matches the process_*_isr family. Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-15dcd/musb: harden EP0 DATA_OUT against short packet and host overrunhathach
Mirror the IN-side short-packet fix on the OUT drain: end the data stage (-> STATUS_IN) when wLength is received OR a short OUT packet (count0 < CFG_TUD_ENDPOINT0_SIZE) signals the host's end-of-data, not only when remain_wlength hits exactly 0. Also clamp the remain_wlength subtraction so a host that overruns wLength can't underflow it and strand the transfer. Without this, a control-OUT whose host sends fewer bytes than wLength left pipe0 in DATA_OUT; usbd then armed STATUS IN and tripped the split's TU_ASSERT(!dir_in). Found by /code-review; conformant hosts send exactly wLength so HIL was already green. Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-15dcd/musb: read EP0 SETUP into uint32_t[2], drop the double copyhathach
pipe0_read_setup() copied the FIFO into a local union, then copied that into the caller's struct. Read the two FIFO words straight into the caller's uint32_t[2] (one copy) and cast to tusb_control_request_t* in pipe0_start_setup(). pipe0.deferred_setup becomes uint32_t[2] so the deferral path reads directly into it as well. Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-15dcd/musb: extract pipe0_process_status_isr() to de-dup EP0 tail pathshathach
The deferral (RXRDY-combined) and csrl==0 tail paths in process_ep0_isr ran the same per-state status-stage logic. Move all of it into one pipe0_process_status_isr() helper covering every state including DATA_IN, which picks STATUS_OUT vs STATUS_OUT_PENDING_IRQ from deferred_setup_valid (a deferred SETUP means the status confirm was coalesced with it). Both callers now just invoke the helper; the deferral path saves the SETUP and sets deferred_setup_valid first. Also drops the deferral path's TU_ASSERT(remain_wlength == 0), which was wrong for a short last DATA-IN packet, and renames pipe0_process_deferred_setup -> pipe0_try_deferred_setup (it no-ops when nothing is deferred). Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each), including the #3643 high-CPU-load IRQ-toggle coalescing stress. Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-15dcd/musb: suffix ISR-context process_* handlers with _isrhathach
Rename process_ep0/process_epin/process_epout/process_bus_reset (all invoked only from dcd_int_handler) to *_isr, making their ISR context explicit at every call site. pipe0_process_deferred_setup is left as-is since it also runs from task context (dcd_edpt_stall). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-15dcd/musb: end EP0 IN data stage on short packet, split DATA casehathach
A short IN control response (device sends fewer bytes than wLength — e.g. the 18-byte device descriptor answering a 64-byte GET_DESCRIPTOR) left remain_wlength != 0, so the DATA_IN -> STATUS_OUT transition never fired and pipe0 stayed in DATA_IN through the status stage. usbd then armed the status-OUT while state was still DATA_IN. Set DATAEND and transition on the last packet: remain_wlength == 0, or a short packet (incl. a terminating ZLP) which ends the data stage. With state now tracking the stage, split edpt0_xfer's DATA handling into separate DATA_IN / DATA_OUT cases dispatching on state (asserting state == call direction) instead of the combined dir_in branch. Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each), including the #3643 high-CPU-load IRQ-toggle coalescing stress. Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-15dcd/musb: name pipe0_state_t, use local pointer, group struct fieldshathach
Pure cleanup, no behavior change: - Extract the EP0 control-transfer state into a named pipe0_state_t typedef instead of an anonymous nested struct, and access it through a local pipe0_state_t* in the functions that touch it repeatedly. - Group the pipe0 fields so the two bools sit together and the larger tusb_control_request_t deferred_setup is last. - Reword the deferral comments: "coalesced" -> "combined". Note: separating the edpt0_xfer DATA_IN/DATA_OUT case (dispatch on state instead of dir_in) was attempted and reverted — it breaks ADI MUSB enumeration. usbd can arm the opposite-direction status while pipe0 is still in a DATA state, and only dir-dispatch routes that correctly; a comment on the combined case records this. Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-13dcd/musb: clear rxrdy_consumed when stalling EP0hathach
The actual-STALL path (no deferred SETUP) forced EP0 to IDLE but left rxrdy_consumed set if the aborted transfer had parked RXRDY via NAK flow control (e.g. a rejected OUT-data request in DATA_OUT). A subsequent SETUP IRQ would then hit the parked-gate early return and be ignored, relying on SentStall/SetupEnd to clear the flag first. Clear it here so recovery never depends on that ordering. Addresses Copilot review on #3699. Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-13dcd/musb: replay deferred SETUP instead of stalling EP0hathach
dcd_edpt_stall(EP0 OUT) discarded the deferred SETUP and armed SendStall. A deferred SETUP can only exist once the old transfer's status stage was seen on the wire, so the request usbd is rejecting (class callback failing at CONTROL_STAGE_DATA) already succeeded host-side and the hardware already ACKed the next SETUP - the STALL would land on that innocent request, which then fails host-side without any tud callback ever seeing it. Skip the stall and replay the deferred SETUP; the rejected transfer needs no wire-level stall since it is already over. Review follow-up for #3643 (dcd_musb.c l.860 finding). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-13dcd/musb: gate stale EP0 RXRDY interrupts with rxrdy_consumedhathach
The deferral path drains the SETUP but leaves RxPktRdy set, and the SETUP's IRQ latches after the ISR's clear-on-read intr_tx read - so a second process_ep0 pass (same ISR, via the intr_tx re-read merge) is guaranteed and misreads the leftovers: count0==0 fires a spurious DATA OUT completion, the replay's RXRDYC write turns the second pass into a phantom csrl==0 DATA IN completion, and a zero-length replay re-enters the deferral case on a drained FIFO (count0 assert or garbage saved as a SETUP). The registers cannot expose the staleness: RxPktRdy and count0 read unchanged until ServicedRxPktRdy is written. Track it in software: rxrdy_consumed means "RxPktRdy is set in hw but its packet was already consumed". Set wherever a drained packet's RXRDY is intentionally left set (OUT/zero-length flow-control parks, every DATA OUT drain awaiting the next arm, the deferral path); cleared at every RXRDYC write site (edpt0_xfer arms, dcd_set_address, STALLED/SETEND recovery, bus reset). The RXRDY block returns early while parked. Replayed IN requests skip the RXRDYC in pipe0_start_setup and keep the packet parked until the edpt0_xfer(DATA IN) arm acks it (before loading the shared FIFO), so the stale pass sees RXRDY+parked instead of csrl==0. The normal IDLE path is unchanged - master never re-entered these windows because the single SETUP edge was always consumed by the pass that parked it; the deferral is what introduced a pending second pass. Review follow-up for #3643 (dcd_musb.c l.516 finding). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-13dcd/musb: fix deferred-SETUP replay racing usbd's status callhathach
STATUS_OUT_PENDING conflated "edpt0_xfer(STATUS OUT) called, awaiting confirm IRQ" with "confirm IRQ seen, awaiting edpt0_xfer". The deferral path completed the status and replayed the saved SETUP from the ISR in both flavors; in the IRQ-first one, usbd's still- outstanding edpt0_xfer(STATUS OUT) for the old transfer (queued via status_stage_xact) then landed in the replayed transfer's state and corrupted it: NULL pipe0.buf armed plus RXRDYC, so the host's next DATA OUT drained through a NULL pointer. usbd processes EP0 XFER_COMPLETE events unconditionally, so nothing downstream defuses it. Split the state into STATUS_OUT_PENDING_XFER / _IRQ. The deferral completes and replays only in PENDING_XFER (old transfer already retired); in PENDING_IRQ it only holds the SETUP and the usbd-driven edpt0_xfer fires the completion and replays. The DATA_IN deferral now synthesizes PENDING_IRQ (its remain==0 invariant asserted: a SETUP before DataEnd raises SetupEnd instead), which also makes the old deferred-promotion in the csrl==0 DATA_IN case unreachable - dropped. Assert the drain buffer before the DATA OUT FIFO read as a cheap backstop for this corruption class. Review follow-up for #3643 (dcd_musb.c l.503 finding). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-13dcd/musb: check SentStall/SetupEnd before DATAEND guardhathach
MUSBMHDRC 21.1.5 requires the EP0 service routine to check SentStall and SetupEnd first; the early DATAEND return ran before both, and SentStall is most likely to fire exactly while DataEnd may still read back set (auto-STALL after DataEnd, 21.1.7), which would skip the recovery. The guard also moves below the RXRDY block so a coalesced DATAEND|RXRDY read cannot swallow a SETUP on cores where the CPU-set-only DataEnd bit reads back 1; the comment documents the vendor-dependent read-back. Review follow-up for #3643 (dcd_musb.c l.445 finding). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-13dcd/musb: replace deferral goto with per-state handlinghathach
The goto jumped into the csrl==0 completion switch with RXRDY still set, making its "When CSRL0 is zero" guard comment untrue on that path. Handle each deferral state in a self-contained switch instead; the csrl==0 switch is now only reached with csrl==0 and its comment is truthful again. Behavior unchanged. Review follow-up for #3643 (dcd_musb.c l.523 finding). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-13dcd/musb: restore EP0 OUT RXRDY flow-control commenthathach
The pre-existing comment explaining why the OUT branch does not ack RxPktRdy was dropped when the SETUP handling moved into pipe0_start_setup(). It is load-bearing: acking before edpt0_xfer() arms the drain buffer would let the host send data with nowhere to put it. Restore it with the databook-deviation rationale so the branches don't get "unified" later. Review follow-up for #3643 (dcd_musb.c l.116 finding). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-13dcd/musb: extract pipe0_read_setup() helperhathach
The 8-byte EP0 SETUP drain (count0 assert + two FIFO word reads via a union) was duplicated verbatim between the IDLE case and the deferral case; a future fix applied to one copy but not the other would only show up on the rare deferred-race path. Share one helper. count0 is now read inside the only remaining user (DATA OUT drain). Review follow-up for #3643 (dcd_musb.c l.507 finding). Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-11Merge remote-tracking branch 'origin/master' into musb_ep0_racehathach
# Conflicts: # test/hil/hil_test.py
2026-06-11Merge remote-tracking branch 'origin/master' into stm32c5hathach
# Conflicts: # README.rst
2026-06-11Fix stm32f723disco host/cdc_msc_hid HIL: UART RX starvation + DWC2 DMA ↵Ha Thach
split-IN NAK storm (#3677) Fix stm32f723disco host HIL: UART RX starvation + DWC2 split bulk NAK/XactErr handling (#3677) stm32f7 BSP — UART RX starvation - The host console USART shared interrupt priority with the USB OTG ISR, so a long OTG interrupt could starve RXNE and drop received bytes. Raise the USART RX IRQ above OTG_FS/OTG_HS in both the bare-metal and FreeRTOS init paths, guarded by #ifdef UART_ID so boards without a UART console keep the default OTG priority. dwc2 host — split NAK/XactErr handling - Slave mode: a persistently-NAKing split bulk/control IN poll re-armed the start-split immediately, storming the ISR and starving task context. Throttle by disabling the channel and re-arming on the resulting halt (no frame deferral). - Buffer-DMA mode: a pure split bulk-OUT NAK was unhandled, leaving the channel halted and stalling the transfer — the dominant cause of CDC echo truncation. Handle it by rewinding the buffer pointers and retrying the start-split (Programming Guide v4.20a 5.1.4.2). - Buffer-DMA mode: a split bulk-OUT XactErr was retried immediately, exhausting HCD_XFER_ERROR_MAX before the transient cleared. Throttle via channel_disable + re-arm to give the hub TT a recovery gap, mirroring slave mode. - All three are scoped to split transfers (hcsplt.split_en); non-split NAK/XactErr keep the core-handled / immediate-retry behavior. The OUT XactErr throttle also excludes periodic split, where channel_disable() is a no-op and would wedge the channel. The nak_disabled flag is generalized to retry_disabled and honors xfer->closing so an endpoint close during a throttled retry tears down cleanly. Verified on stm32f723disco HIL (slave + CFG_TUH_DWC2_DMA_ENABLE): host/cdc_msc_hid, msc_file_explorer, and device_info all pass on both variants; DMA CDC echo went from ~15-25% raw failure to 10/10 clean.
2026-06-04dwc2: cleanup setup_packet pointer cast (review feedback)hathach
Cast DOEPDMA0 through uintptr_t and use sizeof(tusb_control_request_t) instead of the magic constant 8, matching project convention. Add a reference to Programming Guide v4.20a 9.1.2.1 for the DOEPDMAn-8 rule. Addresses Copilot review comment; no functional change. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-04Update setup buffer size definition based on DMA configurationhathach
2026-06-04Merge branch 'master' into dwc2_postfixhathach
2026-06-03dwc2: address Copilot review (comment grammar/typo, tinyusb.json f407 dedup)hathach
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-03dwc2: remove investigation debug logginghathach
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-03dwc2: submit setup packet on SETUP_DONE and drop spurious EP0 RX_COMPLETE on ↵hathach
core v3.10a (STM32L476) DWC2 core rev 3.10a pushes an extra EP0 RX_COMPLETE (RXFLVL PKTSTS 0x3) that is not a real OUT data completion, in two cases flagged on DOEPINT: - STPKTRX (Setup Packet Received): between SETUP_RX and SETUP_DONE - STSPHSRX (Status Phase Received, control write): after the OUT data stage when the host starts the IN status phase
2026-06-02dcd/dwc2: fix back-to-back SETUP reception in DMA modeHiFiPhile
Signed-off-by: HiFiPhile <[email protected]>
2026-05-29dwc2: process IN EP before OUTHiFiPhile
To avoid STATUS IN completion of previous control transfer treated as next DATA IN when IRQ latency is high. Signed-off-by: HiFiPhile <[email protected]>
2026-05-29Merge remote-tracking branch 'tinyusb/master' into fix/Dwc2Stm32U5HiFiPhile
2026-05-29dwc2: move OUT transfer management into RXFLVL IRQHiFiPhile
- GRXSTSP register has internal FIFO, receiving events won't mix up (STATUS OUT & next SETUP) - Improve efficiency, remove 2nd IRQ overhead Signed-off-by: HiFiPhile <[email protected]>
2026-05-27dwc2: fix EP0 DMA setup race conditionHiFiPhile
Signed-off-by: HiFiPhile <[email protected]>
2026-05-27dwc2: simplify EP0 ZLP handlingHiFiPhile
Signed-off-by: HiFiPhile <[email protected]>
2026-05-26ch32_usbhs: fix endpoint stall length index and clear-stall responseJie Feng
Fix issue in the stall handling: - dcd_edpt_stall() for an IN endpoint cleared EP_TX_LEN(0) instead of EP_TX_LEN(ep_num), clobbering endpoint 0's transmit length register when stalling any other IN endpoint. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-05-25optimize interrupt handling timeHiFiPhile
Signed-off-by: HiFiPhile <[email protected]>