www.pudn.com > USBDriver.rar > D12Driver.c


/****************************************Copyright (c)************************************************** 
**                               ¹ãÖÝÖÜÁ¢¹¦µ¥Æ¬»ú·¢Õ¹ÓÐÏÞ¹«Ë¾ 
**                                     ÑÐ    ¾¿    Ëù 
**                                        ²úÆ·Ò»²¿  
** 
**                                 http://www.zlgmcu.com 
** 
** ÎÄ   ¼þ   Ãû: D12Driver.c 
** ×îºóÐÞ¸ÄÈÕÆÚ: 2004Äê7ÔÂ2ÈÕ 
** Ãè        Êö: USBÇý¶¯³ÌÐòÈí¼þ°ü: PDIUSBD12 É豸¶ËÇý¶¯³ÌÐò Ó¦Óòã 
** °æ	     ±¾: V1.0 
**********************************************************************************************************/ 
 
#include "config.h" 
#include "D12Config.h" 
#include "D12CI.h" 
#include "D12HAL.h" 
#include "Chap_9.h" 
#include "D12Driver.h" 
 
extern EPPFLAGS bEPPflags; 
 
/** Setup°ü´¦ÀíÈÎÎñ¶ÑÕ» */ 
OS_STK  TaskSetupStk[128]; 
 
/** Setup°ü´¦ÀíÈÎÎñʼþÖ¸Õë  ***/			 
OS_EVENT *pSetup_Event; 
 
/******* PDIUSBD12¸÷¶Ëµã¶ÔÓ¦µÄ USB ½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿é *********/ 
CTRL_USB UsbRec_Ep2;				//¶Ëµã2½ÓÊÕ¿ØÖÆ¿é 
CTRL_USB UsbRec_Ep1;				//¶Ëµã1½ÓÊÕ¿ØÖÆ¿é 
 
CTRL_USB UsbSend_Ep2;				//¶Ëµã2·¢ËÍ¿ØÖÆ¿é 
CTRL_USB UsbSend_Ep1;				//¶Ëµã1·¢ËÍ¿ØÖÆ¿é 
 
/*********************************************************************** 
** º¯ÊýÃû³Æ: INT8U WritePort1(INT32U len,INT8U *sendbuff,INT16U timeout) 
** ¹¦ÄÜÃèÊö: Óö˵ã 1 ·¢ËÍlen¸ö×Ö½Ú 
** Êä¡¡Èë:   INT32U  len:	  	 ·¢Ë͵Ä×Ö½ÚÊý£¨È¡Öµ·¶Î§Îª0x00000001 ~ 0xFFFFFFFF£© 
			 INT8U   sendbuff:   ·¢ËÍ»º³åÇøÖ¸Õë 
			 INT16U  timeout:    ³¬Ê±µÈ´ýʱ¼ä, ±ØÐë´óÓÚµÈÓÚ0 
** Êä¡¡³ö:   0: ·¢Ëͳɹ¦	 > 0: ·¢ËÍʧ°Ü(´íÎóÂë) 
************************************************************************/ 
INT8U WritePort1(INT32U len,INT8U *sendbuff,INT16U timeout) 
{ 
	return (USB_WritePort(3,16,1,&UsbSend_Ep1,sendbuff,len,timeout)); 
}	//Íù¶Ëµã1(¶ËµãË÷ÒýºÅ3)·¢ËÍÊý¾Ý 
 
/*********************************************************************** 
** º¯ÊýÃû³Æ: INT8U WritePort2(INT32U len,INT8U *sendbuff,INT16U timeout) 
** ¹¦ÄÜÃèÊö: Óö˵ã 2 ·¢ËÍlen¸ö×Ö½Ú 
** Êä¡¡Èë:   INT32U  len:	      ·¢Ë͵Ä×Ö½ÚÊý£¨È¡Öµ·¶Î§Îª0x00000001 ~ 0xFFFFFFFF£© 
			 INT8U   *sendbuff:   ·¢ËÍÖ¸Õë 
			 INT16U  timeout:     ³¬Ê±Ê±¼ä, ±ØÐë´óÓÚµÈÓÚ0 
** Êä¡¡³ö:   0: ·¢Ëͳɹ¦	> 0: ·¢ËÍʧ°Ü(´íÎóÂë) 
***********************************************************************/ 
INT8U WritePort2(INT32U len,INT8U *sendbuff,INT16U timeout) 
{ 
	return (USB_WritePort(5,64,2,&UsbSend_Ep2,sendbuff,len,timeout)); 
}	//Íù¶Ëµã2(¶ËµãË÷ÒýºÅ5)·¢ËÍÊý¾Ý 
 
