void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
{
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
uint32_t USBx_BASE = (uint32_t)USBx;
USB_OTG_EPTypeDef *ep;
uint32_t i;
uint32_t ep_intr;
uint32_t epint;
uint32_t epnum;
uint32_t fifoemptymsk;
uint32_t temp;
/* 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);
}
/* Handle RxQLevel Interrupt */
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
{
USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
temp = USBx->GRXSTSP;
ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
{
if ((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
{
(void)USB_ReadPacket(USBx, ep->xfer_buff,
(uint16_t)((temp & USB_OTG_GRXSTSP_BCNT) >> 4));
ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
}
}
else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
{
(void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
}
else
{
/* ... */
}
USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
}
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
{
epnum = 0U;
/* Read in the device interrupt bits */
ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
while (ep_intr != 0U)
{
if ((ep_intr & 0x1U) != 0U)
{
epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
{
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
(void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
}
if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
{
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
/* Class B setup phase done for previous decoded setup */
(void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
}
if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
{
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
}
/* Clear Status Phase Received interrupt */
if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
{
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
}
/* Clear OUT NAK interrupt */
if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
{
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
}
}
epnum++;
ep_intr >>= 1U;
}
}
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
{
/* Read in the device interrupt bits */
ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
epnum = 0U;
while (ep_intr != 0U)
{
if ((ep_intr & 0x1U) != 0U) /* In ITR */
{
epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
{
fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
if (hpcd->Init.dma_enable == 1U)
{
hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
/* this is ZLP, so prepare EP0 for next setup */
if ((epnum == 0U) && (hpcd->IN_ep[epnum].xfer_len == 0U))
{
/* prepare to rx more setup packets */
(void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
}
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
#else
HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
}
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)
{
(void)PCD_WriteEmptyTxFifo(hpcd, epnum);
}
}
epnum++;
ep_intr >>= 1U;
}
}
/* 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;
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
#else
HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
}
else
{
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->ResumeCallback(hpcd);
#else
HAL_PCD_ResumeCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
}
__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)
{
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->SuspendCallback(hpcd);
#else
HAL_PCD_SuspendCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
}
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
}
#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
/* 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) >> 2U;
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
#else
HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
}
else
{
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->SuspendCallback(hpcd);
#else
HAL_PCD_SuspendCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
}
}
#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
/* Handle Reset Interrupt */
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
{
USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
(void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
{
USBx_INEP(i)->DIEPINT = 0xFB7FU;
USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
USBx_INEP(i)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
}
USBx_DEVICE->DAINTMSK |= 0x10001U;
if (hpcd->Init.use_dedicated_ep1 != 0U)
{
USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
USB_OTG_DOEPMSK_XFRCM |
USB_OTG_DOEPMSK_EPDM;
USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
USB_OTG_DIEPMSK_XFRCM |
USB_OTG_DIEPMSK_EPDM;
}
else
{
USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
USB_OTG_DOEPMSK_XFRCM |
USB_OTG_DOEPMSK_EPDM |
USB_OTG_DOEPMSK_OTEPSPRM |
USB_OTG_DOEPMSK_NAKM;
USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
USB_OTG_DIEPMSK_XFRCM |
USB_OTG_DIEPMSK_EPDM;
}
/* Set Default Address to 0 */
USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
/* setup EP0 to receive SETUP packets */
(void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable,
(uint8_t *)hpcd->Setup);
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
}
/* Handle Enumeration done Interrupt */
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
{
(void)USB_ActivateSetup(hpcd->Instance);
hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
/* Set USB Turnaround time */
(void)USB_SetTurnaroundTime(hpcd->Instance,
HAL_RCC_GetHCLKFreq(),
(uint8_t)hpcd->Init.speed);
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->ResetCallback(hpcd);
#else
HAL_PCD_ResetCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
}
/* Handle SOF Interrupt */
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
{
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->SOFCallback(hpcd);
#else
HAL_PCD_SOFCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
}
/* Handle Incomplete ISO IN Interrupt */
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
{
/* Keep application checking the corresponding Iso IN endpoint
causing the incomplete Interrupt */
epnum = 0U;
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
#else
HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
}
/* Handle Incomplete ISO OUT Interrupt */
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
{
/* Keep application checking the corresponding Iso OUT endpoint
causing the incomplete Interrupt */
epnum = 0U;
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
#else
HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
}
/* Handle Connection event Interrupt */
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
{
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->ConnectCallback(hpcd);
#else
HAL_PCD_ConnectCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
}
/* Handle Disconnection event Interrupt */
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
{
temp = hpcd->Instance->GOTGINT;
if ((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
{
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->DisconnectCallback(hpcd);
#else
HAL_PCD_DisconnectCallback(hpcd);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
}
hpcd->Instance->GOTGINT |= temp;
}
}
}