summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2022-06-17 22:12:33 +0800
committersakumisu <[email protected]>2022-06-17 22:13:18 +0800
commit268054a98ce1cef90d82aa20e8a9829df8b5e4bf (patch)
tree8d8fac4902c5991bb7e9f0bbe1efacb16a11d06b
parent22ad2d471cf281eb89c373c7862f542d3695a99b (diff)
update dwc2 intr transfer
-rw-r--r--port/dwc2/usb_hc_dwc2.c76
1 files changed, 45 insertions, 31 deletions
diff --git a/port/dwc2/usb_hc_dwc2.c b/port/dwc2/usb_hc_dwc2.c
index a3a4c62e..fe96ba6a 100644
--- a/port/dwc2/usb_hc_dwc2.c
+++ b/port/dwc2/usb_hc_dwc2.c
@@ -193,7 +193,7 @@ static void dwc2_pipe_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uin
// }
break;
case USB_ENDPOINT_TYPE_INTERRUPT:
- regval |= USB_OTG_HCINTMSK_FRMORM | USB_OTG_HCINTMSK_NAKM;
+ regval |= USB_OTG_HCINTMSK_FRMORM;
break;
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
regval |= USB_OTG_HCINTMSK_FRMORM;
@@ -905,6 +905,7 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
struct dwc2_pipe *chan;
int chidx;
int ret;
+ uint32_t wait_ms_count = 0;
chan = (struct dwc2_pipe *)ep;
@@ -920,8 +921,21 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
chidx = chan->chidx;
chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen);
- dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid);
- ret = dwc2_pipe_wait(chan, timeout);
+
+ while (1) {
+ wait_ms_count++;
+ dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid);
+ usb_osal_msleep(chan->ep_interval);
+ if (chan->result != -EBUSY) {
+ break;
+ }
+ if ((wait_ms_count * chan->ep_interval) > timeout) {
+ ret = -ETIMEDOUT;
+ goto error_out;
+ }
+ }
+
+ ret = dwc2_pipe_wait(chan, 0);
if (ret < 0) {
goto error_out;
}
@@ -963,30 +977,7 @@ error_out:
int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg)
{
- struct dwc2_pipe *chan;
- int chidx;
- int ret;
-
- chan = (struct dwc2_pipe *)ep;
-
- ret = usb_osal_mutex_take(chan->exclsem);
- if (ret < 0) {
- return ret;
- }
-
- ret = dwc2_pipe_asynchsetup(chan, callback, arg);
- if (ret < 0) {
- goto error_out;
- }
-
- chidx = chan->chidx;
- chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen);
- dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid);
-
- return 0;
-error_out:
- usb_osal_mutex_give(chan->exclsem);
- return ret;
+ return -1;
}
int usb_ep_cancel(usbh_epinfo_t ep)
@@ -1091,10 +1082,12 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
chan = &g_dwc2_hcd.chan[ch_num];
if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) {
- CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
- dwc2_halt(ch_num);
chan->result = 0;
+
USB_UNMASK_HALT_HC_INT(ch_num);
+ dwc2_halt(ch_num);
+ CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
+ CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
} else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) {
USB_UNMASK_HALT_HC_INT(ch_num);
chan->result = -EIO;
@@ -1104,6 +1097,7 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
dwc2_halt(ch_num);
chan->result = -EPERM;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
+ CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
} else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) {
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
@@ -1135,6 +1129,7 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
USB_UNMASK_HALT_HC_INT(ch_num);
dwc2_halt(ch_num);
chan->result = -EIO;
+ CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
} else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) {
USB_MASK_HALT_HC_INT(ch_num);
@@ -1154,8 +1149,17 @@ static void dwc2_inchan_irq_handler(uint8_t ch_num)
}
}
chan->result = 0;
+ dwc2_pipe_wakeup(chan);
+ } else if (chan->result == -EAGAIN) {
+ /* re-activate the channel */
+ uint32_t tmpreg = USB_OTG_HC(ch_num)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USB_OTG_HC(ch_num)->HCCHAR = tmpreg;
+ } else {
+ dwc2_pipe_wakeup(chan);
}
- dwc2_pipe_wakeup(chan);
+
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
}
}
@@ -1216,6 +1220,7 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
dwc2_halt(ch_num);
chan->result = -EIO;
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
+ CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
} else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) {
USB_MASK_HALT_HC_INT(ch_num);
@@ -1237,8 +1242,17 @@ static void dwc2_outchan_irq_handler(uint8_t ch_num)
}
}
chan->result = 0;
+ dwc2_pipe_wakeup(chan);
+ } else if (chan->result == -EAGAIN) {
+ /* re-activate the channel */
+ uint32_t tmpreg = USB_OTG_HC(ch_num)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USB_OTG_HC(ch_num)->HCCHAR = tmpreg;
+ } else {
+ dwc2_pipe_wakeup(chan);
}
- dwc2_pipe_wakeup(chan);
+
CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
}
}