/********************************************************************** 
** º¯ÊýÃû³Æ: INT8U ReadPort1(INT32U len,INT8U *recbuff,INT16U timeout) 
** ¹¦ÄÜÃèÊö: ´Ó¶Ëµã 1 ¶Á³ö len¸ö×Ö½Ú 
** Êä¡¡Èë:   INT32U  len:	     Òª¶Á³öµÄ×Ö½ÚÊý£¨È¡Öµ·¶Î§Îª0x00000001 ~ 0xFFFFFFFF£© 
			 INT8U   *recbuff:   ½ÓÊÕÊý¾ÝÖ¸Õë 
			 INT16U  timeout:    ³¬Ê±Ê±¼ä, ±ØÐë´óÓÚµÈÓÚ0 
** Êä¡¡³ö:   0: ¶Á³ö³É¹¦	 > 0: ¶Á³öʧ°Ü(´íÎóÂë) 
***********************************************************************/ 
INT8U ReadPort1(INT32U len,INT8U *recbuff,INT16U timeout) 
{ 
	return (USB_ReadPort(2,&UsbRec_Ep1,len,recbuff,timeout)); 
} 
 
/********************************************************************** 
** º¯ÊýÃû³Æ: INT8U ReadPort2(INT32U len,INT8U *recbuff,INT16U timeout) 
** ¹¦ÄÜÃèÊö: ´Ó¶Ëµã 2 ¶Á³ölen¸ö×Ö½Ú 
** Êä¡¡Èë:   INT32U  len:	     Òª¶Á³öµÄ×Ö½ÚÊý£¨È¡Öµ·¶Î§Îª0x00000001 ~ 0xFFFFFFFF£© 
			 INT8U   *recbuff:   ½ÓÊÕÊý¾ÝÖ¸Õë 
			 INT16U  timeout:    ³¬Ê±Ê±¼ä, ±ØÐë´óÓÚµÈÓÚ0 
** Êä¡¡³ö:   0: ¶Á³ö³É¹¦	> 0: ¶Á³öʧ°Ü(´íÎóÂë) 
**********************************************************************/ 
INT8U ReadPort2(INT32U len,INT8U *recbuff,INT16U timeout) 
{ 
	return (USB_ReadPort(4,&UsbRec_Ep2,len,recbuff,timeout)); 
} 
 
/********************************************************************* 
** º¯ÊýÃû³Æ: INT8U Init_D12(void) 
** ¹¦ÄÜÃèÊö: ÉèÖÃD12ÓëÓ²¼þµÄÁ¬½Ó, ³õʼ»¯D12,  ¸´Î»D12 
** Êä¡¡Èë:   ÎÞ 
** Êä¡¡³ö:   0: ³õʼ»¯³É¹¦    1: ³õʼ»¯Ê§°Ü   
**********************************************************************/ 
INT8U Init_D12(void) 
{ 
	INT32U i; 
	 
	OS_ENTER_CRITICAL(); 
	 
	Init_D12Port();							//³õʼ»¯PDIUSBD12ÓëLPC2200µÄÁ¬½ÓµÄÓ²¼þÅäÖà 
	Rst_D12();								//¸´Î»PDIUSBD12 
	reconnect_USB();        				//ÖØÐÂÁ¬½ÓUSB 
	if (readchipid() != 0x1012){			//¶ÁȡоƬIDºÅ,Èç¹û²»Îª 1012H 
		OS_EXIT_CRITICAL();  
		return 1;							//Ôò¸´Î»Ê§°Ü 
	} 
	 
	bEPPflags.value = 0;					//³õʼ»¯USBʼþ±êÖ¾±äÁ¿ 
  	UsbRec_Ep1.Sem = 0;						//¶Ëµã1½ÓÊÕ×ÊÔ´ÔÊÐíʹÓà 
 	UsbRec_Ep2.Sem = 0;						//¶Ëµã1½ÓÊÕ×ÊÔ´ÔÊÐíʹÓà 
 	UsbSend_Ep1.Sem = 0;					//¶Ëµã1·¢ËÍ×ÊÔ´ÔÊÐíʹÓà 
 	UsbSend_Ep2.Sem = 0;					//¶Ëµã1·¢ËÍ×ÊÔ´ÔÊÐíʹÓà 
  	UsbRec_Ep1.Grp  = 0; 					//¶Ëµã1ÎÞÈÎÎñµÈ´ý½ÓÊÕ 
	UsbRec_Ep2.Grp  = 0;					//¶Ëµã2ÎÞÈÎÎñµÈ´ý½ÓÊÕ 
	UsbSend_Ep1.Grp = 0;					//¶Ëµã1ÎÞÈÎÎñµÈ´ý·¢ËÍ 
	UsbSend_Ep2.Grp = 0;					//¶Ëµã2ÎÞÈÎÎñµÈ´ý·¢ËÍ 
	 
    for (i = 0; i < OS_RDY_TBL_SIZE; i++){ 
    	UsbRec_Ep1.Tbl[i]  = 0;				//Çå¿Õ¶Ëµã1ºÍ2½ÓÊÕÓë·¢Ë͵ȴýÈÎÎñÁбí 
    	UsbRec_Ep2.Tbl[i]  = 0; 
		UsbSend_Ep1.Tbl[i] = 0; 
		UsbSend_Ep2.Tbl[i] = 0; 
    } 
 
 	pSetup_Event = OSSemCreate(0);			//´´½¨Setup°ü´¦ÀíÈÎÎñÐźÅÁ¿ 
 	if (pSetup_Event == NULL)				//Èç¹û·µ»ØµÄʼþÖ¸ÕëΪ¿Õ 
 	{ 
	 	OS_EXIT_CRITICAL();  
 	 	return 1;							//Ôò³õʼ»¯Ê§°Ü 
	} 
	 
	OS_EXIT_CRITICAL(); 
 	return 0;								//³õʼ»¯³É¹¦ 
} 
 
 
//×ÜÏ߸´Î»´¦Àí×Ó³ÌÐò 
void bus_reset(void) 
{ 
} 
 
