turn off TX FIFO Empty for EPIN if all bytes are written
fix dcd synopsys issue with usbnet #289
This commit is contained in:
parent
83353dd93f
commit
8d18d6077b
|
@ -291,9 +291,10 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
||||||
|
|
||||||
if(dir == TUSB_DIR_OUT)
|
if(dir == TUSB_DIR_OUT)
|
||||||
{
|
{
|
||||||
out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | \
|
out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) |
|
||||||
desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos | \
|
(desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) |
|
||||||
desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos;
|
(desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos);
|
||||||
|
|
||||||
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));
|
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -321,11 +322,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
||||||
// - Offset: GRXFSIZ + 16 + Size*(epnum-1)
|
// - Offset: GRXFSIZ + 16 + Size*(epnum-1)
|
||||||
// - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n".
|
// - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n".
|
||||||
|
|
||||||
in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | \
|
in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) |
|
||||||
epnum << USB_OTG_DIEPCTL_TXFNUM_Pos | \
|
(epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) |
|
||||||
desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos | \
|
(desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) |
|
||||||
(desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | \
|
(desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) |
|
||||||
desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos;
|
(desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos);
|
||||||
|
|
||||||
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum));
|
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum));
|
||||||
|
|
||||||
// Both TXFD and TXSA are in unit of 32-bit words.
|
// Both TXFD and TXSA are in unit of 32-bit words.
|
||||||
|
@ -352,9 +354,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
|
||||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||||
|
|
||||||
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
|
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
|
||||||
xfer->buffer = buffer;
|
xfer->buffer = buffer;
|
||||||
xfer->total_len = total_bytes;
|
xfer->total_len = total_bytes;
|
||||||
xfer->queued_len = 0;
|
xfer->queued_len = 0;
|
||||||
xfer->short_packet = false;
|
xfer->short_packet = false;
|
||||||
|
|
||||||
uint16_t num_packets = (total_bytes / xfer->max_size);
|
uint16_t num_packets = (total_bytes / xfer->max_size);
|
||||||
|
@ -365,21 +367,23 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
|
||||||
num_packets++;
|
num_packets++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IN and OUT endpoint xfers are interrupt-driven, we just schedule them
|
// IN and OUT endpoint xfers are interrupt-driven, we just schedule them here.
|
||||||
// here.
|
|
||||||
if(dir == TUSB_DIR_IN) {
|
if(dir == TUSB_DIR_IN) {
|
||||||
// A full IN transfer (multiple packets, possibly) triggers XFRC.
|
// A full IN transfer (multiple packets, possibly) triggers XFRC.
|
||||||
in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | \
|
in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) |
|
||||||
((total_bytes & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) << USB_OTG_DIEPTSIZ_XFRSIZ_Pos);
|
((total_bytes & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) << USB_OTG_DIEPTSIZ_XFRSIZ_Pos);
|
||||||
|
|
||||||
in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
|
in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
|
||||||
|
|
||||||
// Enable fifo empty interrupt only if there are something to put in the fifo.
|
// Enable fifo empty interrupt only if there are something to put in the fifo.
|
||||||
if(total_bytes != 0) {
|
if(total_bytes != 0) {
|
||||||
dev->DIEPEMPMSK |= (1 << epnum);
|
dev->DIEPEMPMSK |= (1 << epnum);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Each complete packet for OUT xfers triggers XFRC.
|
// Each complete packet for OUT xfers triggers XFRC.
|
||||||
out_ep[epnum].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | \
|
out_ep[epnum].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) |
|
||||||
((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos);
|
((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos);
|
||||||
|
|
||||||
out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,6 +539,7 @@ static void receive_packet(xfer_ctl_t * xfer, /* USB_OTG_OUTEndpointTypeDef * ou
|
||||||
xfer->short_packet = (xfer_size < xfer->max_size);
|
xfer->short_packet = (xfer_size < xfer->max_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write a data packet to EPIN FIFO
|
||||||
static void transmit_packet(xfer_ctl_t * xfer, USB_OTG_INEndpointTypeDef * in_ep, uint8_t fifo_num) {
|
static void transmit_packet(xfer_ctl_t * xfer, USB_OTG_INEndpointTypeDef * in_ep, uint8_t fifo_num) {
|
||||||
usb_fifo_t tx_fifo = FIFO_BASE(fifo_num);
|
usb_fifo_t tx_fifo = FIFO_BASE(fifo_num);
|
||||||
|
|
||||||
|
@ -658,21 +663,30 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy
|
||||||
static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointTypeDef * in_ep) {
|
static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointTypeDef * in_ep) {
|
||||||
// DAINT for a given EP clears when DIEPINTx is cleared.
|
// DAINT for a given EP clears when DIEPINTx is cleared.
|
||||||
// IEPINT will be cleared when DAINT's out bits are cleared.
|
// IEPINT will be cleared when DAINT's out bits are cleared.
|
||||||
for(uint8_t n = 0; n < EP_MAX; n++) {
|
for ( uint8_t n = 0; n < EP_MAX; n++ )
|
||||||
xfer_ctl_t * xfer = XFER_CTL_BASE(n, TUSB_DIR_IN);
|
{
|
||||||
|
xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_IN);
|
||||||
|
|
||||||
if(dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n))) {
|
if ( dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n)) )
|
||||||
|
{
|
||||||
// IN XFER complete (entire xfer).
|
// IN XFER complete (entire xfer).
|
||||||
if(in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC) {
|
if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC )
|
||||||
|
{
|
||||||
in_ep[n].DIEPINT = USB_OTG_DIEPINT_XFRC;
|
in_ep[n].DIEPINT = USB_OTG_DIEPINT_XFRC;
|
||||||
dev->DIEPEMPMSK &= ~(1 << n); // Turn off TXFE b/c xfer inactive.
|
|
||||||
dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
|
dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// XFER FIFO empty
|
// XFER FIFO empty
|
||||||
if(in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE) {
|
if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE )
|
||||||
|
{
|
||||||
in_ep[n].DIEPINT = USB_OTG_DIEPINT_TXFE;
|
in_ep[n].DIEPINT = USB_OTG_DIEPINT_TXFE;
|
||||||
transmit_packet(xfer, &in_ep[n], n);
|
transmit_packet(xfer, &in_ep[n], n);
|
||||||
|
|
||||||
|
// Turn off TXFE if all bytes are written.
|
||||||
|
if (xfer->queued_len == xfer->total_len)
|
||||||
|
{
|
||||||
|
dev->DIEPEMPMSK &= ~(1 << n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue