stm32f4: Refactor IN and OUT endpoint interrupt handling into their own functions.
This commit is contained in:
		@@ -553,6 +553,64 @@ static void read_rx_fifo(USB_OTG_OUTEndpointTypeDef * out_ep) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTypeDef * out_ep) {
 | 
			
		||||
  // DAINT for a given EP clears when DOEPINTx is cleared.
 | 
			
		||||
  // OEPINT will be cleared when DAINT's out bits are cleared.
 | 
			
		||||
  for(int n = 0; n < 4; n++) {
 | 
			
		||||
    xfer_ctl_t * xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT);
 | 
			
		||||
    if(dev->DAINT & (1 << (USB_OTG_DAINT_OEPINT_Pos + n))) {
 | 
			
		||||
      // SETUP packet Setup Phase done.
 | 
			
		||||
      if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_STUP) {
 | 
			
		||||
        out_ep[n].DOEPINT =  USB_OTG_DOEPINT_STUP;
 | 
			
		||||
        dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true);
 | 
			
		||||
        _setup_offs = 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // OUT XFER complete (single packet).
 | 
			
		||||
      if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_XFRC) {
 | 
			
		||||
        out_ep[n].DOEPINT = USB_OTG_DOEPINT_XFRC;
 | 
			
		||||
 | 
			
		||||
        // TODO: Because of endpoint 0's constrained size, we handle XFRC
 | 
			
		||||
        // on a packet-basis. The core can internally handle multiple OUT
 | 
			
		||||
        // packets; it would be more efficient to only trigger XFRC on a
 | 
			
		||||
        // completed transfer for non-0 endpoints.
 | 
			
		||||
        if(xfer->short_packet) {
 | 
			
		||||
          xfer->short_packet = false;
 | 
			
		||||
          dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true);
 | 
			
		||||
        } else {
 | 
			
		||||
          // Schedule another packet to be received.
 | 
			
		||||
          out_ep[n].DOEPTSIZ = (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | \
 | 
			
		||||
              ((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos);
 | 
			
		||||
          out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointTypeDef * in_ep) {
 | 
			
		||||
  // DAINT for a given EP clears when DIEPINTx is cleared.
 | 
			
		||||
  // IEPINT will be cleared when DAINT's out bits are cleared.
 | 
			
		||||
  for(uint8_t n = 0; n < 4; n++) {
 | 
			
		||||
    xfer_ctl_t * xfer = XFER_CTL_BASE(n, TUSB_DIR_IN);
 | 
			
		||||
 | 
			
		||||
    if(dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n))) {
 | 
			
		||||
      // IN XFER complete (entire xfer).
 | 
			
		||||
      if(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);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // XFER FIFO empty
 | 
			
		||||
      if(in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE) {
 | 
			
		||||
        in_ep[n].DIEPINT = USB_OTG_DIEPINT_TXFE;
 | 
			
		||||
        transmit_packet(xfer, &in_ep[n], n);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OTG_FS_IRQHandler(void) {
 | 
			
		||||
  USB_OTG_DeviceTypeDef * dev = DEVICE_BASE;
 | 
			
		||||
  USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE;
 | 
			
		||||
@@ -586,64 +644,12 @@ void OTG_FS_IRQHandler(void) {
 | 
			
		||||
 | 
			
		||||
  // OUT endpoint interrupt handling.
 | 
			
		||||
  if(int_status & USB_OTG_GINTSTS_OEPINT) {
 | 
			
		||||
 | 
			
		||||
    // DAINT for a given EP clears when DOEPINTx is cleared.
 | 
			
		||||
    // OEPINT will be cleared when DAINT's out bits are cleared.
 | 
			
		||||
    for(int n = 0; n < 4; n++) {
 | 
			
		||||
      xfer_ctl_t * xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT);
 | 
			
		||||
      if(dev->DAINT & (1 << (USB_OTG_DAINT_OEPINT_Pos + n))) {
 | 
			
		||||
        // SETUP packet Setup Phase done.
 | 
			
		||||
        if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_STUP) {
 | 
			
		||||
          out_ep[n].DOEPINT =  USB_OTG_DOEPINT_STUP;
 | 
			
		||||
          dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true);
 | 
			
		||||
          _setup_offs = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // OUT XFER complete (single packet).
 | 
			
		||||
        if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_XFRC) {
 | 
			
		||||
          out_ep[n].DOEPINT = USB_OTG_DOEPINT_XFRC;
 | 
			
		||||
 | 
			
		||||
          // TODO: Because of endpoint 0's constrained size, we handle XFRC
 | 
			
		||||
          // on a packet-basis. The core can internally handle multiple OUT
 | 
			
		||||
          // packets; it would be more efficient to only trigger XFRC on a
 | 
			
		||||
          // completed transfer for non-0 endpoints.
 | 
			
		||||
          if(xfer->short_packet) {
 | 
			
		||||
            xfer->short_packet = false;
 | 
			
		||||
            dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true);
 | 
			
		||||
          } else {
 | 
			
		||||
            // Schedule another packet to be received.
 | 
			
		||||
            out_ep[n].DOEPTSIZ = (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | \
 | 
			
		||||
                ((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos);
 | 
			
		||||
            out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    handle_epout_ints(dev, out_ep);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // IN endpoint interrupt handling.
 | 
			
		||||
  if(int_status & USB_OTG_GINTSTS_IEPINT) {
 | 
			
		||||
 | 
			
		||||
    // DAINT for a given EP clears when DIEPINTx is cleared.
 | 
			
		||||
    // IEPINT will be cleared when DAINT's out bits are cleared.
 | 
			
		||||
    for(uint8_t n = 0; n < 4; n++) {
 | 
			
		||||
      xfer_ctl_t * xfer = XFER_CTL_BASE(n, TUSB_DIR_IN);
 | 
			
		||||
 | 
			
		||||
      if(dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n))) {
 | 
			
		||||
        // IN XFER complete (entire xfer).
 | 
			
		||||
        if(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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // XFER FIFO empty
 | 
			
		||||
        if(in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE) {
 | 
			
		||||
          in_ep[n].DIEPINT = USB_OTG_DIEPINT_TXFE;
 | 
			
		||||
          transmit_packet(xfer, &in_ep[n], n);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    handle_epin_ints(dev, in_ep);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user