//DMA½áÊø´¦Àí 
void dma_eot(void) 
{ 
} 
 
//×ÜÏß¹ÒÆð¸Ä±ä 
void usb_suspend(void) 
{ 
} 
 
/****************************************** 
** º¯ÊýÃû³Æ: void Usb_Exception(void) 
** ¹¦ÄÜÃèÊö: D12ÖжϷþÎñ³ÌÐò 
*******************************************/ 
void Usb_Exception(void) 
{ 
	INT16U i_st; 
 
	OS_ENTER_CRITICAL();;							//½øÈëD12ÖжϷþÎñ³ÌÐòʱ¹ØÖÐ¶Ï 
	i_st = D12_ReadInterruptRegister();				//¶ÁÈ¡PDIUSBD12ÖжϼĴæÆ÷Öµ 
	 
	if(i_st != 0) { 
		if(i_st & D12_INT_BUSRESET) 
			bus_reset();							//×ÜÏ߸´Î»´¦Àí 
		if(i_st & D12_INT_EOT) 
			dma_eot();								//DMA´«Êä¼¼Êõ´¦Àí 
		if(i_st & D12_INT_SUSPENDCHANGE) 
			usb_suspend();							//×ÜÏß¹ÒÆð¸Ä±ä 
		if(i_st & D12_INT_ENDP0IN) 
			ep0_txdone();							//¿ØÖƶ˵㷢ËÍÊý¾Ý´¦Àí 
		if(i_st & D12_INT_ENDP0OUT) 
			ep0_rxdone();							//¿ØÖƶ˵ã½ÓÊÕÊý¾Ý´¦Àí 
		if(i_st & D12_INT_ENDP1IN) 
			USB_WriteISR(&UsbSend_Ep1,3,16,1);		//¶Ëµã 1·¢ËÍÊý¾Ý´¦Àí 
		if(i_st & D12_INT_ENDP1OUT) 
			USB_ReadISR(&UsbRec_Ep1,2,16,1);		//¶Ëµã 1½ÓÊÕÊý¾Ý´¦Àí 
		if(i_st & D12_INT_ENDP2IN) 
			USB_WriteISR(&UsbSend_Ep2,5,64,2);		//¶Ëµã 2·¢ËÍÊý¾Ý´¦Àí 
		if(i_st & D12_INT_ENDP2OUT) 
			USB_ReadISR(&UsbRec_Ep2,4,64,2);		//¶Ëµã 2½ÓÊÕÊý¾Ý´¦Àí 
	} 
	//add for uC/OS-II 
	CLR_INTD12();									//Çå³ýPDIUSBD12µÄÖжϱêÖ¾ 
	CLR_INT();										//֪ͨÖжϽáÊø 
   			 
   	OS_EXIT_CRITICAL();							    //Í˳öD12ÖжϷþÎñ³ÌÐòʱ¿ªÖÐ¶Ï 
} 
 
