561 lines
14 KiB
C
561 lines
14 KiB
C
/********************************************************************************
|
||
* 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<len;i++)
|
||
{
|
||
buf[i] = g_abUsbEp0Buf[(i & (EP0PKTSIZE - 1))];
|
||
|
||
if(i == (len-1))
|
||
{
|
||
EP0SENDNAK; // send NAK
|
||
break;
|
||
}
|
||
|
||
if((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<len;i++)
|
||
buf[i] = USBEPDAT_B(ep);
|
||
#endif
|
||
// EP1BUF0CLR; // Clear buffer 0,
|
||
return len; // return receive data len
|
||
}
|
||
|
||
/***************************************************************************
|
||
* Function: usbEpTxAll
|
||
* Description: USB Epn except Ep0 Rx last all data
|
||
* Input: ep : the number of ep,form 1 to 8
|
||
buf : Receive data memory address
|
||
len : last all data length
|
||
* Output: NULL
|
||
* Return: Receive data length
|
||
* Other: NULL
|
||
**************************************************************************/
|
||
u16 usbEpnRxLastAllData(u8 ep, u8 * buf,u16 len)
|
||
{
|
||
#if !DYNAMICFIFO
|
||
u16 i;
|
||
#endif
|
||
u16 rxlen = 0, pktlen = 0;
|
||
u32 tempEpStat;
|
||
u16 maxpacketsize = USBMAXPKTSIZE(ep);
|
||
|
||
if(len == 0)
|
||
{
|
||
EPBUF0CLR(ep);
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
#if DYNAMICFIFO
|
||
USBEPBF(ep) = (u32)buf;
|
||
EPBUF0CLR(ep); // Clear buffer 0
|
||
#endif
|
||
|
||
while(rxlen != len)
|
||
{
|
||
while(!(USBEPSTS(ep)&Bit0_En))
|
||
{;}
|
||
tempEpStat = USBEPSTS(ep);
|
||
pktlen = (tempEpStat >> 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<pktlen;i++)
|
||
buf[rxlen+i] = USBEPDAT_B(ep);
|
||
#endif
|
||
}
|
||
else if(pktlen > 0)
|
||
{
|
||
#if DYNAMICFIFO
|
||
EPBUF0CLR(ep); // Clear buffer 0
|
||
#else
|
||
for(i=0;i<pktlen;i++)
|
||
buf[rxlen+i] = USBEPDAT_B(ep);
|
||
#endif
|
||
}
|
||
else // Zero-length pkt
|
||
{
|
||
EPBUF0CLR(ep); // Clear buffer 0
|
||
}
|
||
rxlen += pktlen;
|
||
}
|
||
}
|
||
#if DYNAMICFIFO
|
||
USBEPBF(ep) = (u32)buf;
|
||
#endif
|
||
return rxlen;
|
||
}
|
||
|
||
/***************************************************************************
|
||
* Function: usbEp0Tx
|
||
* Description: USB Ep0 tx one packet data
|
||
* Input: buf : transmit data memory address
|
||
len : transmit data length
|
||
* Output: NULL
|
||
* Return: NULL
|
||
* Other: NULL
|
||
**************************************************************************/
|
||
static void usbEp0Tx(u8 * buf,u8 len)
|
||
{
|
||
#if !DYNAMICFIFO
|
||
u8 i;
|
||
#endif
|
||
|
||
USBCECON |= Bit11_En; // Clear Buffer 1
|
||
#if DYNAMICFIFO
|
||
USBCEBF = (u32)buf;
|
||
|
||
USBCESTS_B3 = 0x08;
|
||
USBCESTS_B2 = (len << 4); // BF1VENTRS,low 4-bit
|
||
USBCESTS_B3 = (len >> 4); // BF1VENTRS,high 4-bit
|
||
#else
|
||
for(i=0;i<len;i++)
|
||
USBCEDAT_B = buf[i];
|
||
#endif
|
||
if(len <= EP0PKTSIZE) // Short pkt
|
||
{
|
||
EP0SENDACK; // set 'send ACK' mode, <20><>ΪӲ<CEAA><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD><EFBFBD>ÿ<EFBFBD>ζ<EFBFBD><CEB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
}
|
||
|
||
while(!(USBCESTS & Bit1_En))
|
||
{;} // Waiting for short pkt is transmitted successfully
|
||
EP0CXDPKTCLR; //д1 <20><><EFBFBD><EFBFBD>!// Clear the CXDPKT flag after short pkt is sent
|
||
// USBCESTS_B2 &= 0x0F; // clear BF1VENTRS,low 4-bit
|
||
// USBCESTS_B3 &= 0xF0; // clear BF1VENTRS,high 4-bit
|
||
}
|
||
|
||
/***************************************************************************
|
||
* Function: usbEp0TxAll
|
||
* Description: USB Ep0 Tx all data
|
||
* Input: buf : transmit data memory address
|
||
len : transmit data length
|
||
* Output: NULL
|
||
* Return: NULL
|
||
* Other: NULL
|
||
**************************************************************************/
|
||
static void usbEp0TxAll(u8 * buf,u16 len)
|
||
{
|
||
if(len == 0)
|
||
{
|
||
usbEp0Tx(buf,0);
|
||
}
|
||
else
|
||
{
|
||
while(len)
|
||
{
|
||
if(len > 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<len;i++)
|
||
USBEPDAT_B(ep) = buf[i];
|
||
#endif
|
||
if(len < USBMAXPKTSIZE(ep))
|
||
EPPKTRDY(ep); // buf 0 ready
|
||
while(USBEPSTS(ep) & Bit19_En)
|
||
{;}
|
||
EPDPKTCLR(ep); // Clear DPKT interrupt
|
||
}
|
||
|
||
|
||
/***************************************************************************
|
||
* Function: usbEpTxAll
|
||
* Description: USB Epn except Ep0 Tx all data
|
||
* 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
|
||
**************************************************************************/
|
||
|
||
#define USB_SEND_WAIT_CNT 600000 //50ms 12000*50
|
||
static void usbEpTxAll(u8 ep, u8 * buf, u16 len)
|
||
{
|
||
u16 maxpacketsize = USBMAXPKTSIZE(ep);
|
||
#if DYNAMICFIFO
|
||
USBEPBF(ep) = (u32)buf;
|
||
|
||
if(len == 0)
|
||
{
|
||
EPPKTLENL(ep) = 0;
|
||
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;
|
||
}
|
||
}
|
||
|
||
EPDPKTCLR(ep); // Clear DPKT interrupt
|
||
}
|
||
else
|
||
{
|
||
while(len)
|
||
{
|
||
EPDPKTCLR(ep); // Clear DPKT interrupt <20>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD>
|
||
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;
|
||
}
|
||
//<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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<len;i++)
|
||
USBEPDAT_B(ep) = buf[i];
|
||
EPPKTRDY(ep); // buf 0 ready
|
||
len = 0;
|
||
}
|
||
while(USBEPSTS(ep) & Bit19_En)
|
||
{;}
|
||
EPDPKTCLR(ep); // Clear DPKT interrupt
|
||
}
|
||
}
|
||
#endif
|
||
}
|