/** * @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); } }
/** * @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; }