📄 usbd_if.c
字号:
/*
* H/W I/F process for USB Device control
* $Revision: 1.8 $ $Date: 2006/08/10 08:11:29 $
*/
/*=== Include =============================================================*/
/* #include "sprsts.h" */
#include "SPRSTS.h"
#include "usbd_if.h"
#include "Reg72V05.h"
#include "OSCall.h"
/*=== Define ==============================================================*/
/* Open */
#define MAX_OPEN (1) /* Times that Open can be done */
/* Endpoint */
#define MAX_ENDPOINT (4) /* Endpoint number related to S1R72V05 */
#define MAX_EPX (3) /* Endpoint number except for EP0 */
/* Endpoint FIFO Size */
#define MAX_FIFOSIZE (0x1200) /* FIFO Size */
/*=== Define ==============================================================*/
/* Callbacks */
#define CBINF_VBUS (0x00) /* Notification for VBUS change */
#define CBINF_DPDM (0x01) /* Notification for Reset,Suspend,Resume,ChirpCmp,ResumeCmp */
#define CBINF_RCVSOF (0x02) /* Notification for SOF's receiving */
#define CBINF_RCVSETUP (0x03) /* Notification for Request's receiving */
#define CBINF_EP0XFER (0x04) /* Notification for EP0 Handshake */
#define CBINF_EPXXFER (0x05) /* Notification for EPR Handshake */
#define CBINF_REPLYDESC (0x06) /* Notification for completion of Reply Descriptor */
#define CBINF_SETADR (0x07) /* Notification for completion of Set Address */
#define CBINF_BULKONLY (0x08) /* Notification for BulkOnly CBW,CSW */
#define MAX_CALLBACK (9) /* Number of callback */
/* Interrupt Status */
#define IS_DEVICE_INT_STAT (0x00) /* Position to save interrupt status */
#define IS_EPR_INT_STAT (0x01) /* Position to save interrupt status */
#define IS_SIE_INT_STAT (0x02) /* Position to save interrupt status */
#define IS_FIFO_INT_STAT (0x03) /* Position to save interrupt status */
#define IS_BULK_INT_STAT (0x04) /* Position to save interrupt status */
#define IS_EP0_INT_STAT (0x05) /* Position to save interrupt status */
#define IS_EPA_INT_STAT (0x06) /* Position to save interrupt status */
#define IS_EPB_INT_STAT (0x07) /* Position to save interrupt status */
#define IS_EPC_INT_STAT (0x08) /* Position to save interrupt status */
#define MAX_IS (9) /* Number of interrupt status */
/* Main Int Stat Mask */
#define MASK_MAIN_INT_STAT (0x80)
#define MASK_DEVICE_INT_STAT (0xBF) /* VBUS_Changed,D_SIE_IntStat,D_BulkIntStat,RcvEP0SETUP,D_FIFO_IntStat,D_EP0IntStat,D_EPrIntStat */
#define MASK_SIE_INT_STAT (0x7F) /* NonJ RcvSOF,DetectRESET,DetectSUSPEND,ChirpCmp,RestoreCmp,SetAddressCmp */
#define MASK_FIFO_INT_STAT (0x80) /* DescriptorCmp */
/* Main Int Stat Mask */
#define GRP_EP0_INT (BIT_OUT_ShortACK | BIT_IN_TranACK | BIT_OUT_TranACK | BIT_IN_TranNAK | BIT_OUT_TranNAK | BIT_IN_TranErr | BIT_OUT_TranErr)
#define GRP_BO_INT (BIT_CBW_Cmp | BIT_CBW_LengthErr | BIT_CBW_Err | BIT_CSW_Cmp | BIT_CSW_Err)
#define R8_ALLZERO (0x00)
#define R8_INT_ALLZERO (0xFF)
#define R16_ALLZERO (0x0000)
#define R16_INT_ALLZERO (0xFFFF)
/* EPx Handshake */
#define INT_OUTSHORTACK (0x40) /* EPx OUT Short ACK */
#define INT_INACK (0x20) /* EPx IN ACK */
#define INT_OUTACK (0x10) /* EPx OUT ACK */
#define INT_INNAK (0x08) /* EPx IN NAK */
#define INT_OUTNAK (0x04) /* EPx OUT NAK */
#define INT_INSTALL (0x02) /* EPx IN STALL */
#define INT_OUTSTALL (0x01) /* EPx OUT STALL */
/* Transfer Type */
#define EPX_CAP_CONTROL (0x01) /* Support for Control transfer */
#define EPX_CAP_BULK (0x02) /* Support for Bulk transfer */
#define EPX_CAP_INT (0x04) /* Support for Interrupt transfer */
#define EPX_CAP_ISO (0x08) /* Support for Isochronous transfer */
#define EPX_CAP_DMA (0x10) /* Support for DMA transfer */
/*=== Structure ===========================================================*/
/* Information of transfer type which can be set for EP */
typedef struct epx_capabirity {
UCHAR type; /* Transfer type */
} EPX_CAPABIRITY;
/* FIFO Area Map */
typedef struct fifo_map {
USHORT ep0Start; /* Start address of EP0 area */
USHORT ep0Size; /* Size of EP0 area */
USHORT replyStart; /* Start address of Reply Descriptor area */
USHORT replySize; /* Size of Reply Descriptor area */
USHORT cbwStart; /* Start address of CBW area */
USHORT cbwSize; /* Size of CBW area */
USHORT cswStart; /* Start address of CSW area */
USHORT cswSize; /* Size of CSW area */
USHORT epxStart[MAX_EPX]; /* Start address of EPx area */
USHORT epxSize[MAX_EPX]; /* Size of EPx area */
} FIFO_MAP;
/*=== Macro ===============================================================*/
#define IS_EPX_DIRIN(epn) (((epn) & 0x80) == 0x80 ? TRUE : FALSE)
#define IS_BIT(bits,mask) (((bits) & (mask)) != 0x00 ? TRUE : FALSE)
#define CLR_BIT(bits,mask) ((bits) = ((bits) & ~(mask)))
#define SET_BIT(bits,mask) ((bits) = ((bits) | (mask)))
/*=== Variable ============================================================*/
/* Area to save interrupt status */
static volatile UCHAR IntStat[MAX_IS];
/* Map of FIFO area */
static FIFO_MAP FifoMap;
/* USBD_IFGetFeatureMode(),USBD_IFSetFeatureMode() */
static USBD_IF_FEATURE_MODE FeatureMode;
/* Tabel of callback function */
static CALLBACK_PROC CallbackTable[MAX_CALLBACK];
/* Information of Endpoint that means whether it can be set */
static EPX_CAPABIRITY EPxCapabirity[MAX_ENDPOINT]
={
{EPX_CAP_CONTROL | EPX_CAP_DMA} , /* EP0 */
{EPX_CAP_BULK | EPX_CAP_INT | EPX_CAP_DMA}, /* EPa */
{EPX_CAP_BULK | EPX_CAP_INT | EPX_CAP_DMA}, /* EPb */
{EPX_CAP_BULK | EPX_CAP_INT | EPX_CAP_DMA}, /* EPc */
};
/* Test Packet Data */
UCHAR TestPacket[]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,
0xAA,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,
0xEE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xBF,0xDF,
0xEF,0xF7,0xFB,0xFD,0xFC,0x7E,0xBF,0xDF,
0xEF,0xF7,0xFB,0xFD,0x7E};
static volatile UCHAR tempMainIntStat,tempDeviceIntStat,tempD_SIE_IntStat,tempD_EPrIntStat,tempD_FIFO_IntStat,tempD_EP0IntStat,tempD_BulkIntStat;
static volatile UCHAR tempD_EPxIntStat[MAX_EPX];
#ifdef DEBUG_C
#define INTLOGCNT (256)
#ifdef INTLOG
static volatile UCHAR IntStatLog[INTLOGCNT][0x10];
static volatile USHORT IntStatLogCnt;
static volatile UCHAR USBD_IntProcIn;
#endif
#endif
/*=== Function Prototype ==================================================*/
static LONG InitIc(void);
static LONG InitVariables(void);
void InterruptProc(void);
static void USBD_IFISRProcess(void);
/* =============================================================================
// Function_Name: USBD_IFReset
// description : Reset USBD I/F
// argument : None
// return : STATUS_SUCCESS Finished normally
// flag :
// global :
// =============================================================================
*/
LONG USBD_IFReset(void)
{
LONG retValue;
#ifdef DEBUG_C
#ifdef INTLOG
USHORT i,j;
#endif
#endif
retValue = STATUS_SUCCESS;
do { /* Don't loop */
/* Initialize IC */
retValue = InitIc();
if (retValue != STATUS_SUCCESS) {
break;
}
/* Initialize variables */
retValue = InitVariables();
if (retValue != STATUS_SUCCESS) {
break;
}
#ifdef DEBUG_C
#ifdef INTLOG
IntStatLogCnt = 0;
for (i = 0;i < INTLOGCNT;i++) {
for (j = 0;j < 0x10;j++) {
IntStatLog[i][j] = 0;
}
}
USBD_IntProcIn = 0;
#endif
#endif
} while (0);
return retValue;
}
/* =============================================================================
// Function_Name: USBD_IFAttach
// description : Do process for Attach
// argument : None
// return : STATUS_SUCCESS Finished normally
// STATUS_NOT_OPENED Not be opened yet
// memo : Don't set detection of Suspend & Reset to Enable here
// flag :
// global :
// =============================================================================
*/
LONG USBD_IFAttach(void)
{
LONG retValue;
retValue = STATUS_SUCCESS;
do { /* Don't loop */
/* Case of connecting VBUS */
CLR_BIT(IntStat[IS_DEVICE_INT_STAT],BIT_VBUS_Changed);
/* D_USB_Status.FSxHS = 1 */
RegSet(REG08_D_USB_Status,BIT_FSxHS_FSmode); /* set FSxHS to 1 */
/* Enable the USB, forbid detection of Reset and Suspend */
RegWrite(REG08_D_NegoControl,BIT_ActiveUSB | BIT_DisBusDetect);
/*
* Because if SETUP packet has been received before receiving USB reset after Power ON,
* it must be ignored, so set OpMode to 02h.
* Set value of OpMode to 00h after USB Reset has been processed.
*/
RegWrite(REG08_D_XcvrControl,BIT_D_TermSelect_FS | BIT_D_XcvrSelect_FS | BIT_D_OpMode_DisableBitStuffing);
} while (0);
#ifdef DEBUG_C
#ifdef INTLOG
IntStatLogCnt = 0x00;
#endif
#endif
return retValue;
}
/* =============================================================================
// Function_Name: USBD_IFDetach
// description : Do process for Detach
// argument : None
// return : STATUS_SUCCESS Finished normally
// STATUS_NOT_OPENED Not be opened yet
// flag :
// global :
// =============================================================================
*/
LONG USBD_IFDetach(void)
{
LONG retValue;
UCHAR i;
retValue = STATUS_SUCCESS;
do { /* Don't loop */
RegModify(REG08_D_XcvrControl,MASK_D_OpMode,BIT_D_OpMode_NonDriving); /* Non Drive */
RegClear(REG08_D_NegoControl,BIT_EnAutoNego); /* AutoNego */
/* Clear GoChirp,RestoreUSB,InSUSPEND */
RegWrite(REG08_D_NegoControl,R8_ALLZERO); /* D_NegoControl = 0x00 */
/* D_XcvrControl = 0x41 */
RegWrite(REG08_D_XcvrControl,BIT_D_XcvrSelect_FS | BIT_D_OpMode_NonDriving);
RegWrite(REG08_D_USB_Address,R8_ALLZERO); /* USB Address 0 */
RegWrite(REG08_D_USB_Test,R8_ALLZERO); /* Clear all bits of USBTest */
/* Clear variables */
RegWrite(REG08_D_SIE_IntStat,R8_INT_ALLZERO);
CLR_BIT(IntStat[IS_DEVICE_INT_STAT],R8_ALLZERO);
IntStat[IS_SIE_INT_STAT] = R8_ALLZERO;
IntStat[IS_EPR_INT_STAT] = R8_ALLZERO;
IntStat[IS_EP0_INT_STAT] = R8_ALLZERO;
for (i = 0;i < MAX_EPX;i++) {
IntStat[IS_EPA_INT_STAT + i] = R8_ALLZERO;
}
} while (0);
return retValue;
}
/* =============================================================================
// Function_Name: USBD_IFEnableBusDetect
// description : Enable the detection of Suspend & Reset
// argument : None
// return : STATUS_SUCCESS
// STATUS_NOT_OPENED Not be opened yet
// flag :
// global :
// =============================================================================
*/
LONG USBD_IFEnableBusDetect(void)
{
LONG retValue;
retValue = STATUS_SUCCESS;
do { /* Don't loop */
RegSet(REG08_D_SIE_IntEnb,(MASK_EnDetectRESET | MASK_EnDetectSUSPEND | MASK_EnChirpCmp | MASK_EnRestoreCmp));
if ((RegRead(REG08_D_NegoControl) & MASK_EnAutoNego) != BIT_EnAutoNego) {
RegClear(REG08_D_NegoControl,BIT_DisBusDetect); /* Enable the detection of Reset and Suspend */
if (FeatureMode.DisableHS == 0) {
/* When HS Mode is enabled */
RegClear(REG08_D_NegoControl,BIT_DisableHS);
} else {
/* When HS Mode is disabled */
RegSet(REG08_D_NegoControl,BIT_DisableHS);
}
if (FeatureMode.AutoNego == 1) {
/* Enable AutoNego here */
RegSet(REG08_D_NegoControl,BIT_EnAutoNego);
}
}
} while (0);
return retValue;
}
/* =============================================================================
// Function_Name: USBD_IFRemoteWakeup
// description : Send K of Remote Wakeup and stop
// argument : USBD_IF_SIGNAL_K Send K
// USBD_IF_SIGNAL_STOP_K Stop sending of K
// return : STATUS_SUCCESS Finished normally
// STATUS_NOT_OPENED Not be opened yet
// STATUS_INVALID_PARAMETER Parameter error
// flag :
// global :
// =============================================================================
*/
LONG USBD_IFRemoteWakeup(UCHAR SignalState)
{
LONG retValue;
retValue = STATUS_SUCCESS;
do { /* Don't loop */
if (SignalState == USBD_IF_SIGNAL_K) {
RegClear(REG08_D_SIE_IntEnb,BIT_EnNonJ); /* Disable the Non_J interrupt */
RegSet(REG08_D_NegoControl,BIT_SendWakeup);
} else if (SignalState == USBD_IF_SIGNAL_STOP_K) {
RegClear(REG08_D_NegoControl,BIT_SendWakeup);
RegSet(REG08_D_SIE_IntEnb,BIT_EnNonJ); /* Enable the Non_J interrupt */
} else {
retValue = STATUS_INVALID_PARAMETER;
}
} while (0);
return retValue;
}
/* =============================================================================
// Function_Name: USBD_IFResetProcess
// description : Do process for detecting Reset
// argument : None
// return : STATUS_SUCCESS Finished normally
// STATUS_NOT_OPENED Not be opened yet
// flag :
// global :
// =============================================================================
*/
LONG USBD_IFResetProcess(void)
{
LONG retValue;
UCHAR i;
retValue = STATUS_SUCCESS;
do { /* Don't loop */
/* D_NegoControl.EnAutoNego == 0 */
if ((RegRead(REG08_D_NegoControl) & MASK_EnAutoNego) != BIT_EnAutoNego) {
/* When AutoNego is not used */
RegClear(REG08_D_NegoControl,BIT_DisBusDetect); /* Detection function of Suspend and Reset -> Disable */
/* Start Chirp */
RegSet(REG08_D_NegoControl,BIT_GoChirp);
}
/* Stop Repry Descriptor */
RegSet(REG08_D_EP0ControlOUT,BIT_AutoForceNAK);
RegClear(REG08_D_EP0Control,BIT_ReplyDescriptor_Go);
/* Clear interrupt status */
RegWrite(REG08_DeviceIntStat,BIT_RcvEP0SETUP); /* Clear RcvEP0Setup */
CLR_BIT(IntStat[IS_DEVICE_INT_STAT],BIT_D_BulkIntStat | BIT_RcvEP0SETUP | BIT_D_FIFO_IntStat | BIT_D_EP0IntStat | BIT_D_EPrIntStat);
CLR_BIT(IntStat[IS_SIE_INT_STAT],BIT_NonJ | BIT_RcvSOF | BIT_DetectRESET | BIT_DetectSUSPEND | BIT_RestoreCmp | BIT_SetAddressCmp); /* Clear others except except fot ChirpCmp */
CLR_BIT(IntStat[IS_EPR_INT_STAT],0xFF);
CLR_BIT(IntStat[IS_FIFO_INT_STAT],MASK_FIFO_INT_STAT);
CLR_BIT(IntStat[IS_EP0_INT_STAT],0xFF);
for (i = 0;i < MAX_EPX;i++) {
IntStat[IS_EPA_INT_STAT + i] = R8_ALLZERO;
}
} while (0);
return retValue;
}
/* =============================================================================
// Function_Name: USBD_IFSuspendProcess
// description : Do process for detecting Suspend
// argument : None
// return : STATUS_SUCCESS Finished normally
// STATUS_NOT_OPENED Not be opened yet
// flag :
// global :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -