From f7f80e844ce7d3a38554609a11b8c16bb383ec21 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 31 Oct 2024 23:00:19 +0700 Subject: [PATCH] do ping for slave out when nak/nyet --- src/portable/synopsys/dwc2/dwc2_type.h | 1 + src/portable/synopsys/dwc2/hcd_dwc2.c | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 342a4cb2d..89561a5e6 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -434,6 +434,7 @@ typedef struct TU_ATTR_PACKED { uint32_t xfer_size : 19; // 0..18 Transfer size in bytes uint32_t packet_count : 10; // 19..28 Number of packets uint32_t pid : 2; // 29..30 Packet ID + uint32_t do_ping : 1; // 31 Do PING } dwc2_channel_tsize_t; TU_VERIFY_STATIC(sizeof(dwc2_channel_tsize_t) == 4, "incorrect size"); diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 3b2721869..a1666b8d0 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -67,16 +67,21 @@ typedef struct { dwc2_channel_split_t hcsplt_bm; }; + uint8_t is_hs_dev; uint8_t next_pid; - // uint8_t resv[3]; + // uint8_t resv[2]; } hcd_endpoint_t; // Additional info for each channel when it is active typedef struct { volatile bool allocated; uint8_t ep_id; // associated edpt - uint8_t err_count; + union TU_ATTR_PACKED { + uint8_t err_count : 7; + uint8_t do_ping : 1; + }; uint8_t result; + uint16_t xferred_bytes; // bytes that accumulate transferred though USB bus for the whole hcd_edpt_xfer(), which can // be composed of multiple channel_start_xfer() (retry with NAK/NYET) uint8_t* buf_start; @@ -180,6 +185,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t edpt_alloc(void) { for (uint32_t i = 0; i < CFG_TUH_DWC2_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; if (edpt->hcchar_bm.enable == 0) { + tu_memclr(edpt, sizeof(hcd_endpoint_t)); edpt->hcchar_bm.enable = 1; return i; } @@ -460,6 +466,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* hcsplt_bm->split_en = 0; edpt->next_pid = HCTSIZ_PID_DATA0; + edpt->is_hs_dev = (devtree_info.speed == TUSB_SPEED_HIGH) ? 1 : 0; return true; } @@ -482,7 +489,12 @@ bool channel_start_xfer(dwc2_regs_t* dwc2, uint8_t ch_id) { // hctsiz: zero length packet still count as 1 const uint16_t packet_count = cal_packet_count(xfer->buf_len, hcchar_bm->ep_size); - channel->hctsiz = (edpt->next_pid << HCTSIZ_PID_Pos) | (packet_count << HCTSIZ_PKTCNT_Pos) | xfer->buf_len; + uint32_t hctsiz = (edpt->next_pid << HCTSIZ_PID_Pos) | (packet_count << HCTSIZ_PKTCNT_Pos) | xfer->buf_len; + if (xfer->do_ping && edpt->is_hs_dev && edpt->next_pid != HCTSIZ_PID_SETUP && hcchar_bm->ep_dir == TUSB_DIR_OUT) { + hctsiz |= HCTSIZ_DOPING; + xfer->do_ping = 0; + } + channel->hctsiz = hctsiz; // pre-calculate next PID based on packet count, adjusted in transfer complete interrupt if short packet if (hcchar_bm->ep_num == 0) { @@ -822,7 +834,8 @@ bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, bool is_period, xfer->result = XFER_RESULT_FAILED; is_done = true; } else { - // Got here due to NAK or NYET (need to do PING for HS) -> Retry transfer + // Got here due to NAK or NYET -> Retry transfer with do PING (for highspeed) + xfer->do_ping = 1; TU_ASSERT(channel_start_xfer(dwc2, ch_id)); } } else if (hcint & HCINT_ACK) {