TMC32_QJB/USB/USB_ep.c
2026-04-30 16:23:12 +08:00

561 lines
14 KiB
C
Raw Permalink Blame History

/********************************************************************************
* 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
}