/******************************************************************* 
** º¯ÊýÃû³Æ: void  TaskSetup(void *pdata) 
** ¹¦ÄÜÃèÊö: ¿ØÖÆ´«Êä´¦Àí 
** Êä	 Èë: void *pdata  ÈÎÎñ²ÎÊý 
** Êä	 ³ö: ÎÞ 
** ×¢	 Òâ: ¸ÃÈÎÎñµÄÓÅÏȼ¶Ó¦¸ßÓÚÆäËüÈÎÎñ,²ÅÄÜÔÚÈκÎÇé¿öÏ´«ÊäSetup°ü 
********************************************************************/ 
void  TaskSetup(void *pdata) 
{ 
#if OS_CRITICAL_METHOD == 3       /* Allocate storage for CPU status register */ 
	OS_CPU_SR  cpu_sr; 
#endif 
	INT8U err; 
	 
	pdata = pdata;                /* Prevent compiler warning */ 
	for (;;) 
	{ 
		OSSemPend(pSetup_Event,0,&err);		//µÈ´ýSetup°ü 
		if (err == OS_NO_ERR){				//½ÓÊÕµ½Setup°ü  
			OS_ENTER_CRITICAL();			//¹ØÖÐ¶Ï 
			control_handler();				//½øÐпØÖÆ´«Êä´¦Àí 
			OS_EXIT_CRITICAL();			    //¿ªÖÐ¶Ï 
		} 
	} 
} 
 
 
/******************************************************************************************* 
** º¯ÊýÃû³Æ:  void USB_ReadISR(CTRL_USB *pUsb,INT8U endp,INT32U eppsize,INT8U buffnums) 
** ¹¦ÄÜÃèÊö:  USB ¶Ëµã½ÓÊÕÖжϷþÎñ³ÌÐò 
** Êä¡¡  Èë:  CTRL_USB *pUsb:	USB ½ÓÊÕÓë·¢ËÍ¿ØÖƽṹÌåÖ¸Õë 
			  INT8U		endp:	¶ËµãË÷ÒýºÅ 
			  INT32U eppsize:	¶Ëµã×î´óÐÅÏ¢°ü´óС 
			  INT8U buffnums:	¸Ã¶Ëµã»º³åÇø¸öÊý(ÈçD12µÄ¶Ëµã2ÓÐÁ½¸ö½ÓÊÕ»º³åÇø)© 
** Êä¡¡  ³ö:  ÎÞ 
********************************************************************************************/ 
void USB_ReadISR(CTRL_USB *pUsb,INT8U endp,INT32U eppsize,INT8U buffnums) 
{ 
	INT8U *pBuff,endpstatus,i; 
	INT32U len; 
	 
	D12_ReadLastTransactionStatus(endp);			   //¸´Î»ÖжϼĴæÆ÷ 
	 
	if (pUsb->Grp != 0){						   	   //ÓÐÈÎÎñÔڵȴý½ÓÊÕ²ÅÔÊÐí½øÐнÓÊÕ 
		if (pUsb->Sem == 0){					   	   //¸Ã¶Ëµã½ÓÊÕ×ÊÔ´»¹Î´±»Ä³Ò»ÈÎÎñ¶ÀÕ¼ 
			pUsb->Prio = USB_GetHighPrio(pUsb);        //È¡µÈ´ýÈÎÎñÁбíÖÐÓÅÏȼ¶×î¸ßµÄÈÎÎñµÄÓÅÏȼ¶ 
			pUsb->Cnt  = 0;				   			   //½ÓÊÕ¼ÆÊýÇå0 
			pUsb->Sem  = 1; 				   		   //±êÖ¾ÓÐÈÎÎñ¶ÀÕ¼Á˸ýÓÊն˵ã 
		} 
		pBuff = pUsb->pBuff[pUsb->Prio];		  	   //µÃµ½½ÓÊÕÖ¸Õë 
 
		for (i = 0; i < buffnums; i++){											 
			len = pUsb->Max[pUsb->Prio] - pUsb->Cnt;   //¼ÆË㻹ÓжàÉÙ¸ö×Ö½Úδ½ÓÊÕ 
			if (len > 0) 
			{ 
				if (len >= eppsize)											 
					len = (INT8U)D12_ReadEndpoint(endp,(INT8U)eppsize,pBuff + pUsb->Cnt);//½ÓÊÕÕû¸ö»º³åÇø 
				else 
					len = (INT8U)D12_ReadEndpoint(endp,(INT8U)len,pBuff + pUsb->Cnt); 	 //½ÓÊÕlen¸ö×Ö½Ú 
				pUsb->Cnt = pUsb->Cnt + len;			//¼ÆÊýÆ÷¼ÓÉÏʵ¼ÊÉÏÊÕµ½µÄ×Ö½Ú 
			} 
 
			if (pUsb->Cnt >= pUsb->Max[pUsb->Prio]){	//Èç¹û½ÓÊÕÍê±Ï 
				pUsb->Max[pUsb->Prio] = 0;				//½ÓÊÕÍê³É±êÖ¾ÖÃ0,±íʾÕýÈ·½ÓÊÕ 
	   	  		pUsb->Sem  = 0;							//ÊͷŸö˵ã½ÓÊÕ×ÊÔ´ 
	   	  		USB_DelPrio(pUsb,pUsb->Prio);			//½«¸ÃÈÎÎñ´ÓµÈ´ý¶ÓÁÐÖÐɾ³ý 
	  			OSTimeDlyResume(pUsb->Prio);		    //ʹ¸Ã½ÓÊÕÈÎÎñ¾ÍÐ÷ 
	  			break; 
	  	 	} 
			endpstatus = D12_ReadEndpointStatus(endp);	//¶Á¸Ã¶Ëµã״̬¼Ä´æÆ÷ 
			if ((endpstatus & 0x60) == 0)  break;		//Èç¹û»º³åΪ¿Õ,Á¢¼´Ìø³öÑ­»· 
		}//end of for() 
	}//end of if (pUsb->Grp != 0) 
	else 
		D12_ClearBuff(endp);			//ûÓÐÈÎÎñ½ÓÊÕÊý¾Ý,Çå¿Õ¸Ã¶Ëµã½ÓÊÕ»º³åÇø 
} 
 
 
/********************************************************************************************************** 
** º¯ÊýÃû³Æ:  void USB_WriteISR(CTRL_USB *pUsb,INT8U endp,INT32U eppsize,INT8U buffnums) 
** ¹¦ÄÜÃèÊö:  USB ¶Ëµã·¢ËÍÖжϷþÎñ³ÌÐò 
** Êä¡¡  Èë:  CTRL_USB   *pUsb:	 USB ½ÓÊÕÓë·¢ËÍ¿ØÖƽṹÌåÖ¸Õë 
			  INT8U       endp:	 ¶ËµãË÷ÒýºÅ 
			  INT32U   eppsize:	 ¶Ëµã×î´óÐÅÏ¢°ü´óС 
			  INT8U   buffnums:	 ¸Ã¶Ëµã»º³åÇø¸öÊý(ÈçD12ÓÐÁ½¸ö»º³åÇø)© 
** Êä¡¡  ³ö:  ÎÞ 
***********************************************************************************************************/ 
void USB_WriteISR(CTRL_USB *pUsb,INT8U endp,INT32U eppsize,INT8U buffnums) 
{ 
	INT32U len; 
	INT8U *pBuff,i,endpstatus; 
	 
	D12_ReadLastTransactionStatus(endp);					//¸´Î»ÖжϼĴæÆ÷ 
 
	if (pUsb->Grp != 0){															 
		if (pUsb->Cnt >= pUsb->Max[pUsb->Prio]){			//¶ÀÕ¼ÈÎÎñÈ«²¿Êý¾ÝдÈ뻺³åÇø 
			endpstatus = D12_ReadEndpointStatus(endp) & 0x60; 
			if (endpstatus == 0){							//»º³åÇøÖеÄÊý¾ÝÈ«²¿·¢ËÍÍê±Ï 
				pUsb->Sem  = 0;								//ÊͷŸö˵ãµÄ·¢ËÍ×ÊÔ´ 
				pUsb->Max[pUsb->Prio] = 0;					//ÖÃÕýÈ··¢Ëͱê־Ϊ0 
				USB_DelPrio(pUsb,pUsb->Prio);				//½«¸ÃÈÎÎñ´ÓµÈ´ý¶ÓÁÐÖÐɾ³ý 
				OSTimeDlyResume(pUsb->Prio);	    		//ʹ¸ÃÈÎÎñ¾ÍÐ÷ 
			}else 
				return; 
		} 
	} 
	else 
  		return; 
  	 
  	if (pUsb->Grp != 0){									//»¹ÓÐÈÎÎñÔڵȴý·¢ËÍÊý¾Ý 
    		if (pUsb->Sem == 0){							//¸Ã·¢ËͶ˵ã¿ÉÒÔʹÓà 
			pUsb->Prio = USB_GetHighPrio(pUsb); 
			pUsb->Cnt  = 0;									//·¢ËͼÆÊýÇå0 
			pUsb->Sem  = 1; 								//ʹ¸ÃÈÎÎñ¶ÀÕ¼¸Ã·¢ËÍ×ÊÔ´ 
		} 
		pBuff = pUsb->pBuff[pUsb->Prio];					//µÃµ½·¢ËÍ»º³åÇøÖ¸Õë 
 
		for (i = 0; i < buffnums; i++){ 
			endpstatus = D12_ReadEndpointStatus(endp) & 0x60; 
			if (endpstatus == 0x60)  break;					//Èç¹û»º³åÇøÈ«²¿¶¼Âú,ÄÇô²»¿ÉÒÔÔÙдÈë 
				 
			len = pUsb->Max[pUsb->Prio] - pUsb->Cnt; 
			if (len > 0){					   				//ÓпյĻº³åÇø¶øÇҵȴý·¢ËÍ×Ö½ÚÊý´óÓÚ0 
				if (len >= eppsize)			   				//дÂú»º³åÇø 
					len = D12_WriteEndpoint(endp,(INT8U)eppsize,pBuff + pUsb->Cnt);  
				else						   				//дlen¸ö×Ö½Ú 
					len = D12_WriteEndpoint(endp,(INT8U)len,pBuff + pUsb->Cnt);   
				pUsb->Cnt = pUsb->Cnt + len;      			//·¢ËͼÆÊýÆ÷¼ÓÉÏʵ¼ÊÉÏ·¢Ë͵Ä×Ö½Ú 
			}//end of if (len > 0) 
		}//end of for()	 
	}//end of if (pUsb->Grp != 0)	 
} 
 
