/** * @brief Generic endpoint IN handler. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @notapi */ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) { stm32_otg_t *otgp = usbp->otg; uint32_t epint = otgp->ie[ep].DIEPINT; otgp->ie[ep].DIEPINT = epint; if (epint & DIEPINT_TOC) { /* Timeouts not handled yet, not sure how to handle.*/ } if ((epint & DIEPINT_XFRC) && (otgp->DIEPMSK & DIEPMSK_XFRCM)) { /* Transmit transfer complete.*/ USBInEndpointState *isp = usbp->epc[ep]->in_state; if (isp->txsize < isp->totsize) { /* In case the transaction covered only part of the total transfer then another transaction is immediately started in order to cover the remaining.*/ isp->txsize = isp->totsize - isp->txsize; isp->txcnt = 0; usb_lld_prepare_transmit(usbp, ep); chSysLockFromIsr(); usb_lld_start_in(usbp, ep); chSysUnlockFromIsr(); } else { /* End on IN transfer.*/ _usb_isr_invoke_in_cb(usbp, ep); } } if ((epint & DIEPINT_TXFE) && (otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEM(ep))) { /* The thread is made ready, it will be scheduled on ISR exit.*/ chSysLockFromIsr(); usbp->txpending |= (1 << ep); otgp->DIEPEMPMSK &= ~(1 << ep); usb_lld_wakeup_pump(usbp); chSysUnlockFromIsr(); } }
/** * @brief Generic endpoint IN handler. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @notapi */ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) { stm32_otg_t *otgp = usbp->otg; uint32_t epint = otgp->ie[ep].DIEPINT; otgp->ie[ep].DIEPINT = 0xFFFFFFFF; if (epint & DIEPINT_TOC) { /* Timeouts not handled yet, not sure how to handle.*/ } if ((epint & DIEPINT_XFRC) && (otgp->DIEPMSK & DIEPMSK_XFRCM)) { /* Transmit transfer complete.*/ _usb_isr_invoke_in_cb(usbp, ep); } if ((epint & DIEPINT_TXFE) && (otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEM(ep))) { /* The thread is made ready, it will be scheduled on ISR exit.*/ chSysLockFromIsr(); usbp->txpending |= (1 << ep); otgp->DIEPEMPMSK &= ~(1 << ep); usb_lld_wakeup_pump(usbp); chSysUnlockFromIsr(); } }
/** * @brief Starts a transmit operation on an IN endpoint. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @notapi */ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK; usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep); }