summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2026-08-17 19:04:37 +0700
committerGitHub <[email protected]>2026-08-17 19:04:37 +0700
commit2465ea8f435114af3b3c935cc4fbed423d9eac69 (patch)
treea47ef0f4ecb66ecba5d00e286fc4bf6f067096a9 /src
parent9fb2f9cb3f8e30fa9ca2a32f4cdc6f0fb07a5be3 (diff)
parent8ccd0d549798c66d484e5a4b4c57edf49e8bb097 (diff)
Merge pull request #3790 from hathach/fix/lpc43-hfp-reliability
Fix HFP HIL reliability issue
Diffstat (limited to 'src')
-rw-r--r--src/class/mtp/mtp_device.c18
-rw-r--r--src/portable/chipidea/ci_hs/ci_hs_imxrt.h3
-rw-r--r--src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h5
-rw-r--r--src/portable/chipidea/ci_hs/ci_hs_type.h9
-rw-r--r--src/portable/chipidea/ci_hs/dcd_ci_hs.c4
-rw-r--r--src/portable/chipidea/ci_hs/hcd_ci_hs.c4
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c7
7 files changed, 44 insertions, 6 deletions
diff --git a/src/class/mtp/mtp_device.c b/src/class/mtp/mtp_device.c
index 7657899ec..275c9f858 100644
--- a/src/class/mtp/mtp_device.c
+++ b/src/class/mtp/mtp_device.c
@@ -437,8 +437,11 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
TU_LOG_DRV(" MTP Data %s CB: xferred_bytes=%lu, xferred_len/total_len=%lu/%lu, is_complete=%d\r\n",
is_data_in ? "IN" : "OUT", xferred_bytes, p_mtp->xferred_len, p_mtp->total_len, is_complete ? 1 : 0);
- // Send/queue ZLP if packet is full-sized but transfer is complete
- if (is_complete && xferred_bytes > 0 && !(xferred_bytes & (threshold - 1))) {
+ // Send/queue ZLP if packet is full-sized but transfer is complete.
+ // OUT must deliver this final payload to the application before receiving
+ // its terminating ZLP below.
+ const bool need_zlp = is_complete && xferred_bytes > 0 && !(xferred_bytes & (threshold - 1));
+ if (is_data_in && need_zlp) {
TU_LOG_DRV(" queue ZLP\r\n");
TU_VERIFY(usbd_edpt_claim(p_mtp->rhport, ep_addr));
TU_ASSERT(usbd_edpt_xfer(p_mtp->rhport, ep_addr, NULL, 0, false));
@@ -466,9 +469,16 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
cb_data.io_container = headerless_packet;
cb_data.io_container.payload_bytes = xferred_bytes;
}
- tud_mtp_data_xfer_cb(&cb_data);
+ if (xferred_bytes > 0) {
+ tud_mtp_data_xfer_cb(&cb_data);
+ }
- if (is_complete) {
+ if (need_zlp) {
+ TU_LOG_DRV(" queue ZLP\r\n");
+ TU_VERIFY(usbd_edpt_claim(p_mtp->rhport, ep_addr));
+ TU_ASSERT(usbd_edpt_xfer(p_mtp->rhport, ep_addr, NULL, 0, false));
+ return true;
+ } else if (is_complete) {
// back to header + payload for response
cb_data.io_container = headered_packet;
cb_data.io_container.header->len = sizeof(mtp_container_header_t);
diff --git a/src/portable/chipidea/ci_hs/ci_hs_imxrt.h b/src/portable/chipidea/ci_hs/ci_hs_imxrt.h
index f0f918fe2..8f0d6083e 100644
--- a/src/portable/chipidea/ci_hs/ci_hs_imxrt.h
+++ b/src/portable/chipidea/ci_hs/ci_hs_imxrt.h
@@ -36,6 +36,9 @@ static const ci_hs_controller_t _ci_controller[] =
#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base)
+// NXP recommends AHBBRST = INCR16 (remainder as unspecified-length bursts)
+#define CI_HS_SET_AHB_BURST(_p) (CI_HS_REG(_p)->SBUSCFG = SBUSCFG_AHBBRST_INCR16_UNSPEC)
+
//------------- DCD -------------//
#define CI_DCD_INT_ENABLE(_p) NVIC_EnableIRQ ((IRQn_Type)_ci_controller[_p].irqnum)
#define CI_DCD_INT_DISABLE(_p) NVIC_DisableIRQ((IRQn_Type)_ci_controller[_p].irqnum)
diff --git a/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h b/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h
index f2061bd7a..c7dc7e69f 100644
--- a/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h
+++ b/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h
@@ -34,4 +34,9 @@ static const ci_hs_controller_t _ci_controller[] =
#define CI_HCD_INT_ENABLE(_p) NVIC_EnableIRQ ((IRQn_Type)_ci_controller[_p].irqnum)
#define CI_HCD_INT_DISABLE(_p) NVIC_DisableIRQ((IRQn_Type)_ci_controller[_p].irqnum)
+// USB0 (high-speed) only: NXP recommends AHBBRST = INCR16 (remainder as
+// unspecified-length bursts)
+#define CI_HS_SET_AHB_BURST(_p) \
+ do { if ((_p) == 0) { CI_HS_REG(_p)->SBUSCFG = SBUSCFG_AHBBRST_INCR16_UNSPEC; } } while (0)
+
#endif
diff --git a/src/portable/chipidea/ci_hs/ci_hs_type.h b/src/portable/chipidea/ci_hs/ci_hs_type.h
index 70817a6e3..b209c7545 100644
--- a/src/portable/chipidea/ci_hs/ci_hs_type.h
+++ b/src/portable/chipidea/ci_hs/ci_hs_type.h
@@ -71,11 +71,18 @@ enum {
USBMODE_VBUS_POWER_SELECT = TU_BIT(5), // Need to be enabled for LPC18XX/43XX in host mode
};
+// SBUSCFG
+enum {
+ SBUSCFG_AHBBRST_INCR16_UNSPEC = 7, // INCR16 burst, remainder as unspecified-length bursts
+};
+
// Device Registers
typedef struct
{
//------------- ID + HW Parameter Registers-------------//
- volatile uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX
+ volatile uint32_t TU_RESERVED[36]; ///< ID/HW parameter registers, not used by this driver
+ volatile uint32_t SBUSCFG; ///< System Bus Interface Configuration (not present on every MCU)
+ volatile uint32_t TU_RESERVED[27];
//------------- Capability Registers-------------//
volatile uint8_t CAPLENGTH; ///< Capability Registers Length
diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c
index fa98d6882..8c08c6bd5 100644
--- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c
+++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c
@@ -237,6 +237,10 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) {
usbmode |= USBMODE_CM_DEVICE;
dcd_reg->USBMODE = usbmode;
+ #ifdef CI_HS_SET_AHB_BURST
+ CI_HS_SET_AHB_BURST(rhport);
+ #endif
+
#ifdef CFG_TUD_CI_HS_VBUS_CHARGE
dcd_reg->OTGSC = OTGSC_VBUS_CHARGE | OTGSC_OTG_TERMINATION;
#else
diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c
index 3cb69acfa..0f24f5bb6 100644
--- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c
+++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c
@@ -82,6 +82,10 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) {
hcd_reg->USBMODE = USBMODE_CM_HOST;
#endif
+ #ifdef CI_HS_SET_AHB_BURST
+ CI_HS_SET_AHB_BURST(rhport);
+ #endif
+
#if !TUH_OPT_HIGH_SPEED
hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
#endif
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index 86aa54510..b2f1a93a4 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -1143,7 +1143,12 @@ static void handle_incomplete_iso_in(uint8_t rhport) {
xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN);
if (xfer->iso_retry > 0) {
xfer->iso_retry--;
- // Restart ISO transfe: re-write TSIZ and CTL
+ // Restart ISO transfer: re-write DMA address, TSIZ, and CTL
+ #if CFG_TUD_DWC2_DMA_ENABLE
+ if (dma_device_enabled(dwc2)) {
+ epin->diepdma = (uintptr_t) xfer->buffer;
+ }
+ #endif
dwc2_ep_tsize_t deptsiz = {.value = 0};
deptsiz.xfer_size = xfer->total_len;
deptsiz.packet_count = tu_div_ceil(xfer->total_len, xfer->max_size);