/** * @brief This function handles PCD Endpoint interrupt request. * @param hpcd: PCD handle * @retval HAL status */ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd) { PCD_EPTypeDef *ep; uint16_t count=0; uint8_t EPindex; __IO uint16_t wIstr; __IO uint16_t wEPVal = 0; /* stay in loop while pending interrupts */ while (((wIstr = hpcd->Instance->ISTR) & USB_ISTR_CTR) != 0) { /* extract highest priority endpoint number */ EPindex = (uint8_t)(wIstr & USB_ISTR_EP_ID); if (EPindex == 0) { /* Decode and service control endpoint interrupt */ /* DIR bit = origin of the interrupt */ if ((wIstr & USB_ISTR_DIR) == 0) { /* DIR = 0 */ /* DIR = 0 => IN int */ /* DIR = 0 implies that (EP_CTR_TX = 1) always */ PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0); ep = &hpcd->IN_ep[0]; ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num); ep->xfer_buff += ep->xfer_count; /* TX COMPLETE */ HAL_PCD_DataInStageCallback(hpcd, 0); if((hpcd->USB_Address > 0)&& ( ep->xfer_len == 0)) { hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF); hpcd->USB_Address = 0; } } else { /* DIR = 1 */ /* DIR = 1 & CTR_RX => SETUP or OUT int */ /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ ep = &hpcd->OUT_ep[0]; wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0); if ((wEPVal & USB_EP_SETUP) != 0) { /* Get SETUP Packet*/ ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num); PCD_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count); /* SETUP bit kept frozen while CTR_RX = 1*/ PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0); /* Process SETUP Packet*/ HAL_PCD_SetupStageCallback(hpcd); } else if ((wEPVal & USB_EP_CTR_RX) != 0) { PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0); /* Get Control Data OUT Packet*/ ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num); if (ep->xfer_count != 0) { PCD_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count); ep->xfer_buff+=ep->xfer_count; } /* Process Control Data OUT Packet*/ HAL_PCD_DataOutStageCallback(hpcd, 0); PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket); PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID); } } } else { /* Decode and service non control endpoints interrupt */ /* process related endpoint register */ wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, EPindex); if ((wEPVal & USB_EP_CTR_RX) != 0) { /* clear int flag */ PCD_CLEAR_RX_EP_CTR(hpcd->Instance, EPindex); ep = &hpcd->OUT_ep[EPindex]; /* OUT double Buffering*/ if (ep->doublebuffer == 0) { count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num); if (count != 0) { PCD_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count); } } else { if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) { /*read from endpoint BUF0Addr buffer*/ count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num); if (count != 0) { PCD_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count); } } else { /*read from endpoint BUF1Addr buffer*/ count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num); if (count != 0) { PCD_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count); } } PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT); } /*multi-packet on the NON control OUT endpoint*/ ep->xfer_count+=count; ep->xfer_buff+=count; if ((ep->xfer_len == 0) || (count < ep->maxpacket)) { /* RX COMPLETE */ HAL_PCD_DataOutStageCallback(hpcd, ep->num); } else { HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len); } } /* if((wEPVal & EP_CTR_RX) */ if ((wEPVal & USB_EP_CTR_TX) != 0) { ep = &hpcd->IN_ep[EPindex]; /* clear int flag */ PCD_CLEAR_TX_EP_CTR(hpcd->Instance, EPindex); /* IN double Buffering*/ if (ep->doublebuffer == 0) { ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num); if (ep->xfer_count != 0) { PCD_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count); } } else { if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_TX) { /*read from endpoint BUF0Addr buffer*/ ep->xfer_count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num); if (ep->xfer_count != 0) { PCD_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, ep->xfer_count); } } else { /*read from endpoint BUF1Addr buffer*/ ep->xfer_count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num); if (ep->xfer_count != 0) { PCD_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, ep->xfer_count); } } PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_IN); } /*multi-packet on the NON control IN endpoint*/ ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num); ep->xfer_buff+=ep->xfer_count; /* Zero Length Packet? */ if (ep->xfer_len == 0) { /* TX COMPLETE */ HAL_PCD_DataInStageCallback(hpcd, ep->num); } else { HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len); } } } } return HAL_OK; }
/** * @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 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); } }