| Age | Commit message (Collapse) | Author |
|
Mark active close and abort operations on both the endpoint and host channel before requesting a halt. Channel, RX FIFO, and Tx FIFO interrupt paths then discard work until Channel Halted retires the transfer, so split ACK/NYET handling cannot re-arm a channel that software is closing.
Serialize the state transition with GAHBCFG.GINT. This keeps a parked low-speed channel atomic with the one-transaction-per-frame SOF scheduler without freeing and reallocating the ESP32 interrupt handler. Slave mode temporarily restores controller interrupts while waiting for halt-request queue space; periodic DMA channels remain owned until their natural halt.
|
|
Handle the ESP32-S2/S3 DWC2 low-speed preamble limitation by scheduling affected channels from SOF and limiting each activation to one packet.
Signed-off-by: HiFiPHile <[email protected]>
|
|
|
|
|
|
enum_full_complete() already closes the failed device (from #3815).
Nothing retries the root port itself: the host then sits idle until
reboot. Re-post the attach up to USBH_ENUM_ROOT_RETRY_MAX times while
the port still reports a connection.
The budget is per port and given back when the attachment ends, including
when an attach event tears down an in-flight enumeration. tuh_umount_cb()
is only called for a device that reached tuh_mounted().
Co-authored-by: Cursor <[email protected]>
|
|
A remove for hub_addr = 0, hub_port = 0 covers everything below the root
port, but process_remove_event() only closed dev0 when the event named
the exact bus address it was enumerating on. Mid-enumeration behind a
downstream hub then left enumerating_daddr at 0 and deferred every later
attach.
Co-authored-by: Cursor <[email protected]>
|
|
HFNUM retains only 16384 host-frame positions, while valid periodic endpoint intervals can be longer. Resubmission after the counter wraps can therefore alias the elapsed time and skip the next established service phase.
Cap the host-selected interval to one HFNUM cycle using the root-port frame unit. USB permits a shorter host-provided period, and the bounded interval keeps phase calculation unambiguous for native and split endpoints.
|
|
Periodic DMA channels use their natural service-boundary halt instead of a software CHDIS request. Keep the endpoint busy after an abort so a replacement transfer cannot reuse its state or buffer while the channel remains active.
When HCINT.HALTED arrives, release the channel without reporting completion for the aborted transfer. If endpoint closure is also pending, release the endpoint from the same halt path.
|
|
agent/fix-dwc2-host-fifo-allocation
|
|
A disconnect can close endpoint zero after an enumeration control stage completes but before USBH submits the next stage or request. HCD submission then legitimately returns false; treating that result as an invariant violation asserts during rapid replug and can leave enumeration unfinished.
Complete an in-progress control request as failed when its DATA or status stage cannot be submitted. Propagate submission failures from every asynchronous enumeration continuation and finish enumeration through the normal failure cleanup path. This keeps controller teardown races out of assertions without fabricating a successful transfer.
Validated by interrupting enumeration during rapid STM32U5A5 replug tests with DWC2 DMA and slave modes.
|
|
A root-port disconnect invalidates every active transfer. Retire channel and FIFO interrupt sources plus host-channel state in the disconnect ISR using the Linux DWC2 cleanup model instead of reinitializing the core and PHY, which can sleep on STM32 HS PHYs.
Flush posted slave requests, request halts for enabled channels, clear channel interrupt and software ownership, and keep endpoint records closing until USBH processes the remove event. Reject transfer submissions to closing endpoints, preserve fast-replug notification, and re-enable the global host-channel interrupt when a new channel is initialized.
|
|
In slave mode, channel_xfer_start() enabled an OUT channel but left every FIFO write to a later PTXFEMP interrupt. DWC2 creates the request-queue entry only when the packet's final FIFO word is written, so unrelated interrupt work could consume the selected service frame before the transfer was actually queued.
Factor FIFO writes into a capacity-checked helper and write the initial packet while the channel-enable operation is still protected from DWC2 interrupts. Keep FIFO-empty interrupts only for data that does not fit immediately. The protected section never waits for FIFO or request-queue space.
When initial periodic OUT submission is too close to the frame boundary, release the unused channel and defer the still-pending endpoint to the next SOF. Internal retries bypass this initial boundary guard.
A hardware trace showed HCCHAR enabled for frame 0x0378 while the packet's final FIFO word was delayed until frame 0x03ae. The complete five-commit fix set passed 600 seconds in every O0/O2 and slave/DMA mode.
Signed-off-by: HiFiPHile <[email protected]>
|
|
Periodic IN and DMA-backed transfers selected ODDFRM before waiting for request-queue space. A DWC2 interrupt could also run between reading HFNUM and writing HCCHAR.CHENA, allowing the selected frame to pass while the transfer still appeared active.
Wait for request-queue capacity with controller interrupts enabled, then mask only GAHBCFG.GINT while sampling HFNUM and enabling a new periodic channel. Record the periodic phase from that same HFNUM sample so a boundary after channel enable cannot shift later interval calculations. The bounded critical section contains no queue wait, callback, disable, or allocation loop. Retries that already selected their frame bypass the new selection step.
Also clear a retained HCCHAR.CHDIS before every channel enable. A halted channel can otherwise be re-enabled as CHENA|CHDIS and wait for a terminal interrupt that never arrives.
Hardware traces captured periodic IN selections at frames 0x3303 and 0x3266 but activation only after 0x330c and 0x3273, respectively.
|
|
A frame-overrun interrupt means the selected periodic service interval has already been missed. Retrying an isochronous transfer after that point cannot deliver the original packet and can leave the class waiting indefinitely for a terminal result.
Enable frame-overrun interrupts for slave periodic channels. Complete isochronous IN and OUT overruns as XFER_RESULT_FAILED in both slave and DMA modes, accounting for bytes already written on OUT. Preserve the existing retry behavior for non-isochronous DMA transfers.
This reports the missed packet honestly through the normal HCD completion path: no fabricated success and no class-level abort workaround.
|
|
DWC2 buffer/external DMA mode automatically halts a periodic channel at its next service boundary. Programming HCCHAR.CHDIS|CHENA for a non-split periodic channel is explicitly disallowed by the controller programming guide, yet channel_disable() skipped that write only for split periodic transfers.
Return without programming channel disable for every periodic DMA channel. Non-periodic DMA and slave-mode channels retain the existing explicit-disable path.
The previous path reproduced after 420 seconds in O2/DMA with a closing capture transfer left INVALID while HCCHAR retained CHENA|CHDIS and HCINT was clear.
|
|
Slave-mode channel handlers process one interrupt cause per pass, but the dispatcher acknowledged every HCINT bit before invoking them. When ChHltd arrived together with another cause, the handler consumed the other cause and the halt was lost. A subsequent disable could then leave CHENA|CHDIS asserted with HCINT and HAINT clear, so the submitted periodic transfer never completed.
When a slave channel reports ChHltd with another cause, acknowledge only the non-halt causes and leave ChHltd pending for the next channel-IRQ pass. DMA handlers retain their existing combined-cause behavior.
The uninstrumented negative capture reproduced the lost terminal state with HCCHAR=0xe044881c, HCTSIZ=0x0008001c, HCINT=0, and XFER_RESULT_INVALID.
|
|
Protect periodic deferral cancellation from the SOF interrupt. Re-enable the host interrupt before disabling an active channel because slave-mode channel disable may wait for request-queue space.
|
|
agent/fix-dwc2-host-fifo-allocation
|
|
Popping an IN transfer-completion entry from GRXSTSP asserts HCINT.XferCompl. Drain the receive FIFO first, then read the live masked global status so the newly asserted channel completion is handled without waiting for another interrupt.
|
|
|
|
Anchor resubmitted periodic transfers to the endpoint service interval and defer early submissions through SOF. This prevents callback latency from shifting the cadence or causing intervals to be skipped, while keeping pending transfers abortable.
Signed-off-by: HiFiPHile <[email protected]>
|
|
Fix DWC2 DMA data toggle mismatch in IN-transfers
|
|
bound endpoint number in tu_bind_driver_to_ep_itf
|
|
tu_bind_driver_to_ep_itf() now returns false when ep_num >= CFG_TUH_ENDPOINT_MAX, but the host caller ignores that result and continues enumeration. Configurations such as host/bare_api set the limit to 8, while valid USB devices may use endpoints 8–15. A recognized class can therefore continue and later index ep_status[epnum] or ep2drv[epnum] out of bounds. Wrap this call in TU_ASSERT(...), as the device path already does, so parsing fails immediately.
Signed-off-by: HiFiPHile <[email protected]>
|
|
|
|
|
|
disconnected->connected or connected->disconnected
|
|
|
|
The core has already halted a periodic IN channel when every packet completes. Report the transfer at that point instead of requesting another halt interrupt, allowing the next service interval to be queued without delay.
Signed-off-by: HiFiPHile <[email protected]>
|
|
Isochronous endpoints do not use the normal data-toggle sequence. Avoid saving or advancing HCTSIZ PID state on completion and retry so later transfers cannot be submitted with an invalid toggled PID.
Signed-off-by: HiFiPHile <[email protected]>
|
|
vendor_host.c/.h implemented a CFG_TUH_VENDOR class driver that no example, board
or test ever enabled: usbh's driver table entry was compiled out everywhere, and
the six tusb_config.h files that mentioned the macro all set it to 0. Maintainer
call - dead code, not a shrinking of supported classes.
Removes the sources, the usbh driver-table entry, the CFG_TUH_VENDOR default in
tusb_option.h, the tusb.h include, both build-system source lists, the rp2040
family.cmake entry and the IAR project template rows.
|
|
dcd(ci_hs): stage the device address before priming the status stage
|
|
IMXRT1060RM 42.7.23 and UM10503 Table 478 both ask for the DEVICEADDR write
with USBADRA=1 to happen after the SET_ADDRESS data phase and before the
prime of the status stage, so the controller loads USBADR from its holding
register when the status stage is ACKed. The driver did it the other way
round, leaving a window between the ENDPTPRIME store and the DEVICEADDR
store: an IN answered inside that window ACKs with USBADRA still 0, so the
holding register is never consulted and the device keeps answering on
address 0 while the host has moved to the new one. Instruction timing alone
cannot open that window, but dcd_set_address() runs in task context, so any
interrupt landing between the two stores stretches it past a microframe.
Hardware discards a staged address on a SETUP or OUT to endpoint 0 and
zeroes USBADR on a bus reset, which covers a superseded SET_ADDRESS. What
it cannot cover is a SETUP latched before this write and still unconsumed
after the full CI_HS_BUSY_SPIN spin, which refuses the prime: condition 2
already fired for that earlier SETUP, so the stage would survive and load
USBADR on the next EP0 IN ACK of an unrelated transfer. USB 2.0 9.4.6 is
explicit that "the USB device does not change its device address until
after the Status stage of this request is completed successfully", so the
refused-prime path restores the previous USBADR rather than leaving a stage
armed. Restoring the previous value rather than writing zero keeps 9.4.6's
Address-state row correct, where a device already at a non-zero address
must stay there; on Linux that write is always a no-op, since hub_set_address
only issues SET_ADDRESS from USB_STATE_DEFAULT.
Cast dev_addr before the shift: it is uint8_t, promoted to int, so an
address of 64 or more reached the sign bit of a 32-bit int.
No errata applies: IMXRT1060CE_A Rev 1.3 lists only ERR050101 and ERR010661
for USB, IMXRT1060CE_B Rev 1.1 only ERR010661.
Validated on mimxrt1064_evk: 18/19 device+host tests, 6x usbtest 30/30, and
a 100-iteration forced re-enumeration A/B that is clean on both this change
and its parent (0/100 each). All 19 ci_hs boards build; unit tests 63/63;
PVS drops one diagnostic (the sign-bit shift) and adds none.
|
|
ohci: fix double allocation of dummy TDs in gtd_find_free
|
|
|
|
UAC2: Add more terminal types
|
|
|
|
ERR050101: while an isochronous IN endpoint is active, an IN token addressed to
that same endpoint number on ANOTHER device sharing the host can silently
unprime one of this device's OUT endpoints - control, bulk, interrupt or
isochronous alike. NXP states it cannot be detected by software and raises no
interrupt, so the endpoint simply stops answering and the transfer never
completes.
The workaround is a uniqueness requirement rather than a particular number: the
isochronous IN endpoint must not share its number with any IN endpoint in use on
the bus. One family-wide constant therefore defeats it, since two affected
boards on the same hub then pick the same number and each becomes the other's
aggressor. CFG_TUSB_MIMXRT1XXX_ERRATA_ERR050101 is set only for the parts whose
errata list it - RT1015, RT1020, RT1024 and RT1050, where it is marked no fix
scheduled, plus RT1060 and RT1064 rev A - so RT1010 and the RT11xx family keep
the ordinary number and cannot collide with an affected board beside them.
Several affected boards on one hub can still be given distinct numbers with
-DEPNUM_ISO_IN.
The guard covers every example that has an isochronous IN endpoint: audio_test,
audio_4_channel_mic, uac2_headset, cdc_uac2, usbtest, video_capture and
video_capture_2ch. The video examples move the endpoint only when streaming
isochronously, since the bulk configuration is unaffected, and video_capture_2ch
takes two numbers because it has two streams.
The macro name follows CFG_TUSB_RP2_ERRATA_E2/E4/E15 already in tree, and its
is fixed, and which cannot be told apart at compile time - a way to define it to
0.
device_issues.rst records ERR050101 against every affected part with a link to
each errata sheet, and adds the LPC55S2x USB.3 speed-detection and USB.5
isochronous IN entries, neither of which TinyUSB works around. The branch's
design notes are included under docs/superpowers.
Verified: 340 wedge-free runs on mimxrt1064_evk, which previously wedged within
hours, and the macro resolving to endpoint 0x87 on mimxrt1064_evk against 0x83
on mimxrt1010_evk and stm32f407disco.
|
|
DEVCMDSTAT mixes read/write fields with write-1-to-clear latches, so a blind
read-modify-write writes a pending latch back as a one and silently clears it -
a setup consumed that way strands EP0. Mask the latches on every update.
The setup path follows the manual's order: acknowledge the latch, then read the
payload. The EP0 IN interrupt is cleared along with EP0 OUT, as the control
endpoint flowchart requires - a control IN completion latched before the setup
must not reach usbd after it, where it would be applied to the request the setup
just started and arm its status stage early.
The payload is copied a byte at a time out of a buffer now declared volatile:
the controller DMAs a new setup packet into it as soon as the latch is cleared,
and C orders volatile accesses only against each other, so gcc sinks a plain
memcpy below the guard read that follows at -O2 and -O3 - leaving only -Os, the
level CI builds, correct.
|
|
A refused transfer is a recoverable condition - a new setup superseding a
control response, for instance - rather than a bug, but every failure path
treated it as one. TU_ASSERT carries TU_BREAKPOINT, which is gated on a debugger
being attached rather than on CFG_TUSB_DEBUG, so on a rig where a probe is
always attached it halted the CPU even in release builds. Use TU_VERIFY on the
control transfer paths, including the multi-packet data stage continuation, and
drop the breakpoint from the endpoint transfer failure arm, which already marks
the endpoint ready again so the next transfer can proceed.
The result of usbd_control_xfer_cb() was separately dropped on the floor,
leaving EP0 neither armed nor stalled and nothing recorded. It is logged now,
and deliberately not stalled: a DCD refuses an EP0 prime when a newer setup is
already latched, and EP0 stalls are cleared by hardware when that setup arrives,
so a stall issued here would land after the auto-clear and stall the transfer
that superseded this one. The pending setup re-drives EP0 by itself.
|
|
A bus reset was detected only from the port change that ends it, which is late:
the manual asks the DCD to clear the endpoint semaphores, cancel every prime and
free the dTDs while the reset is still being driven. Enable the reset interrupt
and do all of that there, in the manual's order (IMXRT1060RM 42.5.6.2.1,
p.2394), including the two steps that were missing - confirming the port is
still being reset, and freeing the dTDs. A failed check means the cleanup
arrived late and the controller may be in an undefined state, so the manual's
remedy is carried out rather than noted: a controller reset, followed by the
full re-initialisation it then requires, since the reset detaches the device.
The port change that ends the reset is left with what the manual gives it, the
negotiated speed, which the new BUS_RESET_END event carries. A port change is
classified by the interrupt that preceded it: a suspend raises no port change of
its own, the resume that ends it does.
Every unbounded register spin is now bounded. They waited on bits the hardware
clears within a frame, but each could hang an interrupt handler outright on a
controller that had stopped responding. The endpoint flush follows all three
steps of IMXRT1060RM 42.5.6.6.5 (p.2413), repeating a flush the controller
refuses while a packet is in progress - previously reported as success.
EP0 setup handling is hardened alongside: the payload is copied out of the queue
head through the volatile qualifier before ENDPTSETUPSTAT is cleared, since that
clear releases the setup lockout and a back-to-back setup can overwrite the
buffer immediately after, and C orders volatile accesses only against each
other, so a plain memcpy may legally be sunk past the store.
There is deliberately no unplug detection. IMXRT1060RM 42.7.31 (p.2470) states a
zero Current Connect Status means the device "did not attach successfully or was
forcibly disconnected by the software writing a zero to the Run bit ... It does
not state the device being disconnected or suspended", so a cable pull raises no
port change at all; VBUS via OTGSC is the manual's disconnect indicator and is
board dependent.
Verified on mimxrt1064_evk: 30 forced bus resets each re-enumerating at high
speed with no descriptor errors, plus repeated full usbtest batteries at 30/30
across the series.
|
|
A driver that can see reset signalling begin has no way to say so: the only
event carries the negotiated speed, which does not exist until the reset
ends. On ChipIdea that left the stack believing it was still configured for
the whole reset window - 3 ms at minimum, tens of milliseconds in practice -
while the controller had already torn its endpoints down, so a class driver
writing in that window primed a disabled endpoint over a zeroed queue head.
Add DCD_EVENT_BUS_RESET_START for the leading edge and rename the existing
event to DCD_EVENT_BUS_RESET_END, keeping DCD_EVENT_BUS_RESET as an alias.
START is optional and END stays self-sufficient, so every other driver and
the unit tests are untouched.
|
|
This adds more standard terminal types that can
be used in descriptors to improve end user experience
when operating system can present more acurate
image for audio device terminal.
Signed-off-by: Jerzy Kasenberg <[email protected]>
|
|
|
|
Fix HFP HIL reliability issue
|
|
|
|
Replace the duplicated per-MCU dispatch in dcd_init/hcd_init and the two
helper flavors (USB_Type access on iMX RT, raw offset 0x90 on LPC18/43)
with one SBUSCFG register field plus a per-header CI_HS_SET_AHB_BURST()
hook, compiled only where defined. The LPC USB0-only policy is now
visible at the macro definition.
|
|
midi2 device: complete the UMP stream discovery responder
|
|
clamp committed video payload size to streaming ep buffer
|
|
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Signed-off-by: HiFiPhile <[email protected]>
|