/******************************************************************************** * Copyright (c) 2012, Beijing Tongfang Microelectroics Co., Ltd. * All rights reserved. * Module: USB * Author: Yang Song * Version: V1.0 * History: * 2012-09-24 Original version ********************************************************************************/ #include "global.h" USB_DEVICE_REQUEST st_usbDeviceRequest; volatile u8 g_bUsbEp0TxIntFlag; u8 g_bUsbEp1RcvDataFlag; u16 g_sUsbEp2TxLen; u8 g_bUsbEp0RcvDataFlag; u16 g_sUsbEp0TxLen; // Length of Ep0 data to be transmitted u8 *g_abUsbEp0Buf = (u8 *)USBFIFO_ADDR_START; // USB Ep1 data trans buf u8 *g_abUsbEp1Buf = (u8 *)USBFIFO_ADDR_START+0x100; // USB Ep1 data trans buf u8 *g_abUsbEp2Buf = (u8 *)USBFIFO_ADDR_START+0xA00; // USB Ep2 data trans bufv u8 *g_abUsbEp3Buf = (u8 *)USBFIFO_ADDR_START+0xB00; // USB Ep2 data trans bufv #if !DYNAMICFIFO u8 *g_abUsbBuf = (u8 *)USBFIFO_ADDR_START; #endif /*************************************************************************** * Description: static function **************************************************************************/ static void usbEpTxAll(u8 ep, u8 * buf, u16 len); static void usbEpTx(u8 ep, u8 * buf,u8 len); static void usbEp0TxAll(u8 * buf,u16 len); static void usbEp0Tx(u8 * buf,u8 len); /*************************************************************************** * Function: usbEp0RxTx * Description: USB Ep0 Rx and Tx * Input: NULL * Output: NULL * Return: NULL * Other: NULL **************************************************************************/ void usbEp0RxTx(void) { u32 rcvlen; rcvlen = (USBCESTS >> 8) & 0x000003FF; // buf 0 valid enties if(EP0STSCXS) // SETUP stage,CXS interrupt { EP0SENDNAK; EP0CXSCLR; // Write 1 to clear CXS interrutp st_usbDeviceRequest.wValue = USBDCC1 >> 16; st_usbDeviceRequest.bRequest = USBDCC1 >> 8; st_usbDeviceRequest.bmRequestType = USBDCC1; st_usbDeviceRequest.wLength = USBDCC2 >> 16; st_usbDeviceRequest.wIndex = USBDCC2; if(!(st_usbDeviceRequest.bmRequestType&Bit6_En) && !(st_usbDeviceRequest.bmRequestType&Bit5_En)) // Bit6~5=00,Standard st_usbDeviceRequest.bStdRqstFlag = 1; else if(!(st_usbDeviceRequest.bmRequestType&Bit6_En) && (st_usbDeviceRequest.bmRequestType&Bit5_En)) // Bit6~5=01,Class st_usbDeviceRequest.bClsRqstFlag = 1; else if((st_usbDeviceRequest.bmRequestType&Bit6_En) && !(st_usbDeviceRequest.bmRequestType&Bit5_En)) // Bit6~5=10,Vendor st_usbDeviceRequest.bVdrRqstFlag = 1; } else if(EP0STSCXDPKT && (rcvlen > 0)) // CXDPKT interrupt,Data stage { EP0CXDPKTCLR; // Write 1 to clear CXDPKT interrutp USBCECON |= Bit10_En; // clear buf while(!(EP0STSCXSTS)) {;} EP0CXSTSCLR; // Write 1 to clear CXSTS interrupt EP0SENDACK; g_bUsbEp0RcvDataFlag = 0x01; } else if(EP0STSCXDPKT && (g_sUsbEp0TxLen > 0)) // CXDPKT interrupt,and there is data left for being transmitted { EP0CXDPKTCLR; // Write 1 to clear CXDPKT interrupt if(EP0STSCXSTS) // Status stage,CXSTS interrupt { EP0CXSTSCLR; // Write 1 to clear CXSTS interrutp if((!(USBCECON & Bit9_En)) && (USBCECON & Bit8_En)) { EP0SENDACK; // Send ACK if 0-length data packet received } else { EP0SENDNAK; // Send NAK,not complete yet } } usbEpnTxAll(0, USBbuf,g_sUsbEp0TxLen); } else if(EP0STSCXDPKT) // CXDPKT interrupt,no data left { EP0CXDPKTCLR; // Write 1 to clear CXDPKT interrutp EP0SENDACK; // Send ACK } else if(EP0STSCXSTS) // Status stage,CXSTS interrupt { EP0CXSTSCLR; // Write 1 to clear CXSTS interrupt EP0SENDACK; } } /*************************************************************************** * Function: usbEpnTx * Description: USB all Ep Tx one packet * Input: ep : the number of ep,form 0 to 8 buf : transmit data memory address len : transmit data length * Output: NULL * Return: NULL * Other: NULL **************************************************************************/ void usbEpnTx(u8 ep, u8 * buf,u8 len) { if(ep == 0) usbEp0Tx(buf,len); else usbEpTx(ep,buf,len); } /*************************************************************************** * Function: usbEpnTxAll * Description: USB all Ep Tx all data * Input: ep : the number of ep,form 0 to 8 buf : transmit data memory address len : transmit data length * Output: NULL * Return: NULL * Other: NULL **************************************************************************/ void usbEpnTxAll(u8 ep, u8 * buf, u16 len) { if(ep == 0) usbEp0TxAll(buf,len); else usbEpTxAll(ep, buf, len); } /*************************************************************************** * Function: usbEp0RxAll * Description: USB Ep0 Rx all data * Input: buf : receive data memory address len : receive data length * Output: NULL * Return: NULL * Other: NULL **************************************************************************/ void usbEp0RxAll(u8 * buf,u16 len) { u16 rcvlen; u16 i; while(!EP0STSCXDPKT); rcvlen = (USBCESTS >> 8) & 0x000003FF; // buf 0 valid enties if(rcvlen > 0) // CXDPKT interrupt,Data stage { EP0CXDPKTCLR; // Write 1 to clear CXDPKT interrutp for(i=0;i 0) && ((i + 1) % EP0PKTSIZE == 0)) { USBCECON |= Bit10_En; // Ep0 Buffer0 cleared EP0SENDACK; while(!(EP0STSCXDPKT)) {;} EP0CXDPKTCLR; EP0SENDNAK; // send NAK } } USBCECON |= Bit10_En; // clear buf while(!(EP0STSCXSTS)) {;} EP0CXSTSCLR; // Write 1 to clear CXSTS interrupt EP0SENDACK; } else // CXDPKT interrupt,no data left { EP0CXDPKTCLR; // Write 1 to clear CXDPKT interrutp EP0SENDACK; // Send ACK } } /*************************************************************************** * Function: usbEpTxAll * Description: USB Epn except Ep0 Rx first packet data * Input: ep : the number of ep,form 1 to 8 buf : Receive data memory address * Output: NULL * Return: Receive data length * Other: NULL **************************************************************************/ u8 usbEpnRxFirstPacket(u8 ep, u8 * buf) { u32 tempEpStat; u8 len; #if !DYNAMICFIFO u8 i; #endif while(!(USBEPSTS(ep)&Bit0_En)) {;} tempEpStat = USBEPSTS(ep); len = (tempEpStat >> 8) & 0x03FF; // Buf 0 valid entries,bit 8~17 of USBEP2STS EPDPKTCLR(ep); // Clear DPKT interrupt #if DYNAMICFIFO Memcpy(buf,(u8*)(USBEPBF(ep)) ,len); #else for(i=0;i> 8) & 0x03FF; // Buf 0 valid entries,bit 8~17 of USBEP2STS EPDPKTCLR(ep); // Clear DPKT interrupt if(pktlen == maxpacketsize) // whole packet length { #if DYNAMICFIFO USBEPBF(ep) += maxpacketsize; EPBUF0CLR(ep); // Clear buffer 0 #else for(i=0;i 0) { #if DYNAMICFIFO EPBUF0CLR(ep); // Clear buffer 0 #else for(i=0;i> 4); // BF1VENTRS,high 4-bit #else for(i=0;i EP0PKTSIZE) { usbEp0Tx(buf,EP0PKTSIZE); len -= EP0PKTSIZE; buf += EP0PKTSIZE; } else if(len == EP0PKTSIZE) { usbEp0Tx(buf,len); Delay(0x2000); if(!EP0STSCXSTS) usbEp0Tx(buf,0); len = 0; } else { usbEp0Tx(buf,len); len = 0; } } } } /*************************************************************************** * Function: usbEpTx * Description: USB Epn except Ep0 Tx one packet * Input: ep : the number of ep,form 1 to 8 buf : transmit data memory address len : transmit data length * Output: NULL * Return: NULL * Other: NULL **************************************************************************/ static void usbEpTx(u8 ep, u8 * buf,u8 len) { #if DYNAMICFIFO USBEPBF(ep) = (u32)buf; EPBUF0CLR(ep); // Clear Buffer 0 while(USBEPCON(ep) & Bit9_En) {;} EPPKTLENL(ep) = len; #else u8 i; EPBUF0CLR(ep); // Clear Buffer 0 while(USBEPCON(ep) & Bit9_En) {;} for(i=0;i USB_SEND_WAIT_CNT) { TimerHSIClockCount(TIM3, STOP_TIMER); break; } } EPDPKTCLR(ep); // Clear DPKT interrupt } else { while(len) { EPDPKTCLR(ep); // Clear DPKT interrupt 移到这里 EPBUF0CLR(ep); // Clear Buffer 0 while(USBEPCON(ep) & Bit9_En) {;} if(len > maxpacketsize) { EPPKTLENL(ep) = maxpacketsize; TimerHSIClockCount(TIM3, START_TIMER); while(USBEPSTS(ep) & Bit19_En) { if(TimerHSIClockCount(TIM3, GET_TIMER) > USB_SEND_WAIT_CNT) { TimerHSIClockCount(TIM3, STOP_TIMER); break; } } len -= maxpacketsize; USBEPBF(ep) += maxpacketsize; } else if(len == maxpacketsize) { EPPKTLENL(ep) = maxpacketsize; TimerHSIClockCount(TIM3, START_TIMER); while(USBEPSTS(ep) & Bit19_En) { if(TimerHSIClockCount(TIM3, GET_TIMER) > USB_SEND_WAIT_CNT) { TimerHSIClockCount(TIM3, STOP_TIMER); break; } } len = 0; } else { EPPKTLENL(ep) = len; EPPKTRDY(ep); // buf 0 ready TimerHSIClockCount(TIM3, START_TIMER); while(USBEPSTS(ep) & Bit19_En) { if(TimerHSIClockCount(TIM3, GET_TIMER) > USB_SEND_WAIT_CNT) { TimerHSIClockCount(TIM3, STOP_TIMER); break; } } len = 0; } //提前到函数入口 EPDPKTCLR(ep); // Clear DPKT interrupt } } #else u8 i; if(len == 0) { EPPKTRDY(ep); // buf 0 ready while(USBEPSTS(ep) & Bit19_En) {;} EPDPKTCLR(ep); // Clear DPKT interrupt } else { while(len) { // EPBUF0CLR(ep); // Clear Buffer 0 while(USBEPCON(ep) & Bit9_En) {;} if(len > maxpacketsize) { for(i=0;i<(maxpacketsize>>2);i++) USBEPDAT(ep) = *(u32 *)(buf + (i<<2)); len -= maxpacketsize; buf += maxpacketsize; } else if(len == maxpacketsize) { for(i=0;i<(maxpacketsize>>2);i++) USBEPDAT(ep) = *(u32 *)(buf + (i<<2)); len = 0; } else //if(len < transmodelen) { for(i=0;i