/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** * File Name : otgd_fs_int.c * Author : MCD Application Team * Version : V3.1.0 * Date : 10/30/2009 * Description : Endpoint interrupt's service routines. ******************************************************************************** * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE * CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. *******************************************************************************/ #ifdef STM32F10X_CL /* Includes ------------------------------------------------------------------*/ #include "stm32f10x.h" #include "usb_type.h" #include "otgd_fs_int.h" #include "usb_lib.h" #include "usb_istr.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Max size of the received OUT Non periodic packet */ #define MAX_OUT_PKT_SIZE 160 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ uint8_t USBD_Data_Buffer [MAX_OUT_PKT_SIZE]; __IO uint8_t IsocBuff [(ISOC_BUFFER_SZE * NUM_SUB_BUFFERS)]; __IO uint32_t IsocBufferIdx = 0; extern USB_OTG_CORE_REGS core_regs; __IO uint16_t SaveRState; __IO uint16_t SaveTState; /* Extern variables ----------------------------------------------------------*/ extern void (*pEpInt_IN[7])(void); /* Handles IN interrupts */ extern void (*pEpInt_OUT[7])(void); /* Handles OUT interrupts */ /* Private function prototypes -----------------------------------------------*/ static uint32_t OTGD_FS_PCD_ReadDevInEP( USB_OTG_EP *ep); static enum usb_device_speed OTGD_FS_PCD_GetDeviceSpeed(void); static uint32_t OTGD_FS_PCD_WriteEmptyTxFifo(uint32_t epnum); /* Private functions ---------------------------------------------------------*/ /******************************************************************************* * Function Name : OTGD_FS_Handle_ModeMismatch_ISR * Description : Handles the Mode Mismatch error interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_ModeMismatch_ISR(void) { USB_OTG_int_sts_data gintsts; INTR_MODEMISMATCH_Callback(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.modemismatch = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_Sof_ISR * Description : Handles the Start Of Frame detected interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_Sof_ISR(void) { USB_OTG_int_sts_data int_sts; /* Call user function */ INTR_SOFINTR_Callback(); /* Clear interrupt */ int_sts.d32 = 0; int_sts.b.sofintr = 1; WRITE_REG32 (&core_regs.common_regs->int_sts, int_sts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_RxStatusQueueLevel_ISR * Description : Handles the Rx Status Queue Level Interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_RxStatusQueueLevel_ISR(void) { USB_OTG_int_msk_data int_mask; USB_OTG_dev_rx_sts_data status; /* USB_OTG_int_sts_data int_sts; */ USB_OTG_EP *ep; /* Disable the Rx Status Queue Level interrupt */ int_mask.b.rxstsqlvl = 1; MODIFY_REG32( &core_regs.common_regs->int_msk, int_mask.d32, 0); /* Get the Status from the top of the FIFO */ status.d32 = READ_REG32( &core_regs.common_regs->rx_stsp ); /* Get the related endpoint structure */ ep = OTGD_FS_PCD_GetOutEP(status.b.epnum); switch (status.b.pktsts) { case STS_GOUT_NAK: break; case STS_DATA_UPDT: if (status.b.bcnt) { if (ep->type == EP_TYPE_ISOC) { /* Call user function */ INTR_RXSTSQLVL_ISODU_Callback(); /* Copy the received buffer to the RAM */ OTGD_FS_ReadPacket((uint8_t*)(IsocBuff + (ISOC_BUFFER_SZE * IsocBufferIdx)), status.b.bcnt); ep->xfer_buff = (uint8_t*)(IsocBuff + (ISOC_BUFFER_SZE * IsocBufferIdx)); /* Check if the end of the global buffer has been reached */ if (IsocBufferIdx == (NUM_SUB_BUFFERS - 1)) { /* Reset the buffer index */ IsocBufferIdx = 0; } else { /* Increment the buffer index */ IsocBufferIdx ++; } } else { /* Copy the received buffer to the RAM */ OTGD_FS_ReadPacket(USBD_Data_Buffer, status.b.bcnt); ep->xfer_buff = USBD_Data_Buffer; } /* Update the endpoint structure */ ep->xfer_len = status.b.bcnt; ep->xfer_count += status.b.bcnt; } break; case STS_XFER_COMP: break; case STS_SETUP_COMP: break; case STS_SETUP_UPDT: /* Copy the setup packet received in Fifo into the setup buffer in RAM */ OTGD_FS_ReadPacket(USBD_Data_Buffer, 8); ep->xfer_buff = USBD_Data_Buffer; ep->xfer_count += status.b.bcnt; ep->xfer_len = status.b.bcnt; break; default: break; } /* Call the user function */ INTR_RXSTSQLVL_Callback(); /* Enable the Rx Status Queue Level interrupt */ MODIFY_REG32( &core_regs.common_regs->int_msk, 0, int_mask.d32); /* Clear interrupt: this is a read only bit, it cannot be cleared by register access */ /* int_sts.d32 = 0; int_sts.b.rxstsqlvl = 1; WRITE_REG32 (&core_regs.common_regs->int_sts, int_sts.d32); */ return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_NPTxFE_ISR * Description : Handles the Non Periodic Tx FIFO Empty interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_NPTxFE_ISR(void ) { /* USB_OTG_int_sts_data gintsts; */ USB_OTG_int_msk_data gintmsk; gintmsk.d32 = 0; /* Call the user function */ INTR_NPTXFEMPTY_Callback(); gintmsk.b.nptxfempty = 1; MODIFY_REG32(&core_regs.common_regs->int_msk, gintmsk.d32, 0 ); /* Clear interrupt: This bit is a read only bit, cannot be cleared by register access */ /* gintsts.d32 = 0; gintsts.b.nptxfempty = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); */ return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_GInNakEff_ISR * Description : Handles the Global IN Endpoints NAK Effective interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_GInNakEff_ISR(void) { /* USB_OTG_int_sts_data gintsts; */ /* Call user function */ INTR_GINNAKEFF_Callback(); /* Clear interrupt: This is a read only bit, it cannot be cleared by register access */ /* gintsts.d32 = 0; gintsts.b.ginnakeff = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); */ return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_GOutNakEff_ISR * Description : Handles the Global OUT Endpoints NAK Effective interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_GOutNakEff_ISR(void) { /* USB_OTG_int_sts_data gintsts; */ /* Call user function */ INTR_GOUTNAKEFF_Callback(); /* Clear interrupt: This is a read only bit, it cannot be cleared by register access */ /* gintsts.d32 = 0; gintsts.b.goutnakeff = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); */ return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_EarlySuspend_ISR * Description : Handles the Early Suspend detected interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_EarlySuspend_ISR(void ) { USB_OTG_int_sts_data gintsts; USB_OTG_int_msk_data gintmsk; gintmsk.d32 = 0; /* Call user function */ INTR_ERLYSUSPEND_Callback(); gintmsk.b.erlysuspend = 1; MODIFY_REG32(&core_regs.common_regs->int_msk, gintmsk.d32, 0 ); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.erlysuspend = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_USBSuspend_ISR * Description : Handles the Suspend condition detected interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_USBSuspend_ISR(void) { USB_OTG_int_sts_data gintsts; /* Call user function */ INTR_USBSUSPEND_Callback(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.usbsuspend = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_UsbReset_ISR * Description : This interrupt occurs when a USB Reset is detected. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_UsbReset_ISR(void) { USB_OTG_dev_all_int_data daintmsk; USB_OTG_dev_out_ep_msk_data doepmsk; USB_OTG_dev_in_ep_msk_data diepmsk; USB_OTG_dev_cfg_data dcfg; USB_OTG_dev_ctl_data dctl; USB_OTG_int_sts_data gintsts; daintmsk.d32 = 0; doepmsk.d32 = 0; diepmsk.d32 = 0; dcfg.d32 = 0; dctl.d32 = 0; /* Clear the Remote Wakeup Signalling */ dctl.b.rmtwkupsig = 1; MODIFY_REG32(&core_regs.dev_regs->dev_ctl, dctl.d32, 0 ); /* Flush the NP Tx FIFO */ OTGD_FS_FlushTxFifo( 0 ); daintmsk.b.inep0 = 1; daintmsk.b.outep0 = 1; WRITE_REG32( &core_regs.dev_regs->dev_all_int_msk, daintmsk.d32 ); doepmsk.b.setup = 1; doepmsk.b.xfercompl = 1; doepmsk.b.ahberr = 1; doepmsk.b.epdisabled = 1; WRITE_REG32( &core_regs.dev_regs->dev_out_ep_msk, doepmsk.d32 ); diepmsk.b.xfercompl = 1; diepmsk.b.timeout = 1; diepmsk.b.epdisabled = 1; diepmsk.b.ahberr = 1; diepmsk.b.intknepmis = 1; WRITE_REG32( &core_regs.dev_regs->dev_in_ep_msk, diepmsk.d32 ); /* Reset Device Address */ dcfg.d32 = READ_REG32( &core_regs.dev_regs->dev_cfg); dcfg.b.devaddr = 0; WRITE_REG32( &core_regs.dev_regs->dev_cfg, dcfg.d32); /* setup EP0 to receive SETUP packets */ OTGD_FS_PCD_EP0_OutStart(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.usbreset = 1; WRITE_REG32 (&core_regs.common_regs->int_sts, gintsts.d32); /* Call the user reset function */ OTGD_FS_DEVICE_RESET; /* Call user function */ INTR_USBRESET_Callback(); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_EnumDone_ISR * Description : Reads the device status register and set the device speed * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_EnumDone_ISR(void) { USB_OTG_int_sts_data gintsts; USB_OTG_usb_cfg_data gusbcfg; OTGD_FS_EP0Activate(); /* Set USB turnaround time based on device speed and PHY interface. */ gusbcfg.d32 = READ_REG32(&core_regs.common_regs->usb_cfg); /* Full or low speed */ if ( OTGD_FS_PCD_GetDeviceSpeed() == USB_SPEED_FULL) { gusbcfg.b.usbtrdtim = 9; } WRITE_REG32(&core_regs.common_regs->usb_cfg, gusbcfg.d32); /* Call user function */ INTR_ENUMDONE_Callback(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.enumdone = 1; WRITE_REG32( &core_regs.common_regs->int_sts, gintsts.d32 ); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_IsoOutDrop_ISR * Description : Handles the Isochrounous Out packet Dropped interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_IsoOutDrop_ISR(void) { USB_OTG_int_sts_data gintsts; /* Call user function */ INTR_ISOOUTDROP_Callback(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.isooutdrop = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_EOPF_ISR * Description : Handles the Expexted End Of Periodic Frame interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_EOPF_ISR(void ) { USB_OTG_int_sts_data gintsts; USB_OTG_int_msk_data gintmsk; gintmsk.d32 = 0; gintmsk.b.eopframe = 1; MODIFY_REG32(&core_regs.common_regs->int_msk, gintmsk.d32, 0 ); /* Call user function */ INTR_EOPFRAME_Callback(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.eopframe = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_EPMismatch_ISR * Description : Handles the Endpoint Mismatch error interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_EPMismatch_ISR(void) { USB_OTG_int_sts_data gintsts; /* Call user function */ INTR_EPMISMATCH_Callback(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.epmismatch = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_InEP_ISR * Description : Handles all IN endpoints interrupts. * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_InEP_ISR(void) { USB_OTG_dev_in_ep_int_data diepint; uint32_t ep_intr; uint32_t epnum = 0; USB_OTG_EP *ep; uint32_t fifoemptymsk; diepint.d32 = 0; ep_intr = OTGD_FS_ReadDevAllInEPItr(); while ( ep_intr ) { if (ep_intr&0x1) /* In ITR */ { ep = OTGD_FS_PCD_GetInEP(epnum); diepint.d32 = OTGD_FS_PCD_ReadDevInEP(ep); /* Get In ITR status */ if ( diepint.b.xfercompl ) { fifoemptymsk = 0x1 << ep->num; MODIFY_REG32(&core_regs.dev_regs->dev_fifo_empty_msk, fifoemptymsk, 0); /* Clear the Interrupt flag */ CLEAR_IN_EP_INTR(epnum, xfercompl); if (epnum == 0) { /* Call the core IN process for EP0 */ In0_Process(); /* before terminate set Tx & Rx status */ OTG_DEV_SetEPRxStatus(epnum, SaveRState); OTG_DEV_SetEPTxStatus(epnum, SaveTState); } else { OTG_DEV_SetEPTxStatus(EP1_IN, DEV_EP_TX_NAK); (*pEpInt_IN[epnum -1])(); /* Toggle Endpoint frame ID */ if (ep->even_odd_frame == 0) ep->even_odd_frame = 1; else ep->even_odd_frame = 0; } } if ( diepint.b.ahberr ) { CLEAR_IN_EP_INTR(epnum, ahberr); } if ( diepint.b.timeout ) { CLEAR_IN_EP_INTR(epnum, timeout); } if (diepint.b.intktxfemp) { CLEAR_IN_EP_INTR(epnum, intktxfemp); } if (diepint.b.intknepmis) { CLEAR_IN_EP_INTR(epnum, intknepmis); } if (diepint.b.inepnakeff) { CLEAR_IN_EP_INTR(epnum, inepnakeff); } if (diepint.b.emptyintr) { if ((epnum == 0) || (OTG_DEV_GetEPTxStatus(epnum) == DEV_EP_TX_VALID)) { OTGD_FS_PCD_WriteEmptyTxFifo(epnum); } CLEAR_IN_EP_INTR(epnum, emptyintr); } if ( diepint.b.epdisabled ) { /* Reset Endpoint Frame ID to 0 */ ep->even_odd_frame = 0; CLEAR_IN_EP_INTR(epnum, epdisabled); } } epnum++; ep_intr >>= 1; } /* Call user function */ INTR_INEPINTR_Callback(); 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; USB_OTG_dev_out_ep_int_data 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 = OTGD_FS_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.epdisabled ) { /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(epnum, epdisabled); } /* AHB Error */ if ( doepint.b.ahberr ) { CLEAR_OUT_EP_INTR(epnum, ahberr); } /* 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); } } epnum++; ep_intr >>= 1; } /* Call user function */ INTR_OUTEPINTR_Callback(); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_IncomplIsoIn_ISR * Description : Handles the Incomplete Isochrous IN tranfer error interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_IncomplIsoIn_ISR(void) { USB_OTG_int_sts_data gintsts; /* Call user function */ INTR_INCOMPLISOIN_Callback(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.incomplisoin = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_IncomplIsoOut_ISR * Description : Handles the Incomplete Isochrous OUT tranfer error interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_IncomplIsoOut_ISR(void) { USB_OTG_int_sts_data gintsts; /* Call user function */ INTR_INCOMPLISOOUT_Callback(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.outepintr = 1; WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_Handle_Wakeup_ISR * Description : Handles the Wakeup or Remote Wakeup detected interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_Wakeup_ISR(void) { USB_OTG_int_sts_data gintsts; /* Call user function */ INTR_WKUPINTR_Callback(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.wkupintr = 1; WRITE_REG32 (&core_regs.common_regs->int_sts, gintsts.d32); return 1; } /******************************************************************************* * Function Name : OTGD_FS_PCD_GetDeviceSpeed * Description : Get the device speed from the device status register * Input : None * Output : None * Return : The Device speed value. *******************************************************************************/ static enum usb_device_speed OTGD_FS_PCD_GetDeviceSpeed(void) { USB_OTG_dev_sts_data dsts; enum usb_device_speed speed = USB_SPEED_UNKNOWN; dsts.d32 = READ_REG32(&core_regs.dev_regs->dev_sts); switch (dsts.b.enumspd) { case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: speed = USB_SPEED_HIGH; break; case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: case DSTS_ENUMSPD_FS_PHY_48MHZ: speed = USB_SPEED_FULL; break; case DSTS_ENUMSPD_LS_PHY_6MHZ: speed = USB_SPEED_LOW; break; } return speed; } /******************************************************************************* * Function Name : OTGD_FS_PCD_ReadDevInEP * Description : Reads all the Endpoints flags. * Input : None * Output : None * Return : Status *******************************************************************************/ static uint32_t OTGD_FS_PCD_ReadDevInEP( USB_OTG_EP *ep) { uint32_t v, msk, emp; msk = READ_REG32(&core_regs.dev_regs->dev_in_ep_msk); emp = READ_REG32(&core_regs.dev_regs->dev_fifo_empty_msk); msk |= ((emp >> ep->num) & 0x1) << 7; v = READ_REG32(&core_regs.inep_regs[ep->num]->dev_in_ep_int) & msk; return v; } /******************************************************************************* * Function Name : OTGD_FS_PCD_WriteEmptyTxFifo * Description : Checks Fifo for the next packet to be loaded. * Input : None * Output : None * Return : Status *******************************************************************************/ static uint32_t OTGD_FS_PCD_WriteEmptyTxFifo(uint32_t epnum) { USB_OTG_dev_tx_fifo_sts_data txstatus; USB_OTG_EP *ep; uint32_t len = 0; uint32_t dwords; USB_OTG_dev_ep_ctl_data depctl; txstatus.d32 = 0; ep = OTGD_FS_PCD_GetInEP(epnum); len = ep->xfer_len - ep->xfer_count; if (len > ep->maxpacket) { len = ep->maxpacket; } dwords = (len + 3) / 4; txstatus.d32 = READ_REG32( &core_regs.inep_regs[epnum]->dev_tx_fifo_sts); /* Manage the case of 0-length data packets toggling data PID */ if ((ep->xfer_len == 0) && (ep->xfer_count == 0)) { if (ep->num > 0) { depctl.d32 = READ_REG32( &core_regs.inep_regs[epnum]->dev_in_ep_ctl); if (ep->even_odd_frame == 1) { depctl.b.setd0pid = 0; depctl.b.setd1pid = 1; } else { depctl.b.setd0pid = 1; depctl.b.setd1pid = 0; } WRITE_REG32( &core_regs.inep_regs[epnum]->dev_in_ep_ctl, depctl.d32); } } while (txstatus.b.txfspcavail > dwords && ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) { if (ep->num > 0) { depctl.d32 = READ_REG32( &core_regs.inep_regs[epnum]->dev_in_ep_ctl); if (ep->even_odd_frame == 0) { depctl.b.setd0pid = 1; depctl.b.setd1pid = 0; } else { depctl.b.setd0pid = 0; depctl.b.setd1pid = 1; } WRITE_REG32( &core_regs.inep_regs[epnum]->dev_in_ep_ctl, depctl.d32); } /* Write the FIFO */ len = ep->xfer_len - ep->xfer_count; if (len > ep->maxpacket) { len = ep->maxpacket; } dwords = (len + 3) / 4; OTGD_FS_WritePacket(ep->xfer_buff, epnum, len); ep->xfer_count += len; txstatus.d32 = READ_REG32(&core_regs.inep_regs[epnum]->dev_tx_fifo_sts); } return 1; } #endif /* STM32F10X_CL */ /******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/