/** * @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 OTG shared ISR. * * @param[in] usbp pointer to the @p USBDriver object * * @notapi */ static void usb_lld_serve_interrupt(USBDriver *usbp) { stm32_otg_t *otgp = usbp->otg; uint32_t sts, src; sts = otgp->GINTSTS & otgp->GINTMSK; otgp->GINTSTS = sts; /* Reset interrupt handling.*/ if (sts & GINTSTS_USBRST) { _usb_reset(usbp); _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET); } /* Enumeration done.*/ if (sts & GINTSTS_ENUMDNE) { (void)otgp->DSTS; } /* SOF interrupt handling.*/ if (sts & GINTSTS_SOF) { _usb_isr_invoke_sof_cb(usbp); } /* RX FIFO not empty handling.*/ if (sts & GINTSTS_RXFLVL) { /* The interrupt is masked while the thread has control or it would be triggered again.*/ chSysLockFromIsr(); otgp->GINTMSK &= ~GINTMSK_RXFLVLM; usb_lld_wakeup_pump(usbp); chSysUnlockFromIsr(); } /* IN/OUT endpoints event handling.*/ src = otgp->DAINT; if (sts & GINTSTS_IEPINT) { if (src & (1 << 0)) otg_epin_handler(usbp, 0); if (src & (1 << 1)) otg_epin_handler(usbp, 1); if (src & (1 << 2)) otg_epin_handler(usbp, 2); if (src & (1 << 3)) otg_epin_handler(usbp, 3); #if STM32_USB_USE_OTG2 if (src & (1 << 4)) otg_epin_handler(usbp, 4); if (src & (1 << 5)) otg_epin_handler(usbp, 5); #endif } if (sts & GINTSTS_OEPINT) { if (src & (1 << 16)) otg_epout_handler(usbp, 0); if (src & (1 << 17)) otg_epout_handler(usbp, 1); if (src & (1 << 18)) otg_epout_handler(usbp, 2); if (src & (1 << 19)) otg_epout_handler(usbp, 3); #if STM32_USB_USE_OTG2 if (src & (1 << 20)) otg_epout_handler(usbp, 4); if (src & (1 << 21)) otg_epout_handler(usbp, 5); #endif } }