diff options
| author | HiFiPHile <[email protected]> | 2026-09-02 16:18:44 +0200 |
|---|---|---|
| committer | HiFiPHile <[email protected]> | 2026-09-02 16:18:44 +0200 |
| commit | e461c6f9c139a0012ef01d53db1aab1c68789b56 (patch) | |
| tree | a0139e6458fc3d5d13670920ee9529cc0a9349d5 | |
| parent | 14060950b487f931d959699c42b0875c96ca6a01 (diff) | |
fix(dwc2): bound periodic intervals to HFNUM range
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.
| -rw-r--r-- | src/portable/synopsys/dwc2/hcd_dwc2.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 2055b320b..5a171f80e 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -44,7 +44,8 @@ enum { enum { HCD_XFER_PERIOD_SPLIT_NYET_MAX = 3, - HCD_FRAME_NUMBER_MASK = 0x3fff + HCD_FRAME_NUMBER_MASK = 0x3fff, + HCD_FRAME_COUNT = HCD_FRAME_NUMBER_MASK + 1 }; //-------------------------------------------------------------------- @@ -652,6 +653,13 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* break; } + if (channel_is_periodic(edpt->hcchar)) { + // HFNUM cannot distinguish elapsed periods longer than one counter cycle. USB permits the host to provide a + // shorter period, so bound the selected period to the history available from HFNUM. + const uint32_t ucount = (rh_speed == TUSB_SPEED_HIGH) ? 1u : 8u; + edpt->uframe_interval = tu_min32(edpt->uframe_interval, HCD_FRAME_COUNT * ucount); + } + return true; } |
