/******************************************************************************* * Function Name : PCD_WriteEmptyTxFifo * Description : Checks Fifo for the next packet to be loaded. * Input : None * Output : None * Return : Status *******************************************************************************/ static uint32_t PCD_WriteEmptyTxFifo(uint32_t epnum) { USB_OTG_DTXFSTS_TypeDef txstatus; USB_OTG_EP *ep; uint32_t len = 0; uint32_t dwords = 0; uint32_t fifoemptymsk = 0; txstatus.d32 = 0; ep = PCD_GetInEP(epnum); len = ep->xfer_len - ep->xfer_count; if (len > ep->maxpacket) { len = ep->maxpacket; } dwords = (len + 3) / 4; txstatus.d32 = USB_OTG_READ_REG32( &USB_OTG_FS_regs.DINEPS[epnum]->DTXFSTSx); while ((txstatus.b.txfspcavail > dwords) && (ep->xfer_count < ep->xfer_len) && (ep->xfer_len) != 0) { 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; ep->xfer_buff += len; txstatus.d32 = USB_OTG_READ_REG32(&USB_OTG_FS_regs.DINEPS[epnum]->DTXFSTSx); /* Mask the TxFIFOEmpty interrupt to prevent re-entring this routine */ if (ep->xfer_len == ep->xfer_count) { fifoemptymsk = 0x1 << ep->num; USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DIEPEMPMSK, fifoemptymsk, 0); } } return 1; }
/******************************************************************************* * Function Name : OTGD_FS_EPStartXfer * Description : Handle the setup for data xfer for an EP and starts the xfer * Input : None * Output : None * Return : status *******************************************************************************/ USB_OTG_Status OTGD_FS_EPStartXfer(USB_OTG_EP *ep) { USB_OTG_DSTS_TypeDef dsts; USB_OTG_Status status = USB_OTG_OK; __IO USB_OTG_DEPCTLx_TypeDef depctl; OTG_FS_DEPTSIZx_TypeDef deptsiz; depctl.d32 = 0; deptsiz.d32 = 0; /* IN endpoint */ if (ep->is_in == 1) { depctl.d32 = USB_OTG_READ_REG32(&(USB_OTG_FS_regs.DINEPS[ep->num]->DIEPCTLx)); deptsiz.d32 = USB_OTG_READ_REG32(&(USB_OTG_FS_regs.DINEPS[ep->num]->DIEPTSIZx)); /* Zero Length Packet? */ if (ep->xfer_len == 0) { deptsiz.b.xfersize = 0; deptsiz.b.pktcnt = 1; } else { /* Program the transfer size and packet count * as follows: xfersize = N * maxpacket + * short_packet pktcnt = N + (short_packet * exist ? 1 : 0) */ deptsiz.b.xfersize = ep->xfer_len; deptsiz.b.pktcnt = (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; if (ep->type == EP_TYPE_ISOC) { deptsiz.b.mcount = 1; } } USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.DINEPS[ep->num]->DIEPTSIZx, deptsiz.d32); if (ep->type != EP_TYPE_ISOC) { /* Enable the Tx FIFO Empty Interrupt for this EP */ uint32_t fifoemptymsk = 0; fifoemptymsk = 1 << ep->num; USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DIEPEMPMSK, 0, fifoemptymsk); } /* EP enable, IN data in FIFO */ depctl.b.cnak = 1; depctl.b.epena = 1; if (ep->type == EP_TYPE_ISOC) { dsts.d32 = USB_OTG_READ_REG32(&USB_OTG_FS_regs.DEV->DSTS); if (((dsts.b.soffn)&0x1)==0) { depctl.b.setoddfrm=1; } else { depctl.b.setd0pid=1; } } USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.DINEPS[ep->num]->DIEPCTLx, depctl.d32); if (ep->type == EP_TYPE_ISOC) { /*write buffer in TXFIFO*/ /* user should ensure that ep->xfer_len <= ep->maxpacket */ OTGD_FS_WritePacket(ep->xfer_buff, ep->num, ep->xfer_len); } } else { /* OUT endpoint */ depctl.d32 = USB_OTG_READ_REG32(&(USB_OTG_FS_regs.DOUTEPS[ep->num]->DOEPCTLx)); deptsiz.d32 = USB_OTG_READ_REG32(&(USB_OTG_FS_regs.DOUTEPS[ep->num]->DOEPTSIZx)); /* Program the transfer size and packet count as follows: * pktcnt = N * xfersize = N * maxpacket */ if (ep->xfer_len == 0) { deptsiz.b.xfersize = ep->maxpacket; deptsiz.b.pktcnt = 1; } else { deptsiz.b.pktcnt = (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; } USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.DOUTEPS[ep->num]->DOEPTSIZx, deptsiz.d32); if (ep->type == EP_TYPE_ISOC) { if (ep->even_odd_frame) { depctl.b.setoddfrm = 1; } else { depctl.b.setd0pid = 1; } } /* EP enable */ depctl.b.cnak = 1; depctl.b.epena = 1; USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.DOUTEPS[ep->num]->DOEPCTLx, depctl.d32); } return status; }