From b1182de8726db4080a8b1b8b4b57e1667eb81956 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 1 Nov 2024 19:04:32 +0700 Subject: [PATCH] clean up is_period --- src/portable/synopsys/dwc2/hcd_dwc2.c | 97 +++++++++++++++------------ 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 02f6fa54a..960a78ff3 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -66,16 +66,15 @@ typedef struct { uint32_t hcsplt; dwc2_channel_split_t hcsplt_bm; }; - - uint8_t is_hs_dev; uint8_t next_pid; - // uint8_t resv[2]; + uint16_t frame_interval; + uint16_t frame_countdown; } 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 ep_id; union TU_ATTR_PACKED { uint8_t err_count : 7; uint8_t do_ping : 1; @@ -84,8 +83,8 @@ 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) - uint8_t* buf_start; uint16_t buf_len; + uint8_t* buf_start; uint16_t out_fifo_bytes; // bytes written to TX FIFO (may not be transferred on USB bus). } hcd_xfer_t; @@ -133,6 +132,11 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t channel_alloc(dwc2_regs_t* dwc2) { return TUSB_INDEX_INVALID_8; } +// Check if is periodic (interrupt/isochronous) +TU_ATTR_ALWAYS_INLINE static inline bool edpt_is_periodic(uint8_t ep_type) { + return ep_type == HCCHAR_EPTYPE_INTERRUPT || ep_type == HCCHAR_EPTYPE_ISOCHRONOUS; +} + TU_ATTR_ALWAYS_INLINE static inline uint8_t req_queue_avail(const dwc2_regs_t* dwc2, bool is_period) { if (is_period) { return dwc2->hptxsts_bm.req_queue_available; @@ -147,16 +151,17 @@ TU_ATTR_ALWAYS_INLINE static inline void channel_dealloc(dwc2_regs_t* dwc2, uint dwc2->haintmsk &= ~TU_BIT(ch_id); } -TU_ATTR_ALWAYS_INLINE static inline void channel_disable(const dwc2_regs_t* dwc2, dwc2_channel_t* channel, bool is_period) { +TU_ATTR_ALWAYS_INLINE static inline bool channel_disable(const dwc2_regs_t* dwc2, dwc2_channel_t* channel) { // disable also require request queue - TU_ASSERT(req_queue_avail(dwc2, is_period), ); + TU_ASSERT(req_queue_avail(dwc2, edpt_is_periodic(channel->hcchar_bm.ep_type))); channel->hcintmsk |= HCINT_HALTED; channel->hcchar |= HCCHAR_CHDIS | HCCHAR_CHENA; // must set both CHDIS and CHENA + return true; } // attempt to send IN token to receive data -TU_ATTR_ALWAYS_INLINE static inline bool channel_send_in_token(const dwc2_regs_t* dwc2, dwc2_channel_t* channel, bool is_period) { - TU_ASSERT(req_queue_avail(dwc2, is_period)); +TU_ATTR_ALWAYS_INLINE static inline bool channel_send_in_token(const dwc2_regs_t* dwc2, dwc2_channel_t* channel) { + TU_ASSERT(req_queue_avail(dwc2, edpt_is_periodic(channel->hcchar_bm.ep_type))); channel->hcchar |= HCCHAR_CHENA; return true; } @@ -175,10 +180,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t channel_find_enabled(dwc2_regs_t* dw return TUSB_INDEX_INVALID_8; } -// Check if is periodic (interrupt/isochronous) -TU_ATTR_ALWAYS_INLINE static inline bool edpt_is_periodic(uint8_t ep_type) { - return ep_type == HCCHAR_EPTYPE_INTERRUPT || ep_type == HCCHAR_EPTYPE_ISOCHRONOUS; -} // Allocate a new endpoint TU_ATTR_ALWAYS_INLINE static inline uint8_t edpt_alloc(void) { @@ -472,7 +473,15 @@ 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; + if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) { + edpt->frame_interval = 1 << (desc_ep->bInterval - 1); + } else if (desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT) { + if (devtree_info.speed == TUSB_SPEED_HIGH) { + edpt->frame_interval = 1 << (desc_ep->bInterval - 1); + } else { + edpt->frame_interval = desc_ep->bInterval; + } + } return true; } @@ -518,8 +527,12 @@ static bool channel_xfer_start(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); 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; + if (xfer->do_ping && edpt->next_pid != HCTSIZ_PID_SETUP && hcchar_bm->ep_dir == TUSB_DIR_OUT) { + hcd_devtree_info_t devtree_info; + hcd_devtree_get_info(hcchar_bm->dev_addr, &devtree_info); + if (devtree_info.speed == TUSB_SPEED_HIGH) { + hctsiz |= HCTSIZ_DOPING; + } xfer->do_ping = 0; } channel->hctsiz = hctsiz; @@ -534,7 +547,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { // split: TODO support later channel->hcsplt = edpt->hcsplt; - channel->hcint = 0xFFFFFFFF; // clear all interrupts + channel->hcint = 0xFFFFFFFF; // clear all channel interrupts if (dma_host_enabled(dwc2)) { uint32_t hcintmsk = HCINT_HALTED; @@ -544,7 +557,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { channel->hcdma = (uint32_t) xfer->buf_start; if (hcchar_bm->ep_dir == TUSB_DIR_IN) { - channel_send_in_token(dwc2, channel, is_period); + channel_send_in_token(dwc2, channel); } else { channel->hcchar |= HCCHAR_CHENA; } @@ -564,7 +577,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { // IN Token. If we got NAK, we have to re-enable the channel again in the interrupt. Due to the way usbh stack only // call hcd_edpt_xfer() once, we will need to manage de-allocate/re-allocate IN channel dynamically. if (hcchar_bm->ep_dir == TUSB_DIR_IN) { - channel_send_in_token(dwc2, channel, is_period); + channel_send_in_token(dwc2, channel); } else { channel->hcchar |= HCCHAR_CHENA; if (xfer->buf_len > 0) { @@ -612,7 +625,6 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { const uint8_t ep_dir = tu_edpt_dir(ep_addr); const uint8_t ep_id = edpt_find_opened(dev_addr, ep_num, ep_dir); TU_VERIFY(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX); - //hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; // hcd_int_disable(rhport); @@ -620,7 +632,7 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { const uint8_t ch_id = channel_find_enabled(dwc2, dev_addr, ep_num, ep_dir); if (ch_id < 16) { dwc2_channel_t* channel = &dwc2->channel[ch_id]; - channel_disable(dwc2, channel, edpt_is_periodic(channel->hcchar_bm.ep_type)); + channel_disable(dwc2, channel); } // hcd_int_enable(rhport); @@ -685,9 +697,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { edpt->next_pid = cal_next_pid(edpt->next_pid, remain_packets); } else { if (remain_packets) { - // still more packet to send - bool const is_period = edpt_is_periodic(channel->hcchar_bm.ep_type); - channel_send_in_token(dwc2, channel, is_period); + channel_send_in_token(dwc2, channel); // still more packet to send } } break; @@ -711,17 +721,17 @@ static void handle_rxflvl_irq(uint8_t rhport) { } } -static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, bool is_period, uint32_t hcint) { +static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcint) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; bool is_done = false; if (hcint & HCINT_XFER_COMPLETE) { xfer->result = XFER_RESULT_SUCCESS; - channel_disable(dwc2, channel, is_period); + channel_disable(dwc2, channel); channel->hcintmsk &= ~HCINT_ACK; } else if (hcint & (HCINT_XACT_ERR | HCINT_BABBLE_ERR | HCINT_STALL)) { - channel_disable(dwc2, channel, is_period); + channel_disable(dwc2, channel); if (hcint & HCINT_XACT_ERR) { xfer->err_count++; channel->hcintmsk |= HCINT_ACK; @@ -743,14 +753,13 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, bool is_pe xfer->err_count = 0; } else if (hcint & HCINT_NAK) { // NAK received, re-enable channel if request queue is available - channel_send_in_token(dwc2, channel, is_period); + channel_send_in_token(dwc2, channel); } return is_done; } -static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, bool is_period, uint32_t hcint) { - (void) is_period; +static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcint) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; bool is_done = false; @@ -761,11 +770,11 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, bool is_p channel->hcintmsk &= ~HCINT_ACK; } else if (hcint & HCINT_STALL) { xfer->result = XFER_RESULT_STALLED; - channel_disable(dwc2, channel, is_period); + channel_disable(dwc2, channel); } else if (hcint & (HCINT_NAK | HCINT_XACT_ERR | HCINT_NYET)) { // clean up transfer so far, disable and start again later channel_xfer_cleanup(dwc2, ch_id); - channel_disable(dwc2, channel, is_period); + channel_disable(dwc2, channel); if (hcint & HCINT_XACT_ERR) { xfer->err_count++; channel->hcintmsk |= HCINT_ACK; @@ -800,8 +809,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, bool is_p #endif #if CFG_TUH_DWC2_DMA_ENABLE -static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, bool is_period, uint32_t hcint) { - (void) is_period; +static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcint) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; bool is_done = false; @@ -834,13 +842,16 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, bool is_peri } else if (hcint & (HCINT_ACK | HCINT_NAK | HCINT_DATATOGGLE_ERR)) { xfer->err_count = 0; channel->hcintmsk &= ~(HCINT_ACK | HCINT_NAK | HCINT_DATATOGGLE_ERR); + // if (hcint & (HCINT_NAK | HCINT_DATATOGGLE_ERR)) { + // TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,); + // hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; + // } } return is_done; } -static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, bool is_period, uint32_t hcint) { - (void) is_period; +static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcint) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; bool is_done = false; @@ -894,25 +905,27 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_char_t hcchar_bm = channel->hcchar_bm; - const bool is_period = edpt_is_periodic(hcchar_bm.ep_type); uint32_t hcint = channel->hcint; channel->hcint = (hcint & channel->hcintmsk); // clear enabled interrupts bool is_done; if (is_dma) { - // NOTE For DMA This is flow for core with OUT NAK enhancement from v2.71a + #if CFG_TUH_DWC2_DMA_ENABLE if (hcchar_bm.ep_dir == TUSB_DIR_OUT) { - is_done = handle_channel_out_dma(dwc2, ch_id, is_period, hcint); + is_done = handle_channel_out_dma(dwc2, ch_id, hcint); } else { - is_done = handle_channel_in_dma(dwc2, ch_id, is_period, hcint); + is_done = handle_channel_in_dma(dwc2, ch_id, hcint); } + #endif } else { + #if CFG_TUH_DWC2_SLAVE_ENABLE if (hcchar_bm.ep_dir == TUSB_DIR_OUT) { - is_done = handle_channel_out_slave(dwc2, ch_id, is_period, hcint); + is_done = handle_channel_out_slave(dwc2, ch_id, hcint); } else { - is_done = handle_channel_in_slave(dwc2, ch_id, is_period, hcint); + is_done = handle_channel_in_slave(dwc2, ch_id, hcint); } + #endif } if (is_done) {