/** * @brief USBD_OTG_EP1OUT_ISR_Handler * handles all USB Interrupts * @param pdev: device instance * @retval status */ uint32_t USBD_OTG_EP1OUT_ISR_Handler (USB_OTG_CORE_HANDLE *pdev) { USB_OTG_DOEPINTn_TypeDef doepint; USB_OTG_DEPXFRSIZ_TypeDef deptsiz; doepint.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[1]->DOEPINT); doepint.d32&= USB_OTG_READ_REG32(&pdev->regs.DREGS->DOUTEP1MSK); /* Transfer complete */ if ( doepint.b.xfercompl ) { /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(1, xfercompl); if (pdev->cfg.dma_enable == 1) { deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[1]->DOEPTSIZ)); /*ToDo : handle more than one single MPS size packet */ pdev->dev.out_ep[1].xfer_count = pdev->dev.out_ep[1].maxpacket - \ deptsiz.b.xfersize; } /* Inform upper layer: data ready */ /* RX COMPLETE */ USBD_DCD_INT_fops->DataOutStage(pdev , 1); } /* Endpoint disable */ if ( doepint.b.epdisabled ) { /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(1, epdisabled); } /* AHB Error */ if ( doepint.b.ahberr ) { CLEAR_OUT_EP_INTR(1, ahberr); } return 1; }
/** * @brief This function handles PCD interrupt request. * @param hpcd: PCD handle * @retval HAL status */ void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd) { USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; uint32_t i = 0, ep_intr = 0, epint = 0, epnum = 0; uint32_t fifoemptymsk = 0, temp = 0; USB_OTG_EPTypeDef *ep; /* ensure that we are in device mode */ if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE) { /* avoid spurious interrupt */ if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd)) { return; } if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS)) { /* incorrect mode, acknowledge the interrupt */ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS); } if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT)) { epnum = 0; /* Read in the device interrupt bits */ ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance); while ( ep_intr ) { if (ep_intr & 0x1) { epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum); if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC) { CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC); if(hpcd->Init.dma_enable == 1) { hpcd->OUT_ep[epnum].xfer_count = hpcd->OUT_ep[epnum].maxpacket- (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ); hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket; } HAL_PCD_DataOutStageCallback(hpcd, epnum); if(hpcd->Init.dma_enable == 1) { if((epnum == 0) && (hpcd->OUT_ep[epnum].xfer_len == 0)) { /* this is ZLP, so prepare EP0 for next setup */ USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); } } } if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) { /* Inform the upper layer that a setup packet is available */ HAL_PCD_SetupStageCallback(hpcd); CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP); } if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS) { CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS); } } epnum++; ep_intr >>= 1; } } if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT)) { /* Read in the device interrupt bits */ ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance); epnum = 0; while ( ep_intr ) { if (ep_intr & 0x1) /* In ITR */ { epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum); if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC) { fifoemptymsk = 0x1 << epnum; USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk; CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC); if (hpcd->Init.dma_enable == 1) { hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket; } HAL_PCD_DataInStageCallback(hpcd, epnum); if (hpcd->Init.dma_enable == 1) { /* this is ZLP, so prepare EP0 for next setup */ if((epnum == 0) && (hpcd->IN_ep[epnum].xfer_len == 0)) { /* prepare to rx more setup packets */ USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); } } } if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC) { CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC); } if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE) { CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE); } if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE) { CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE); } if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD) { CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD); } if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) { PCD_WriteEmptyTxFifo(hpcd , epnum); } } epnum++; ep_intr >>= 1; } } /* Handle Resume Interrupt */ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT)) { /* Clear the Remote Wake-up Signaling */ USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG; if(hpcd->LPM_State == LPM_L1) { hpcd->LPM_State = LPM_L0; HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE); } else { HAL_PCD_ResumeCallback(hpcd); } __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT); } /* Handle Suspend Interrupt */ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP)) { if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS) { HAL_PCD_SuspendCallback(hpcd); } __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP); } /* Handle LPM Interrupt */ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT)) { __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT); if( hpcd->LPM_State == LPM_L0) { hpcd->LPM_State = LPM_L1; hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >>2 ; HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE); } else { HAL_PCD_SuspendCallback(hpcd); } }
/** * @brief DCD_HandleOutEP_ISR * Indicates that an OUT EP has a pending Interrupt * @param pdev: device instance * @retval status */ static uint32_t DCD_HandleOutEP_ISR(USB_OTG_CORE_HANDLE *pdev) { uint32_t ep_intr; USB_OTG_DOEPINTn_TypeDef doepint; USB_OTG_DEPXFRSIZ_TypeDef deptsiz; uint32_t epnum = 0; doepint.d32 = 0; /* Read in the device interrupt bits */ ep_intr = USB_OTG_ReadDevAllOutEp_itr(pdev); while ( ep_intr ) { if (ep_intr&0x1) { doepint.d32 = USB_OTG_ReadDevOutEP_itr(pdev, epnum); /* Transfer complete */ if ( doepint.b.xfercompl ) { /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(epnum, xfercompl); if (pdev->cfg.dma_enable == 1) { deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[epnum]->DOEPTSIZ)); /*ToDo : handle more than one single MPS size packet */ pdev->dev.out_ep[epnum].xfer_count = pdev->dev.out_ep[epnum].maxpacket - \ deptsiz.b.xfersize; } /* Inform upper layer: data ready */ /* RX COMPLETE */ USBD_DCD_INT_fops->DataOutStage(pdev , epnum); if (pdev->cfg.dma_enable == 1) { if((epnum == 0) && (pdev->dev.device_state == USB_OTG_EP0_STATUS_OUT)) { /* prepare to rx more setup packets */ USB_OTG_EP0_OutStart(pdev); } } } /* Endpoint disable */ if ( doepint.b.epdisabled ) { /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(epnum, epdisabled); } /* Setup Phase Done (control EPs) */ if ( doepint.b.setup ) { /* inform the upper layer that a setup packet is available */ /* SETUP COMPLETE */ USBD_DCD_INT_fops->SetupStage(pdev); CLEAR_OUT_EP_INTR(epnum, setup); } } epnum++; ep_intr >>= 1; } return 1; }
/******************************************************************************* * Function Name : OTGD_FS_Handle_OutEP_ISR * Description : Handles all OUT endpoints interrupts. * Input : None * Output : None * Return : Status *******************************************************************************/ uint32_t OTGD_FS_Handle_OutEP_ISR(void) { uint32_t ep_intr = 0; USB_OTG_DOEPINTx_TypeDef doepint; uint32_t epnum = 0; USB_OTG_EP *ep; doepint.d32 = 0; /* Read in the device interrupt bits */ ep_intr = OTGD_FS_ReadDevAllOutEp_itr(); while ( ep_intr ) { if (ep_intr&0x1) { /* Get EP pointer */ ep = PCD_GetOutEP(epnum); doepint.d32 = OTGD_FS_ReadDevOutEP_itr(ep); /* Transfer complete */ if ( doepint.b.xfercompl ) { /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(epnum, xfercompl); if (epnum == 0) { /* Call the OUT process for the EP0 */ Out0_Process(); } else { (*pEpInt_OUT[epnum-1])(); } } /* Endpoint disable */ if ( doepint.b.epdis) { /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(epnum, epdis); } /* Setup Phase Done (control EPs) */ if ( doepint.b.setup ) { if (epnum == 0) { /* Call the SETUP process for the EP0 */ Setup0_Process(); /* Before exit, update the Tx status */ OTG_DEV_SetEPTxStatus(0x80, SaveTState); } else { /* Other control endpoints */ } /* Clear the EP Interrupt */ CLEAR_OUT_EP_INTR(epnum, setup); } /* Back to back setup received */ if ( doepint.b.b2bsetup ) { if (epnum == 0) { /* Call the SETUP process for the EP0 */ Setup0_Process(); /* Before exit, update the Tx status */ OTG_DEV_SetEPTxStatus(0x80, SaveTState); } } } epnum++; ep_intr >>= 1; } /* Call user function */ INTR_OUTEPINTR_Callback(); return 1; }
/** * @brief Handles PCD interrupt request. * @param hpcd: PCD handle * @retval HAL status */ void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd) { USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; uint32_t index = 0U, ep_intr = 0U, epint = 0U, epnum = 0U; uint32_t fifoemptymsk = 0U, temp = 0U; USB_OTG_EPTypeDef *ep = NULL; uint32_t hclk = 80000000; /* ensure that we are in device mode */ if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE) { /* avoid spurious interrupt */ if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd)) { return; } if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS)) { /* incorrect mode, acknowledge the interrupt */ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS); } if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT)) { epnum = 0; /* Read in the device interrupt bits */ ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance); while (ep_intr) { if (ep_intr & 0x1) { epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum); if (( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC) { CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC); /* setup/out transaction management for Core ID 310A */ if (USBx->GSNPSID == USB_OTG_CORE_ID_310A) { if (!(USBx_OUTEP(0)->DOEPINT & (0x1 << 15))) { if (hpcd->Init.dma_enable == 1) { hpcd->OUT_ep[epnum].xfer_count = hpcd->OUT_ep[epnum].maxpacket - (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ); hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket; } HAL_PCD_DataOutStageCallback(hpcd, epnum); if (hpcd->Init.dma_enable == 1) { if (!epnum && !hpcd->OUT_ep[epnum].xfer_len) { /* this is ZLP, so prepare EP0 for next setup */ USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); } } } /* Clear the SetPktRcvd flag*/ USBx_OUTEP(0)->DOEPINT |= (0x1 << 15) | (0x1 << 5); } else { if (hpcd->Init.dma_enable == 1) { hpcd->OUT_ep[epnum].xfer_count = hpcd->OUT_ep[epnum].maxpacket - (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ); hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket; } HAL_PCD_DataOutStageCallback(hpcd, epnum); if (hpcd->Init.dma_enable == 1) { if (!epnum && !hpcd->OUT_ep[epnum].xfer_len) { /* this is ZLP, so prepare EP0 for next setup */ USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); } } } } if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) { /* Inform the upper layer that a setup packet is available */ HAL_PCD_SetupStageCallback(hpcd); CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP); } if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS) { CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS); } #ifdef USB_OTG_DOEPINT_OTEPSPR /* Clear Status Phase Received interrupt */ if(( epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR) { CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR); } #endif /* USB_OTG_DOEPINT_OTEPSPR */ } epnum++; ep_intr >>= 1; } } if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT)) { /* Read in the device interrupt bits */ ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance); epnum = 0; while ( ep_intr ) { if (ep_intr & 0x1) /* In ITR */ { epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum); if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC) { fifoemptymsk = 0x1 << epnum; // Added for MBED PR #3062 atomic_clr_u32(&USBx_DEVICE->DIEPEMPMSK, fifoemptymsk); CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC); if (hpcd->Init.dma_enable == 1) { hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket; } HAL_PCD_DataInStageCallback(hpcd, epnum); if (hpcd->Init.dma_enable == 1) { /* this is ZLP, so prepare EP0 for next setup */ if((epnum == 0) && (hpcd->IN_ep[epnum].xfer_len == 0)) { /* prepare to rx more setup packets */ USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); } } } if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC) { CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC); } if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE) { CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE); } if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE) { CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE); } if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD) { CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD); } if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) { PCD_WriteEmptyTxFifo(hpcd , epnum); } } epnum++; ep_intr >>= 1; } } /* Handle Resume Interrupt */ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT)) { /* Clear the Remote Wake-up Signaling */ USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG; if(hpcd->LPM_State == LPM_L1) { hpcd->LPM_State = LPM_L0; HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE); } else { HAL_PCD_ResumeCallback(hpcd); } __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT); } /* Handle Suspend Interrupt */ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP)) { if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS) { HAL_PCD_SuspendCallback(hpcd); } __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP); } /* Handle LPM Interrupt */ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT)) { __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT); if( hpcd->LPM_State == LPM_L0) { hpcd->LPM_State = LPM_L1; hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >>2 ; HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE); } else { HAL_PCD_SuspendCallback(hpcd); } }
/** * This interrupt indicates that an OUT EP has a pending Interrupt. * The sequence for handling the OUT EP interrupt is shown below: * -# Read the Device All Endpoint Interrupt register * -# Repeat the following for each OUT EP interrupt bit set (from * LSB to MSB). * -# Read the Device Endpoint Interrupt (DOEPINTn) register * -# If "Transfer Complete" call the request complete function * -# If "Endpoint Disabled" complete the EP disable procedure. * -# If "AHB Error Interrupt" log error * -# If "Setup Phase Done" process Setup Packet (See Standard USB * Command Processing) */ static int32_t dwc_otg_pcd_handle_out_ep_intr(void) { #define CLEAR_OUT_EP_INTR(__epnum,__intr) \ do { \ doepint_data_t doepint = { 0 }; \ doepint.b.__intr = 1; \ dwc_write_reg32(DWC_REG_OUT_EP_INTR(__epnum), \ doepint.d32); \ } while (0) uint32_t ep_intr; doepint_data_t doepint = { 0 }; uint32_t epnum = 0; // uint32_t epnum_trans = 0; gintsts_data_t gintsts; DBG( "dwc_otg_pcd_handle_out_ep_intr()\n" ); /* Read in the device interrupt bits */ ep_intr = (dwc_read_reg32(DWC_REG_DAINT) & dwc_read_reg32( DWC_REG_DAINTMSK)); ep_intr =( (ep_intr & 0xffff0000) >> 16); /* Clear the OUTEPINT in GINTSTS */ gintsts.d32 = 0; gintsts.b.outepintr = 1; dwc_write_reg32 (DWC_REG_GINTSTS, gintsts.d32); dwc_write_reg32(DWC_REG_DAINT, 0xFFFF0000 ); while ( ep_intr ) { if (ep_intr&0x1) { doepint.d32 = (dwc_read_reg32( DWC_REG_OUT_EP_INTR(epnum)) & dwc_read_reg32(DWC_REG_DOEPMSK)); /* Transfer complete */ if ( doepint.b.xfercompl ) { DBG("EP%d OUT Xfer Complete\n", epnum); /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(epnum,xfercompl); if (epnum == 0) { handle_ep0( 0 ); } else { complete_ep( epnum,0 ); } } /* Endpoint disable */ if ( doepint.b.epdisabled ) { DBG("EP%d OUT disabled\n", epnum); /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(epnum,epdisabled); } /* AHB Error */ if ( doepint.b.ahberr ) { DBG("EP%d OUT AHB Error\n", epnum); CLEAR_OUT_EP_INTR(epnum,ahberr); } /* Setup Phase Done (contorl EPs) */ if ( doepint.b.setup ) { handle_ep0( 0 ); CLEAR_OUT_EP_INTR(epnum,setup); } } epnum++; ep_intr >>=1; } return 1; #undef CLEAR_OUT_EP_INTR }