/** * @brief Enables an endpoint. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @notapi */ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { uint32_t ctl, fsize; stm32_otg_t *otgp = usbp->otg; /* IN and OUT common parameters.*/ switch (usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) { case USB_EP_MODE_TYPE_CTRL: ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL; break; case USB_EP_MODE_TYPE_ISOC: ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_ISO; break; case USB_EP_MODE_TYPE_BULK: ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_BULK; break; case USB_EP_MODE_TYPE_INTR: ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_INTR; break; default: return; } /* OUT endpoint activation or deactivation.*/ otgp->oe[ep].DOEPTSIZ = 0; if (usbp->epc[ep]->out_cb != NULL) { otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize); otgp->DAINTMSK |= DAINTMSK_OEPM(ep); } else { otgp->oe[ep].DOEPCTL &= ~DOEPCTL_USBAEP; otgp->DAINTMSK &= ~DAINTMSK_OEPM(ep); } /* IN endpoint activation or deactivation.*/ otgp->ie[ep].DIEPTSIZ = 0; if (usbp->epc[ep]->in_cb != NULL) { /* FIFO allocation for the IN endpoint.*/ fsize = usbp->epc[ep]->in_maxsize / 4; if (usbp->epc[ep]->in_multiplier > 1) fsize *= usbp->epc[ep]->in_multiplier; otgp->DIEPTXF[ep - 1] = DIEPTXF_INEPTXFD(fsize) | DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, fsize)); otg_txfifo_flush(usbp, ep); otgp->ie[ep].DIEPCTL = ctl | DIEPCTL_TXFNUM(ep) | DIEPCTL_MPSIZ(usbp->epc[ep]->in_maxsize); otgp->DAINTMSK |= DAINTMSK_IEPM(ep); } else { otgp->DIEPTXF[ep - 1] = 0x02000400; /* Reset value.*/ otg_txfifo_flush(usbp, ep); otgp->ie[ep].DIEPCTL &= ~DIEPCTL_USBAEP; otgp->DAINTMSK &= ~DAINTMSK_IEPM(ep); } }
static void otg_disable_ep(USBDriver *usbp) { stm32_otg_t *otgp = usbp->otg; unsigned i; for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { otgp->ie[i].DIEPCTL = 0; otgp->ie[i].DIEPTSIZ = 0; otgp->ie[i].DIEPINT = 0xFFFFFFFF; otgp->oe[i].DOEPCTL = 0; otgp->oe[i].DOEPTSIZ = 0; otgp->oe[i].DOEPINT = 0xFFFFFFFF; } otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); }
/** * @brief USB low level reset routine. * * @param[in] usbp pointer to the @p USBDriver object * * @notapi */ void usb_lld_reset(USBDriver *usbp) { unsigned i; stm32_otg_t *otgp = usbp->otg; /* Flush the Tx FIFO.*/ otg_txfifo_flush(usbp, 0); /* All endpoints in NAK mode, interrupts cleared.*/ for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { otgp->ie[i].DIEPCTL = DIEPCTL_SNAK; otgp->oe[i].DOEPCTL = DOEPCTL_SNAK; otgp->ie[i].DIEPINT = 0xFF; otgp->oe[i].DOEPINT = 0xFF; } /* Endpoint interrupts all disabled and cleared.*/ otgp->DAINT = 0xFFFFFFFF; otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); /* Resets the FIFO memory allocator.*/ otg_ram_reset(usbp); /* Receive FIFO size initialization, the address is always zero.*/ otgp->GRXFSIZ = usbp->otgparams->rx_fifo_size; otg_rxfifo_flush(usbp); /* Resets the device address to zero.*/ otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(0); /* Enables also EP-related interrupt sources.*/ otgp->GINTMSK |= GINTMSK_RXFLVLM | GINTMSK_OEPM | GINTMSK_IEPM; otgp->DIEPMSK = DIEPMSK_TOCM | DIEPMSK_XFRCM; otgp->DOEPMSK = DOEPMSK_STUPM | DOEPMSK_XFRCM; /* EP0 initialization, it is a special case.*/ usbp->epc[0] = &ep0config; otgp->oe[0].DOEPTSIZ = 0; otgp->oe[0].DOEPCTL = DOEPCTL_SD0PID | DOEPCTL_USBAEP | DOEPCTL_EPTYP_CTRL | DOEPCTL_MPSIZ(ep0config.out_maxsize); otgp->ie[0].DIEPTSIZ = 0; otgp->ie[0].DIEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL | DIEPCTL_TXFNUM(0) | DIEPCTL_MPSIZ(ep0config.in_maxsize); otgp->DIEPTXF0 = DIEPTXF_INEPTXFD(ep0config.in_maxsize / 4) | DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, ep0config.in_maxsize / 4)); }
void Usb_t::IReset() { Uart.Printf("========= Rst =========\r\n"); TxFifoFlush(); // Set all EPs in NAK mode and clear Irqs for(uint8_t i=0; i < USB_EP_CNT; i++) { OTG_FS->ie[i].DIEPCTL = DIEPCTL_SNAK; OTG_FS->oe[i].DOEPCTL = DOEPCTL_SNAK; OTG_FS->ie[i].DIEPINT = 0xFF; OTG_FS->oe[i].DOEPINT = 0xFF; Ep[i].IsReceiving = false; Ep[i].IsTransmitting = false; Ep[i].IsTxPending = false; } // Disable and clear all EP irqs OTG_FS->DAINT = 0xFFFFFFFF; OTG_FS->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); OTG_FS->DIEPEMPMSK &= 0xFFFF0000; MemAllocator.Reset(); // RX FIFO init, the address is always zero OTG_FS->GRXFSIZ = RX_FIFO_SZW; RxFifoFlush(); // Reset device address to zero OTG_FS->DCFG = (OTG_FS->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(0); // Enable EP-related irqs OTG_FS->GINTMSK |= GINTMSK_RXFLVLM | GINTMSK_OEPM | GINTMSK_IEPM; OTG_FS->DIEPMSK = DIEPMSK_XFRCM; OTG_FS->DOEPMSK = DOEPMSK_STUPM | DOEPMSK_XFRCM | DOEPMSK_OTEPDM; // Init EP0 OTG_FS->ie[0].DIEPINT |= 0x5B; // } OTG_FS->oe[0].DOEPINT |= 0x5B; // } Clear interrupts OTG_FS->oe[0].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_XFRSIZ(Ep[0].OutMaxSz); OTG_FS->oe[0].DOEPCTL = 0; // EP size is 64 bytes OTG_FS->ie[0].DIEPTSIZ = 0; OTG_FS->ie[0].DIEPCTL = DIEPCTL_TXFNUM(0); OTG_FS->DIEPTXF0 = DIEPTXF_INEPTXFD(TX0_FIFO_SZW) | DIEPTXF_INEPTXSA(RX_FIFO_SZW); // OTG_FS->DIEPTXF0 = DIEPTXF_INEPTXFD(EP0_SZ / 4) | DIEPTXF_INEPTXSA(MemAllocator.Alloc(EP0_SZ / 4)); Ep0State = esWaitingSetup; Ep[0].Rx.Ptr = Ep0RxBuf; }
static void otg_disable_ep(USBDriver *usbp) { stm32_otg_t *otgp = usbp->otg; unsigned i; for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { /* Disable only if enabled because this sentence in the manual: "The application must set this bit only if Endpoint Enable is already set for this endpoint".*/ if ((otgp->ie[i].DIEPCTL & DIEPCTL_EPENA) != 0) { otgp->ie[i].DIEPCTL = DIEPCTL_EPDIS; /* Wait for endpoint disable.*/ while (!(otgp->ie[i].DIEPINT & DIEPINT_EPDISD)) ; } else otgp->ie[i].DIEPCTL = 0; otgp->ie[i].DIEPTSIZ = 0; otgp->ie[i].DIEPINT = 0xFFFFFFFF; /* Disable only if enabled because this sentence in the manual: "The application must set this bit only if Endpoint Enable is already set for this endpoint". Note that the attempt to disable the OUT EP0 is ignored by the hardware but the code is simpler this way.*/ if ((otgp->oe[i].DOEPCTL & DOEPCTL_EPENA) != 0) { otgp->oe[i].DOEPCTL = DOEPCTL_EPDIS; /* Wait for endpoint disable.*/ while (!(otgp->oe[i].DOEPINT & DOEPINT_OTEPDIS)) ; } else otgp->oe[i].DOEPCTL = 0; otgp->oe[i].DOEPTSIZ = 0; otgp->oe[i].DOEPINT = 0xFFFFFFFF; } otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); }