/********************************************************************************** 
** º¯ÊýÃû³Æ: INT8U USB_ReadPort(INT8U endp,CTRL_USB *pUsb,INT32U len,INT8U *recbuff,INT16U timeout) 
** ¹¦ÄÜÃèÊö: ¶Á¶Ëµãº¯Êý 
** Êä	 Èë: INT8U endp:	  ¶ËµãË÷ÒýºÅ		 
			 CTRL_USB *pUsb:  USB ½ÓÊÕÓë·¢ËÍ¿ØÖÆ¿éÖ¸Õë 
			 INT32U     len:  ½ÓÊÕ×Ö½Ú¸öÊý 
			 INT8U *recbuff:  ½ÓÊÕ»º³åÇø 
			 INT16U	timeout:  µÈ´ý³¬Ê±Ê±¼ä 
** Êä	 ³ö: 0:	¶Á³É¹¦       > 0 ¶Áʧ°Ü(´íÎóÂë) 
**********************************************************************************/ 
INT8U USB_ReadPort(INT8U endp,CTRL_USB *pUsb,INT32U len,INT8U *recbuff,INT16U timeout) 
{ 
	INT8U err; 
	 
	err = USB_RW_Param(pUsb,len,recbuff);		//ÌîдUSB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿é²ÎÊý 
	if (err != USB_NO_ERR)   return err;	 
	 
	OS_ENTER_CRITICAL(); 
	if (pUsb->Max[OSPrioCur] != 0){				//Èç¹û»¹Ã»½ÓÊÕÍê³É 
		OS_EXIT_CRITICAL(); 
		OSTimeDly(timeout);						//¶¨Ò峬ʱµÈ´ý 
	}	 
	OS_EXIT_CRITICAL(); 
	 
	return (USB_RW_Result(endp,pUsb,timeout));	//·µ»Ø½ÓÊÕ½á¹û 
} 
 
