From 25de49f8f6e8590eb548d4016e030d19166b9fb3 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 7 Feb 2026 18:01:23 +0700 Subject: minor update --- tools/codespell/ignore-words.txt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'tools/codespell') diff --git a/tools/codespell/ignore-words.txt b/tools/codespell/ignore-words.txt index 957cbd86b..5b6e2e98b 100644 --- a/tools/codespell/ignore-words.txt +++ b/tools/codespell/ignore-words.txt @@ -1,14 +1,15 @@ -synopsys -sie -tre -thre -hsi -fro -dout -mot -te attch +busses +dout endianess +fro +hsi +inout +mot pris -busses ser +sie +synopsys +te +thre +tre -- cgit v1.3.1 From e658e2343589d2f37afbf62c0a6766038739b84d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 6 Mar 2026 15:47:19 +0100 Subject: fix CI Signed-off-by: HiFiPhile --- examples/host/bare_api/skip.txt | 1 + examples/host/bare_api/src/main.c | 16 ++++++++-------- examples/host/cdc_msc_hid/skip.txt | 1 + examples/host/cdc_msc_hid_freertos/skip.txt | 1 + examples/host/device_info/skip.txt | 1 + examples/host/hid_controller/skip.txt | 1 + examples/host/midi_rx/skip.txt | 1 + examples/host/msc_file_explorer/skip.txt | 1 + hw/bsp/lpc54/boards/lpcxpresso54114/board.cmake | 6 ++---- hw/bsp/lpc54/boards/lpcxpresso54608/board.cmake | 7 +++++-- hw/bsp/lpc54/boards/lpcxpresso54628/board.cmake | 7 +++++-- hw/bsp/lpc54/iar/LPC54608_flash.icf | 1 - hw/bsp/lpc54/iar/LPC54628_flash.icf | 1 - hw/bsp/lpc55/family.mk | 4 ++-- src/common/tusb_mcu.h | 13 +++++++++---- tools/codespell/ignore-words.txt | 1 + tools/get_deps.py | 2 +- 17 files changed, 40 insertions(+), 25 deletions(-) create mode 100644 examples/host/bare_api/skip.txt create mode 100644 examples/host/cdc_msc_hid/skip.txt create mode 100644 examples/host/device_info/skip.txt create mode 100644 examples/host/hid_controller/skip.txt create mode 100644 examples/host/midi_rx/skip.txt create mode 100644 examples/host/msc_file_explorer/skip.txt (limited to 'tools/codespell') diff --git a/examples/host/bare_api/skip.txt b/examples/host/bare_api/skip.txt new file mode 100644 index 000000000..308796869 --- /dev/null +++ b/examples/host/bare_api/skip.txt @@ -0,0 +1 @@ +board:lpcxpresso54114 diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 87f612588..544f38102 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -384,12 +384,12 @@ static int _count_utf8_bytes(const uint16_t *buf, size_t len) { return (int) total_bytes; } -static void print_utf16(uint16_t *temp_buf, size_t buf_len) { - if ((temp_buf[0] & 0xff) == 0) return;// empty - size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); - size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len); - _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); - ((uint8_t *) temp_buf)[utf8_len] = '\0'; - - printf("%s", (char *) temp_buf); +static void print_utf16(uint16_t *buf, size_t buf_len) { + if ((buf[0] & 0xff) == 0) return;// empty + size_t utf16_len = ((buf[0] & 0xff) - 2) / sizeof(uint16_t); + size_t utf8_len = (size_t) _count_utf8_bytes(buf + 1, utf16_len); + _convert_utf16le_to_utf8(buf + 1, utf16_len, (uint8_t *) buf, sizeof(uint16_t) * buf_len); + ((uint8_t *) buf)[utf8_len] = '\0'; + + printf("%s", (char *) buf); } diff --git a/examples/host/cdc_msc_hid/skip.txt b/examples/host/cdc_msc_hid/skip.txt new file mode 100644 index 000000000..308796869 --- /dev/null +++ b/examples/host/cdc_msc_hid/skip.txt @@ -0,0 +1 @@ +board:lpcxpresso54114 diff --git a/examples/host/cdc_msc_hid_freertos/skip.txt b/examples/host/cdc_msc_hid_freertos/skip.txt index 2ba4438fd..54e7be1ba 100644 --- a/examples/host/cdc_msc_hid_freertos/skip.txt +++ b/examples/host/cdc_msc_hid_freertos/skip.txt @@ -1 +1,2 @@ mcu:RP2040 +board:lpcxpresso54114 diff --git a/examples/host/device_info/skip.txt b/examples/host/device_info/skip.txt new file mode 100644 index 000000000..308796869 --- /dev/null +++ b/examples/host/device_info/skip.txt @@ -0,0 +1 @@ +board:lpcxpresso54114 diff --git a/examples/host/hid_controller/skip.txt b/examples/host/hid_controller/skip.txt new file mode 100644 index 000000000..308796869 --- /dev/null +++ b/examples/host/hid_controller/skip.txt @@ -0,0 +1 @@ +board:lpcxpresso54114 diff --git a/examples/host/midi_rx/skip.txt b/examples/host/midi_rx/skip.txt new file mode 100644 index 000000000..308796869 --- /dev/null +++ b/examples/host/midi_rx/skip.txt @@ -0,0 +1 @@ +board:lpcxpresso54114 diff --git a/examples/host/msc_file_explorer/skip.txt b/examples/host/msc_file_explorer/skip.txt new file mode 100644 index 000000000..308796869 --- /dev/null +++ b/examples/host/msc_file_explorer/skip.txt @@ -0,0 +1 @@ +board:lpcxpresso54114 diff --git a/hw/bsp/lpc54/boards/lpcxpresso54114/board.cmake b/hw/bsp/lpc54/boards/lpcxpresso54114/board.cmake index c0bbeecd5..b306f885a 100644 --- a/hw/bsp/lpc54/boards/lpcxpresso54114/board.cmake +++ b/hw/bsp/lpc54/boards/lpcxpresso54114/board.cmake @@ -6,10 +6,8 @@ set(PYOCD_TARGET LPC54114) set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/LPC54114J256_cm4_flash.ld) -# Device port default to PORT1 Highspeed -if (NOT DEFINED PORT) - set(PORT 1) -endif() +# Only Port 0 Full-Speed +set(RHPORT_DEVICE 0) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/lpc54/boards/lpcxpresso54608/board.cmake b/hw/bsp/lpc54/boards/lpcxpresso54608/board.cmake index f0715fa12..aea608e60 100644 --- a/hw/bsp/lpc54/boards/lpcxpresso54608/board.cmake +++ b/hw/bsp/lpc54/boards/lpcxpresso54608/board.cmake @@ -8,8 +8,11 @@ set(NXPLINK_DEVICE LPC54608:LPCXpresso54608) set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/LPC54608J512_flash.ld) # Device port default to PORT1 Highspeed -if (NOT DEFINED PORT) - set(PORT 1) +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 1) +endif() +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 0) endif() function(update_board TARGET) diff --git a/hw/bsp/lpc54/boards/lpcxpresso54628/board.cmake b/hw/bsp/lpc54/boards/lpcxpresso54628/board.cmake index 1dea6f353..b0d0d404f 100644 --- a/hw/bsp/lpc54/boards/lpcxpresso54628/board.cmake +++ b/hw/bsp/lpc54/boards/lpcxpresso54628/board.cmake @@ -8,8 +8,11 @@ set(NXPLINK_DEVICE LPC54628:LPCXpresso54628) set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/LPC54628J512_flash.ld) # Device port default to PORT1 Highspeed -if (NOT DEFINED PORT) - set(PORT 1) +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 1) +endif() +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 0) endif() function(update_board TARGET) diff --git a/hw/bsp/lpc54/iar/LPC54608_flash.icf b/hw/bsp/lpc54/iar/LPC54608_flash.icf index 2a7885541..408ab90ed 100644 --- a/hw/bsp/lpc54/iar/LPC54608_flash.icf +++ b/hw/bsp/lpc54/iar/LPC54608_flash.icf @@ -82,4 +82,3 @@ place in DATA_region { block RW }; place in DATA_region { block ZI }; place in DATA_region { last block HEAP }; place in CSTACK_region { block CSTACK }; - diff --git a/hw/bsp/lpc54/iar/LPC54628_flash.icf b/hw/bsp/lpc54/iar/LPC54628_flash.icf index 7cca18159..cc6615bd6 100644 --- a/hw/bsp/lpc54/iar/LPC54628_flash.icf +++ b/hw/bsp/lpc54/iar/LPC54628_flash.icf @@ -80,4 +80,3 @@ place in DATA_region { block RW }; place in DATA_region { block ZI }; place in DATA_region { last block HEAP }; place in CSTACK_region { block CSTACK }; - diff --git a/hw/bsp/lpc55/family.mk b/hw/bsp/lpc55/family.mk index 7b1ab6b09..a7d06d70a 100644 --- a/hw/bsp/lpc55/family.mk +++ b/hw/bsp/lpc55/family.mk @@ -2,8 +2,8 @@ UF2_FAMILY_ID = 0x2abc77ec include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m33 -MCUX_DIR = /hw/mcu/nxp/mcuxsdk-core -SDK_DIR = /hw/mcu/nxp/mcux-devices-lpc +MCUX_DIR = hw/mcu/nxp/mcuxsdk-core +SDK_DIR = hw/mcu/nxp/mcux-devices-lpc # Default to Highspeed PORT1 PORT ?= 1 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 0e5233bbe..c4615a87b 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -71,12 +71,17 @@ #define TUP_DCD_ENDPOINT_MAX 5 #elif TU_CHECK_MCU(OPT_MCU_LPC54) + #include "fsl_device_registers.h" + // TODO USB0 has 5, USB1 has 6 #define TUP_USBIP_IP3511 - #define TUP_USBIP_IP3516 - #define TUP_USBIP_OHCI - #define TUP_USBIP_OHCI_NXP - #define TUP_OHCI_RHPORTS 1 // 1 downstream port + + #if !defined(LPC54114_cm4_SERIES) && !defined(LPC54114_cm0plus_SERIES) + #define TUP_USBIP_IP3516 + #define TUP_USBIP_OHCI + #define TUP_USBIP_OHCI_NXP + #define TUP_OHCI_RHPORTS 1 // 1 downstream port + #endif #define TUP_DCD_ENDPOINT_MAX 6 diff --git a/tools/codespell/ignore-words.txt b/tools/codespell/ignore-words.txt index 5b6e2e98b..7ce778fab 100644 --- a/tools/codespell/ignore-words.txt +++ b/tools/codespell/ignore-words.txt @@ -7,6 +7,7 @@ hsi inout mot pris +ptd ser sie synopsys diff --git a/tools/get_deps.py b/tools/get_deps.py index 2f37901c8..bf91428f4 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -66,7 +66,7 @@ deps_optional = { 'lpc51 lpc55 mcx'], 'hw/mcu/nxp/mcux-sdk': ['https://github.com/nxp-mcuxpresso/mcux-sdk', 'a1bdae309a14ec95a4f64a96d3315a4f89c397c6', - 'kinetis_k kinetis_k32l2 kinetis_kl rw61x imxrt'], + 'kinetis_k kinetis_k32l2 kinetis_kl lpc54 rw61x imxrt'], 'hw/mcu/nxp/mcux-devices-lpc': ['https://github.com/nxp-mcuxpresso/mcux-devices-lpc', '8096b783ec09d0d1c8629025a5f9d8e7df26e520', 'lpc51 lpc55'], -- cgit v1.3.1 From dffc57135846a4b00aca06b2f588daa6d13b67ef Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Thu, 11 Jun 2026 10:17:28 +0700 Subject: Fix stm32f723disco host/cdc_msc_hid HIL: UART RX starvation + DWC2 DMA split-IN NAK storm (#3677) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- AGENTS.md | 4 +-- hw/bsp/stm32f7/family.c | 21 +++++++++++---- src/portable/synopsys/dwc2/hcd_dwc2.c | 51 +++++++++++++++++++++++++++++++---- tools/codespell/ignore-words.txt | 1 + 4 files changed, 65 insertions(+), 12 deletions(-) (limited to 'tools/codespell') diff --git a/AGENTS.md b/AGENTS.md index 5c9908d19..93faa6332 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,7 +18,7 @@ Bias toward caution over speed. For trivial tasks, use judgment. - **Language/style:** C99, 2-space indent (no tabs), snake_case helpers, `UPPER_CASE` macros. Public APIs use `tud_`/`tuh_`; macros use `TU_`. Headers self-contained with `#if CFG_TUSB_MCU` guards. - **Safety:** no dynamic allocation; defer ISR work to task context; use `TU_ASSERT()` for error checks; always check return values; include order: C stdlib → tusb common → drivers → classes. - **Layout:** `src/` core, `hw/{mcu,bsp}/` MCU+BSP, `examples/{device,host,dual}/`, `test/{unit-test,fuzz,hil}/`, `docs/`, `tools/`. -- **Commits/PRs:** imperative mood, scoped changes, link issues, include test/build evidence. +- **Commits/PRs:** imperative mood, scoped changes, link issues, include test/build evidence. After opening a PR, monitor it and drive it to green: address automated review comments (Copilot/Codex/Claude) and fix any failing CI builds, pushing follow-up commits until checks pass and review threads are resolved. Useful: `gh pr checks --watch`, `gh pr view --comments`. - **Formatting/lint:** `clang-format` (`.clang-format`), `codespell` (`.codespellrc`), run `pre-commit run --all-files` before submitting. ## Bootstrap @@ -204,7 +204,7 @@ Device examples need real hardware to validate runtime behavior; must at least b ## References -- MCU reference manuals, datasheets, schematics: `$HOME/Documents/Calibre Library`. +- MCU reference manuals, datasheets, schematics: `$HOME/Documents/calibre-library`. - Supported MCUs/boards: `hw/bsp/` and `docs/reference/boards.rst`. - USB classes: `src/class/{cdc,hid,msc,audio,…}/` — each has `*_device.c` and `*_host.c`. - Key files: `src/tusb.h`, `src/tusb_config.h`, `tools/get_deps.py`, `tools/build.py`, `test/unit-test/project.yml`. diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index 7a322591b..9427ac4a6 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -82,8 +82,9 @@ static UART_HandleTypeDef UartHandle = {.Instance = USARTn, .OverSampling = UART_OVERSAMPLING_16, }}; -// RX ring buffer via RXNE interrupt — no HAL IT functions used (avoid HAL state conflicts) -static uint8_t uart_rx_ff_buf[32]; +// RX ring buffer via RXNE interrupt — no HAL IT functions used (avoid HAL state conflicts). +// Sized to absorb a full host-forwarding burst (>64B) when the main loop briefly stalls. +static uint8_t uart_rx_ff_buf[256]; static tu_fifo_t uart_rx_ff; void USARTn_IRQHandler(void) { @@ -142,13 +143,24 @@ void board_init(void) { // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); + // Set UART interrupt higher priority than USB OTG since the F7 USART has no hardware RX FIFO, so a host example's + // UART RX must not be starved by the frequent USB host interrupts or incoming bytes overrun (ORE) and dropped. + NVIC_SetPriority(OTG_FS_IRQn, 1); + NVIC_SetPriority(OTG_HS_IRQn, 1); + #ifdef UART_ID + NVIC_SetPriority(USARTn_IRQn, 0); + #endif + #elif CFG_TUSB_OS == OPT_OS_FREERTOS // Explicitly disable systick to prevent its ISR from running before scheduler start SysTick->CTRL &= ~1U; // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(OTG_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); - NVIC_SetPriority(OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(OTG_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); + NVIC_SetPriority(OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); + #ifdef UART_ID + NVIC_SetPriority(USARTn_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + #endif #endif #ifdef UART_ID @@ -156,7 +168,6 @@ void board_init(void) { HAL_UART_Init(&UartHandle); tu_fifo_config(&uart_rx_ff, uart_rx_ff_buf, sizeof(uart_rx_ff_buf), false); USARTn->CR1 |= USART_CR1_RXNEIE; - NVIC_SetPriority(USARTn_IRQn, (1 << __NVIC_PRIO_BITS) - 1); NVIC_EnableIRQ(USARTn_IRQn); #endif diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 9ea5f33c5..84a0c6afd 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -104,6 +104,7 @@ typedef struct { uint16_t xferred_bytes; // bytes that accumulate transferred though USB bus for the whole hcd_edpt_xfer(), which can // be composed of multiple channel_xfer_start() (retry with NAK/NYET) uint16_t fifo_bytes; // bytes written/read from/to FIFO (may not be transferred on USB bus). + uint8_t retry_disabled; // 1: channel was disabled to throttle a split retry (NAK in / XactErr out); re-arm on its halt } hcd_xfer_t; typedef struct { @@ -1137,7 +1138,16 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci // TU_LOG1("in hcint = %02lX\r\n", hcint); if (hcint & HCINT_HALTED) { - if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL | HCINT_BABBLE_ERR)) { + if (xfer->retry_disabled) { + // Halt from our split-NAK throttle disable (below): re-arm the start-split, or let teardown finish + // if the endpoint is closing. Programming Guide 3.5 "Halting a Channel" (p73). + xfer->retry_disabled = 0; + if (xfer->closing) { + is_done = true; + } else { + channel_send_in_token(dwc2, channel); + } + } else if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL | HCINT_BABBLE_ERR)) { const uint16_t remain_bytes = (uint16_t) hctsiz.xfer_size; const uint16_t remain_packets = hctsiz.packet_count; const uint16_t actual_len = edpt->buflen - remain_bytes; @@ -1203,7 +1213,15 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci channel->hcintmsk &= ~(HCINT_NAK | HCINT_DATATOGGLE_ERR); hcsplt.split_compl = 0; // restart with start-split channel->hcsplt = hcsplt.value; - channel_xfer_in_retry(dwc2, ch_id, hcint); + // Persistent split bulk/control IN NAK (e.g. idle polled endpoint): re-enabling immediately storms + // the ISR and starves the task. Disable + re-arm on the resulting halt to throttle (like the slave + // path); no frame deferral. Programming Guide 3.5 (p73) Note permits disable on NAK/FrmOvrn splits. + if ((hcint & HCINT_NAK) && hcsplt.split_en && !channel_is_periodic(channel->hcchar)) { + xfer->retry_disabled = 1; + channel_disable(dwc2, channel); + } else { + channel_xfer_in_retry(dwc2, ch_id, hcint); + } } else if (hcint & HCINT_FARME_OVERRUN) { // retry start-split in next binterval channel_xfer_in_retry(dwc2, ch_id, hcint); @@ -1228,7 +1246,16 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc // TU_LOG1("out hcint = %02lX\r\n", hcint); if (hcint & HCINT_HALTED) { - if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL)) { + if (xfer->retry_disabled) { + // Halt from our split-XactErr throttle disable (below): re-issue the start-split (pointers already + // rewound), giving the hub TT a recovery gap. Programming Guide 3.5 "Halting a Channel" (p73). + xfer->retry_disabled = 0; + if (xfer->closing) { + is_done = true; + } else { + channel_xfer_start(dwc2, ch_id); + } + } else if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL)) { is_done = true; xfer->err_count = 0; if (hcint & HCINT_XFER_COMPLETE) { @@ -1251,9 +1278,17 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc xfer->result = XFER_RESULT_FAILED; is_done = true; } else { - // clean up transfer so far and start again + // Rewind, then retry the start-split. Non-periodic SPLIT throttles via channel_disable + re-arm on + // the halt (immediate re-fire exhausts the retry budget; the disable gives the hub TT a recovery + // gap, like slave). Periodic split is excluded: channel_disable() is a no-op for it, so the halt + // never fires and the channel would wedge. Non-split re-inits immediately (Programming Guide 5.1.2.3). channel_xfer_out_wrapup(dwc2, ch_id); - channel_xfer_start(dwc2, ch_id); + if (hcsplt.split_en && !channel_is_periodic(channel->hcchar)) { + xfer->retry_disabled = 1; + channel_disable(dwc2, channel); + } else { + channel_xfer_start(dwc2, ch_id); + } } } } else if (hcint & HCINT_NYET) { @@ -1271,6 +1306,12 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc channel->hcsplt = hcsplt.value; channel->hcchar |= HCCHAR_CHENA; } + } else if ((hcint & HCINT_NAK) && hcsplt.split_en) { + // Split OUT NAK: rewind + retry the start-split, else the channel stalls (Programming Guide 5.1.4.2). + // Non-split OUT NAK is core-handled (5.1.2.2), so this is split-only. + xfer->err_count = 0; + channel_xfer_out_wrapup(dwc2, ch_id); + channel_xfer_start(dwc2, ch_id); } if (xfer->closing == 1) { diff --git a/tools/codespell/ignore-words.txt b/tools/codespell/ignore-words.txt index 7ce778fab..0b1aa284a 100644 --- a/tools/codespell/ignore-words.txt +++ b/tools/codespell/ignore-words.txt @@ -6,6 +6,7 @@ fro hsi inout mot +ore pris ptd ser -- cgit v1.3.1