dcd_stm32f4: Merge relevant changes from dcd_stm32h7.

This commit is contained in:
William D. Jones
2019-09-09 09:53:56 -04:00
parent 3efc81b285
commit 82cd4b5350

View File

@@ -108,7 +108,7 @@ static void bus_reset(void) {
// Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word )
USB_OTG_FS->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (USB_OTG_FS->GRXFSIZ & 0x0000ffffUL); USB_OTG_FS->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (USB_OTG_FS->GRXFSIZ & 0x0000ffffUL);
out_ep[0].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos);
USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT;
} }
@@ -143,12 +143,13 @@ void dcd_init (uint8_t rhport)
{ {
(void) rhport; (void) rhport;
// Programming model begins on page 1336 of Rev 17 of reference manual. // Programming model begins in the last section of the chapter on the USB
// peripheral in each Reference Manual.
USB_OTG_FS->GAHBCFG |= USB_OTG_GAHBCFG_TXFELVL | USB_OTG_GAHBCFG_GINT; USB_OTG_FS->GAHBCFG |= USB_OTG_GAHBCFG_TXFELVL | USB_OTG_GAHBCFG_GINT;
// No HNP/SRP (no OTG support), program timeout later, turnaround // No HNP/SRP (no OTG support), program timeout later, turnaround
// programmed for 18 MHz. // programmed for 32+ MHz.
USB_OTG_FS->GUSBCFG |= (0x0C << USB_OTG_GUSBCFG_TRDT_Pos); USB_OTG_FS->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos);
// Clear all used interrupts // Clear all used interrupts
USB_OTG_FS->GINTSTS |= USB_OTG_GINTSTS_OTGINT | USB_OTG_GINTSTS_MMIS | \ USB_OTG_FS->GINTSTS |= USB_OTG_GINTSTS_OTGINT | USB_OTG_GINTSTS_MMIS | \
@@ -170,14 +171,15 @@ void dcd_init (uint8_t rhport)
USB_OTG_GINTMSK_SOFM | USB_OTG_GINTMSK_RXFLVLM /* SB_OTG_GINTMSK_ESUSPM | \ USB_OTG_GINTMSK_SOFM | USB_OTG_GINTMSK_RXFLVLM /* SB_OTG_GINTMSK_ESUSPM | \
USB_OTG_GINTMSK_USBSUSPM */; USB_OTG_GINTMSK_USBSUSPM */;
// Enable VBus hardware sensing, // Enable VBUS hardware sensing, enable pullup, enable peripheral.
#ifdef USB_OTG_GCCFG_VBDEN #ifdef USB_OTG_GCCFG_VBDEN
USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN | USB_OTG_GCCFG_PWRDWN; USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN | USB_OTG_GCCFG_PWRDWN;
#else #else
USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_PWRDWN; USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_PWRDWN;
#endif #endif
// Soft Connect -> Enable pullup on D+/D- // Soft Connect -> Enable pullup on D+/D-.
// This step does not appear to be specified in the programmer's model.
dev->DCTL &= ~USB_OTG_DCTL_SDIS; dev->DCTL &= ~USB_OTG_DCTL_SDIS;
} }
@@ -318,7 +320,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
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;
} }
@@ -347,9 +349,8 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SNAK; in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_INEPNE) == 0); while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_INEPNE) == 0);
// Disable the endpoint. Note that both SNAK and STALL are set here. // Disable the endpoint.
in_ep[epnum].DIEPCTL |= (USB_OTG_DIEPCTL_SNAK | USB_OTG_DIEPCTL_STALL | \ in_ep[epnum].DIEPCTL |= (USB_OTG_DIEPCTL_STALL | USB_OTG_DIEPCTL_EPDIS);
USB_OTG_DIEPCTL_EPDIS);
while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_EPDISD_Msk) == 0); while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_EPDISD_Msk) == 0);
in_ep[epnum].DIEPINT = USB_OTG_DIEPINT_EPDISD; in_ep[epnum].DIEPINT = USB_OTG_DIEPINT_EPDISD;
} }
@@ -361,7 +362,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
} else { } else {
// Only disable currently enabled non-control endpoint // Only disable currently enabled non-control endpoint
if ( (epnum == 0) || !(out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPENA) ){ if ( (epnum == 0) || !(out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPENA) ){
out_ep[epnum].DOEPCTL |= USB_OTG_DIEPCTL_STALL; out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_STALL;
} else { } else {
// Asserting GONAK is required to STALL an OUT endpoint. // Asserting GONAK is required to STALL an OUT endpoint.
// Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt
@@ -370,8 +371,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
dev->DCTL |= USB_OTG_DCTL_SGONAK; dev->DCTL |= USB_OTG_DCTL_SGONAK;
while((USB_OTG_FS->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF_Msk) == 0); while((USB_OTG_FS->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF_Msk) == 0);
// Ditto here- disable the endpoint. Note that only STALL and not SNAK // Ditto here- disable the endpoint.
// is set here.
out_ep[epnum].DOEPCTL |= (USB_OTG_DOEPCTL_STALL | USB_OTG_DOEPCTL_EPDIS); out_ep[epnum].DOEPCTL |= (USB_OTG_DOEPCTL_STALL | USB_OTG_DOEPCTL_EPDIS);
while((out_ep[epnum].DOEPINT & USB_OTG_DOEPINT_EPDISD_Msk) == 0); while((out_ep[epnum].DOEPINT & USB_OTG_DOEPINT_EPDISD_Msk) == 0);
out_ep[epnum].DOEPINT = USB_OTG_DOEPINT_EPDISD; out_ep[epnum].DOEPINT = USB_OTG_DOEPINT_EPDISD;
@@ -391,13 +391,6 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr);
// TODO: Figure out what happens when none of EPENA, SNAK, or STALL are
// set. Per manual, page 1364 of rev 17, for OUT endpoints,
// you set STALL _instead of_ SNAK when disabling an endpoint during a STALL.
// This means when stall is cleared, none of the above bits are set?
//
// Contrast to IN endpoints, where page 1372 instructs you to set STALL
// _and_ SNAK when STALLing IN endpoints.
if(dir == TUSB_DIR_IN) { if(dir == TUSB_DIR_IN) {
in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
@@ -547,21 +540,21 @@ static void read_rx_fifo(USB_OTG_OUTEndpointTypeDef * out_ep) {
case 0x03: // Out packet done (Interrupt) case 0x03: // Out packet done (Interrupt)
break; break;
case 0x04: // Setup packet done (Interrupt) case 0x04: // Setup packet done (Interrupt)
out_ep[epnum].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); _setup_offs = 2 - ((out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_STUPCNT_Msk) >> USB_OTG_DOEPTSIZ_STUPCNT_Pos);
out_ep[epnum].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos);
break; break;
case 0x06: // Setup packet recvd case 0x06: // Setup packet recvd
{ {
// For some reason, it's possible to get a mismatch between uint8_t setup_left = ((out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_STUPCNT_Msk) >> USB_OTG_DOEPTSIZ_STUPCNT_Pos);
// how many setup packets were received versus the location
// of the Setup packet done word. This leads to situations // We can receive up to three setup packets in succession, but
// where stale setup packets are in the RX FIFO that were received // only the last one is valid.
// after the core loaded the Setup packet done word. Workaround by _setup_packet[4 - 2*setup_left] = (* rx_fifo);
// only accepting one setup packet at a time for now. _setup_packet[5 - 2*setup_left] = (* rx_fifo);
_setup_packet[0] = (* rx_fifo);
_setup_packet[1] = (* rx_fifo);
} }
break; break;
default: // Invalid, do something here, like breakpoint? default: // Invalid
TU_BREAKPOINT();
break; break;
} }
} }
@@ -576,7 +569,7 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy
// SETUP packet Setup Phase done. // SETUP packet Setup Phase done.
if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_STUP) { if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_STUP) {
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); dcd_event_setup_received(0, (uint8_t*) &_setup_packet[2*_setup_offs], true);
_setup_offs = 0; _setup_offs = 0;
} }
@@ -595,7 +588,7 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy
dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true);
} else { } else {
// Schedule another packet to be received. // Schedule another packet to be received.
out_ep[n].DOEPTSIZ = (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | \ out_ep[n].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[n].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
} }