mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-26 08:37:16 +00:00
stm32f4: Refactor IN and OUT endpoint interrupt handling into their own functions.
This commit is contained in:
parent
f43161353c
commit
c95ad426c6
@ -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) {
|
void OTG_FS_IRQHandler(void) {
|
||||||
USB_OTG_DeviceTypeDef * dev = DEVICE_BASE;
|
USB_OTG_DeviceTypeDef * dev = DEVICE_BASE;
|
||||||
USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE;
|
USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE;
|
||||||
@ -586,64 +644,12 @@ void OTG_FS_IRQHandler(void) {
|
|||||||
|
|
||||||
// OUT endpoint interrupt handling.
|
// OUT endpoint interrupt handling.
|
||||||
if(int_status & USB_OTG_GINTSTS_OEPINT) {
|
if(int_status & USB_OTG_GINTSTS_OEPINT) {
|
||||||
|
handle_epout_ints(dev, 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IN endpoint interrupt handling.
|
// IN endpoint interrupt handling.
|
||||||
if(int_status & USB_OTG_GINTSTS_IEPINT) {
|
if(int_status & USB_OTG_GINTSTS_IEPINT) {
|
||||||
|
handle_epin_ints(dev, 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user