/***************************************************************** 
** º¯ÊýÃû³Æ: INT8U USB_WritePort(INT8U endp,INT32U eppsize,INT8U buffnums,CTRL_USB *pUsb, 
								 INT8U *sendbuff,INT32U len,INT16U timeout) 
** ¹¦ÄÜÃèÊö:  
** Êä	 Èë: INT8U endp		  : ¶ËµãË÷ÒýºÅ 
			 INT32U eppsize   : ¸Ã¶ËµãµÄµÄÐÅÏ¢°ü´óС 
			 INT8U buffnums   : ¸Ã¶Ëµã·¢ËÍ»º³åÇø¸öÊý 
			 CTRL_USB *pUsb   : ¸Ã¶ËµãµÄ½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éÖ¸Õë 
			 INT8U  *sendbuff : ·¢ËÍÊý¾Ý×Ö½ÚÖ¸Õë 
			 INT32U   len	  : ·¢ËÍÊý¾Ý×Ö½Ú³¤¶È 
			 INT16U	timeout	  : µÈ´ý³¬Ê±Ê±¼ä 
** Êä	 ³ö: 0   ·¢Ëͳɹ¦    > 0 ·¢ËÍʧ°Ü(´íÎóÂë) 
******************************************************************/ 
INT8U USB_WritePort(INT8U endp,INT32U eppsize,INT8U buffnums,CTRL_USB *pUsb, 
					INT8U *sendbuff,INT32U len,INT16U timeout) 
{ 
	INT8U err,i; 
	INT32U length; 
 
	err = USB_RW_Param(pUsb,len,sendbuff);		//ÌîдUSB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿é²ÎÊý 
	if (err != USB_NO_ERR)   return err; 
 
	OS_ENTER_CRITICAL(); 
    if (pUsb->Sem == 0){			  			//¸Ã¶ËµãûÓб»¶ÀÕ¼ 
		pUsb->Sem  = 1;				    		//¶ÀÕ¼¸Ã¶Ëµã 
		pUsb->Cnt  = 0;							//·¢ËͼÆÊýÖµÇå0 
		pUsb->Prio = OSPrioCur; 				//±£´æ¶ÀÕ¼¸Ã¶ËµãµÄÈÎÎñÓÅÏȼ¶ 
 
		for (i = 0; i < buffnums; i++){										 
			length = pUsb->Max[pUsb->Prio] - pUsb->Cnt;	//¼ÆËãδ·¢ËÍ×Ö½Ú¸öÊý 
			if (length > 0){							//δ·¢ËÍ×Ö½ÚÊý´óÓÚ0 
				if (length >= eppsize)					//дÂú»º³åÇø 
					length = D12_WriteEndpoint(endp,(INT8U)eppsize,sendbuff + pUsb->Cnt); 
				else									//дlength¸ö×Ö½Ú 
		   			length = D12_WriteEndpoint(endp,(INT8U)length,sendbuff + pUsb->Cnt); 
		 		pUsb->Cnt = pUsb->Cnt + length;			//·¢ËͼÆÊýÆ÷¼Ólength 
			} 
		} 
	}//end of if (pUsb->Sem == 0) 
	OS_EXIT_CRITICAL(); 
	 
	OS_ENTER_CRITICAL(); 
	if (pUsb->Max[OSPrioCur] != 0){						//»¹Î´·¢ËÍÍê³É 
		OS_EXIT_CRITICAL();						 
		OSTimeDly(timeout);								//¶¨Ò峬ʱµÈ´ýʱ¼ä				 
	}	 
	OS_EXIT_CRITICAL(); 
	 
	return (USB_RW_Result(endp,pUsb,timeout));  		//·µ»Ø·¢Ëͽá¹û					 
} 
 
/***************************************************************** 
** º¯ÊýÃû³Æ: INT8U USB_RW_Param(CTRL_USB *pUsb,INT32U len,INT8U *buff) 
** ¹¦ÄÜÃèÊö: ÌîдUSB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éÓйزÎÊý 
** Êä	 Èë: CTRL_USB *pUsb   : USB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éÖ¸Õë 
			 INT32U len		  : ½ÓÊÕ»ò·¢ËÍ×Ö½ÚÊý 
			 INT8U *buff	  : ½ÓÊÕ»ò·¢ËÍ»º³åÇøÖ¸Õë 
** Êä	 ³ö: 0   µ÷Óóɹ¦    > 0 µ÷ÓÃʧ°Ü(´íÎóÂë) 
******************************************************************/ 
INT8U USB_RW_Param(CTRL_USB *pUsb,INT32U len,INT8U *pbuff) 
{ 
	OS_ENTER_CRITICAL(); 
	if (bEPPflags.bits.configuration == 0){	//USB×ÜÏßδÅäÖÃÍê³É 
		OS_EXIT_CRITICAL(); 
		return (USB_ERR_NO_CONFIG);			//USB×ÜÏßδÅäÖôíÎó 
	} 
	if (pbuff == 0){     	 
		OS_EXIT_CRITICAL();			     
		return (USB_ERR_BUFF_INVALID);		//»º³åÇøÖ¸ÕëÎÞЧ´íÎó 
	} 
	 
	pUsb->pBuff[OSPrioCur] = pbuff;			//±£´æ¸ÃÈÎÎñµÄ½ÓÊÕ»º³åÇøÊ×Ö· 
	pUsb->Max[OSPrioCur]   = len;			//±£´æÒªÊÕ·¢µÄ×Ö½ÚÊý 
	USB_InsertPrio(pUsb,OSPrioCur);			//²åÈëµÈ´ýÈÎÎñÁбíÖÐ 
	OS_EXIT_CRITICAL(); 
	 
	return (USB_NO_ERR); 
} 
 
/***************************************************************** 
** º¯ÊýÃû³Æ: INT8U USB_RW_Result(INT8U endp,CTRL_USB *pUsb,INT16U timeout) 
** ¹¦ÄÜÃèÊö: Åжϵ±Ç°ÈÎÎñµÄÊý¾ÝÊÇ·ñÊÕ·¢³É¹¦ 
** Êä	 Èë: INT8U endp		  : ¶ËµãË÷ÒýºÅ 
			 CTRL_USB *pUsb   : USB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éÖ¸Õë 
			 INT16U timeout	  : ³¬¹ýµÈ´ýʱ¼ä 
** Êä	 ³ö: 0   ÊÕ·¢³É¹¦    > 0 ÊÕ·¢Ê§°Ü(´íÎóÂë) 
******************************************************************/ 
INT8U USB_RW_Result(INT8U endp,CTRL_USB *pUsb,INT16U timeout) 
{	 
	OS_ENTER_CRITICAL();	 
	if (pUsb->Max[OSPrioCur] != 0){			//ÊÕ·¢Íê³É±êÖ¾²»Îª0,˵Ã÷ÊÕ·¢´íÎó 
		if (pUsb->Prio == OSPrioCur){		//¸ÃÈÎÎñÕ¼ÓÃÁ˶˵ãµÄÊÕ·¢×ÊÔ´ 
			pUsb->Sem = 0;					//±ØÐëÊÍ·Å×ÊÔ´ 
			D12_ClearBuff(endp);			//Çå¿ÕÊÕ·¢»º³åÇø 
		} 
		USB_DelPrio(pUsb,OSPrioCur);		//½«¸ÃÈÎÎñ´ÓµÈ´ýÁбíÖÐɾ³ý 
		OS_EXIT_CRITICAL(); 
		return (USB_ERR_WR_TIMEOUT);		//ÊÕ·¢³¬Ê±´íÎó	 
	}else{									 
		OS_EXIT_CRITICAL();						 
		return (USB_NO_ERR);				//ÊÕ·¢³É¹¦ 
	} 
} 
 
/************************************************************ 
          ÏÂÃæµÄº¯Êý²Ù×÷ USB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éµÈ´ýÁбí 
*************************************************************/ 
/************************************************************ 
** º¯ÊýÃû³Æ:  void USB_DelPrio(CTRL_USB *pUsb,INT8U prio) 
** ¹¦ÄÜÃèÊö:  ½«Ò»ÈÎÎñ´ÓUSB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éµÈ´ýÁбíÖÐɾ³ý 
** Êä¡¡  Èë:  CTRL_USB *pUsb:	USB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éÖ¸Õë 
			  INT8U prio:		ɾ³ýµÄÈÎÎñµÄÓÅÏȼ¶ 
** Êä¡¡  ³ö:  ÎÞ 
************************************************************/ 
void USB_DelPrio(CTRL_USB *pUsb,INT8U prio) 
{ 
	if ((pUsb -> Tbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0) 
	     pUsb -> Grp &= ~OSMapTbl[prio >> 3]; 
} 
 
/************************************************************ 
** º¯ÊýÃû³Æ:  void USB_InsertPrio(CTRL_USB *pUsb,INT8U prio) 
** ¹¦ÄÜÃèÊö:  ½«Ò»ÈÎÎñ²åÈëµ½USB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éµÈ´ýÁбíÖÐ 
** Êä¡¡  Èë:  CTRL_USB *pUsb:	USB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éÖ¸Õë 
			  INT8U prio:		²åÈëÈÎÎñµÄÓÅÏȼ¶ 
** Êä¡¡  ³ö:  ÎÞ 
************************************************************/ 
void USB_InsertPrio(CTRL_USB *pUsb,INT8U prio) 
{ 
	pUsb -> Grp		 	   |= OSMapTbl[prio >> 3]; 
	pUsb -> Tbl[prio >> 3] |= OSMapTbl[prio & 0x07]; 
} 
 
/********************************************************************* 
** º¯ÊýÃû³Æ:  INT8U USB_GetHighPrio(CTRL_USB *pUsb) 
** ¹¦ÄÜÃèÊö:  È¡µÃUSB½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éµÈ´ýÁбíÖÐÓÅÏȼ¶×î¸ßµÄÈÎÎñÓÅÏȼ¶ 
** Êä¡¡  Èë:  CTRL_USB *pUsb:	USB ½ÓÊÕ»ò·¢ËÍ¿ØÖÆ¿éÖ¸Õë 
** Êä¡¡  ³ö:  µÈ´ýÁбíÖÐÓÅÏȼ¶×î¸ßµÄÈÎÎñÓÅÏȼ¶ 
**********************************************************************/ 
INT8U USB_GetHighPrio(CTRL_USB *pUsb) 
{ 
	INT8U x,y; 
	INT8U prio; 
 
	y    = OSUnMapTbl[pUsb->Grp]; 
	x    = OSUnMapTbl[pUsb->Tbl[y]]; 
	prio = (INT8U)((y << 3) + x); 
	return prio; 
}