www.pudn.com > MyUDisk.rar > MyUDisk_ERROR.c


#include  
#include  
#include  
#include  
#include "def.h"  
#include "2410addr.h" 
#include "2410lib.h" 
#include "2410usb.h" 
#include "MyUDisk.h" 
#include "usblib.h" 
  
 
#define   MY_UDISK_STARTADDR	0x31500000	//划出32M的SDRAM来模拟FLASH	 
#define   MY_UDISK_ENDADDR		0x33500000	 
 
unsigned char Device_Descriptor[18] = { 
				    	 0x12,			   //0x12 
						 0x01,             //设备描述符类型 
						 0x10, 0x01,       //spec rev level (BCD) 1.0 
						 0x0,              //设备类型代码 
						 0x0,              //设备子类型代码 
						 0x0,              //设备协议 
						 0x08,             //控制端点的最大包个数 max packet size 
						 0x45, 0x53,        
						 0x34, 0x12,          
						 0x00, 0x01,		 
						 0,                  
						 0,                
						 0,                  
						 0x01              //配置数量 	 
						}; 
unsigned char Configuration_Descriptor_All[32] = { 
                       /*配置描述符*/ 
		        	    9,                 //描述符长度 
					    2,                 //配置描述符 (0x02) 
					    0x20,			   //总长32 字节	             
						0x00,               
						1,                 //设备接口数量 
						1,                 //配置标示值 
					    0,                 
						0xc0,			   //供电方式	 
						25,				   //50ma	 
              		    /*接口描述符*/ 
					    9,                 //描述符长度 
					    4,                 //接口描述符 
					    0,                  
					    0,                  
						2,                 //设备中用到的端口数目 
						8,                 //设备类代码--海量存储设备 
						6,	               //6=SCSI 
						0x50,              //bulk 0nly 传输 
						0,                  
						/*端口描述符*/                  
						0x07,             //端口描述符长度.    
						0x05,             //描述符类型---端口 
						0x81,             //IN端口 
						0x02,             //BULK端口    
						0x20, 0x00,       //最大传输量			 
						0x0,									 
						                   
						0x07,             //端口描述符长度.			 
						0x05,             //描述符类型---端口		 
						0x03,             //OUT端口					 
						0x02,             //BULK端口				 
						0x20, 0x00,       //最大传输量				 
						0x0											 
					}; 
 
unsigned char B_InquiryData[] = { 
							0x00,	                       //Direct Access Device	//直接访问的设备 
							0x80,	                       //RMB					//可删除的设备 
							0x00,	                       //ISO/ECMA/ANSI			// 
							0x01,	                       //Response Data Format	//数据格式 
							0x1f,	                       //Additional Length		// 
							0x00,	                       //Reserved				// 
							0x00,	                       //Reserved				// 
							0x00,	                       //Reserved				// 
							'X', 'I', 'N', 'Z', 'X', ' ', ' ', ' ',					//Vendor Information 
							'U', 'S', 'B', '-', 'M', 'A', 'S', 'S', 'S', 'T', 'O', 'R', 'A', 'G', 'E', ' ',//Product Identification 
							0, 0, 0, 0												// 
							};	                
/*SCSI-Read_Format_capacities命令的返回数据	*/ 
unsigned char B_Read_Format_capacities[] = {0x00, 0x00, 0x00, 0x10,	        //capacity list header 
									0x00, 0x00, 0x07, 0xf5,	0x01, 0x00, 0x02, 0x00,	//capacity descriptor 
								    //Number of Blocks =2037,unformatted media,blocklength = 512Bytes 
									//注:这里的Block和下面的不一样,1Block=32Page=32*512byte 
									//即2037*32*512==32M 
									//???但是和我在BusHound上监控到的aigo的优盘上的数据不一致//在哪里,1Block=1Page 
 
									0x00, 0x00, 0x07, 0xfd,	0x00, 0x00, 0x02, 0x00  //Formattable Capacity Descriptors 
									//???BlockNum不一样呢,好奇怪呀??? 
									};	 
//SCSI-Read_Capacity命令的返回数据 
unsigned char B_Read_Capacity[] = {				   	 
								0x00, 0x00, 0xfe, 0xa0,	   //Last  Logical Block Address for 32MB //可读的地址 
								0x00, 0x00, 0x02, 0x00	   //block length in bytes 
								}; 
//SCSI-Mode_Sense命令的返回数据    	   	 
unsigned char B_Mode_Sense_ALL[] = {0x0b, 0x00,       //Mode Data Length 
							0x00, 0x08, 0x00, 0x00, 
							0x7d, 0, 0, 0, 0x02, 0x00 
							}; 
//SCSI-Mode_Sense命令的返回数据			 
unsigned char B_Mode_Sense_TPP[] = {0xf0, 0x00,       //Mode Data Length 
							05, 00, 00, 00, 00, 0x0b, 00, 00, 00, 00, 0x24, 00, 00, 00, 00, 00 
							}; 
//SCSI-Mode_Sense命令的返回数据			 
unsigned char B_Mode_Sense_ZERO[] = {0x00, 0x06,      //Mode Data Length 
							0x00,	                       //Medium Type Code 
							0,                             //write enabled 
							0, 0, 0, 0                     //reserved	 
                            }; 
 
unsigned char  bulk_CSW[]={0x55,0x53,0x42,0x53,	//bytes 4 dCSWSignature 
					      0x00,0x00,0x00,0x00,	    //bytes 4 dCSWTag 
					      0x00,0x00,0x00,0x00,		//bytes 4 dDataResiduce 
					      0x00};			        //bCSWStatus  00=good state. 
 
struct_CBW	    bulk_CBW; 
U8				ep3Buf[EP3_PKT_SIZE];	 
int				ep0State; 
struct USB_SETUP_DATA descSetup;	 
 
//为了实现IN端点和OUT端点的协调工作,增加这些信息 
//IN端点中用到的状态信息 
unsigned char * g_pIN_NextData;		//指向需要的发送数据区的指针 
int    g_iIN_NextCount;				//剩余的需要发送的数据的长度  
int	   g_iInNeeded;					//在数据结束之后,需要一个CSW数据包 
//OUT端点中用到的状态信息 
unsigned char * g_pOUT_NextData; 
int    g_iOUT_NextCount; 
int    g_iOUT_Count; 
int    g_iOutNeeded;				//表示在OUT的数据接收阶段如Write10的处理 
 
/********************************************************************** 
// 描  述: USB中断服务函数 
// 返  回: void __irq        
// 参  数: void 
**********************************************************************/ 
void __irq IsrUsbd(void) 
{ 
    U8 usbdIntpnd,epIntpnd; 
    U8 saveIndexReg=rINDEX_REG; 
    usbdIntpnd=rUSB_INT_REG; 
    epIntpnd=rEP_INT_REG; 
    //DbgPrintf( "[INT:EP_I=%x,USBI=%x]",epIntpnd,usbIntpnd ); 
	 
	//注:需要明白各中断产生的条件 
    if(usbdIntpnd&SUSPEND_INT)	//挂起中断	 
    { 
    	rUSB_INT_REG=SUSPEND_INT;	 
    	DbgPrintf( "等价于rGPHCON = (rGPHCON&(~(0xf<<18)))|(0x5<<18)			 
	 
    //To enhance the USB signal quality.								 
    //CLKOUT 0,1=OUTPUT to reduce the power consumption. 
	//???也没有看出这个引脚就连接到USB的使能端呀,在哪里看出来的???		 
	//注:看看底板的原理图可知//当然还要看看USB的电气规范可知,对于高速设备D+端要接高电平				 
    rGPHDAT = rGPHDAT | (1<<9);			//USB_EN(device)		//所以此处要接上拉电阻		 
  
	//设置USB的中断处理函数	 
	Isr_Init();										 
	 
	//初始化串口,以供通讯使用 
    Uart_Init(0,115200);	 
	Uart_Select(0);	 
 
	//???????????????????????????选择USB设备?????????????????????????? 
    rMISCCR=rMISCCR&~(1<<3);	// USBD is selected instead of USBH1??  
    rMISCCR=rMISCCR&~(1<<13);	// USB port 1 is enabled.	?????????? 
	 
	//MMU_EnableICache();		//???使能cache 
    InitUsbd();					//完成各数据结构以及USB寄存器的初始化,并且将EP1的FIFO缓冲区中准备好数据以等待发送 
		 
	while (1)					//一切事情由中断服务程序去处理 
	{ 
    	if(DbgPrintfLoop())continue;												 
    	Delay(5000);						 
    	if((i++%2)==0)Led_Display(0x8);		 
    	else Led_Display(0x0);				 
	} 
} 
 
 
#define DBGSTR_LENGTH (0x1000) 
U8 dbgStrFifo[DBGSTR_LENGTH]; 
volatile U32 dbgStrRdPt=0; 
volatile U32 dbgStrWrPt=0; 
 
int DbgPrintfLoop(void) 
{ 
    if(dbgStrRdPt==dbgStrWrPt)return 0; 
    Uart_SendByte(dbgStrFifo[dbgStrRdPt++]); 
    if(dbgStrRdPt==DBGSTR_LENGTH)dbgStrRdPt=0; 
    return 1; 
} 
 
void _WrDbgStrFifo(U8 c) 
{ 
    dbgStrFifo[dbgStrWrPt++]=c; 
    if(dbgStrWrPt==DBGSTR_LENGTH)dbgStrWrPt=0; 
} 
 
void DbgPrintf(char *fmt,...) 
{ 
    int i,slen; 
    va_list ap; 
    char string[256]; 
 
    va_start(ap,fmt); 
    vsprintf(string,fmt,ap); 
     
    slen=strlen(string); 
     
    for(i=0;i0x9)//bLengthH should be used for bLength=0x209 at WIN2K.    	 
	    			ep0State=EP0_STATE_GD_CFG_0;		//for WIN98,WIN2K 
                else	    	     
  					ep0State=EP0_STATE_GD_CFG_ONLY_0;	//for WIN2K 
	    		break; 
   			case STRING_TYPE: 
 	    		DbgPrintf("[GDS]"); 
 	    		CLR_EP0_OUT_PKT_RDY(); 
	    		break; 
			case INTERFACE_TYPE: 
 	    		DbgPrintf("[GDI]"); 
 	    		CLR_EP0_OUT_PKT_RDY(); 
	    		break; 
			case ENDPOINT_TYPE:	    	 
 	    		DbgPrintf("[GDE]"); 
 	    		CLR_EP0_OUT_PKT_RDY(); 
	    		break; 
			default: 
	    		DbgPrintf("[UE:GD?]"); 
	    		break; 
			}	 
			break; 
    	case SET_ADDRESS:	 
            DbgPrintf("[SA:%d]",descSetup.bValueL); 
            rFUNC_ADDR_REG=descSetup.bValueL | 0x80;	//更新USB地址 
			CLR_EP0_OUTPKTRDY_DATAEND();				//Because of no data control transfers. 
            ep0State=EP0_STATE_INIT; 
            break; 
		case SET_CONFIGURATION: 
            DbgPrintf("[SC]"); 
            CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. 
            ep0State=EP0_STATE_INIT; 
			break; 
    	    //////////////////////// For chapter 9 test //////////////////// 
    	case CLEAR_FEATURE: 
			DbgPrintf("[CF]"); 
    	  	CLR_EP0_OUTPKTRDY_DATAEND(); 
    	  	ep0State=EP0_STATE_INIT; 
    	  	break; 
    	case GET_CONFIGURATION: 
			DbgPrintf("[GC]"); 
            CLR_EP0_OUT_PKT_RDY(); 
	    	ep0State=EP0_CONFIG_SET;    	  	    
    	    break; 
    	case GET_INTERFACE: 
			DbgPrintf("[GI]"); 
    	  	CLR_EP0_OUT_PKT_RDY(); 
	    	ep0State=EP0_INTERFACE_GET; 
    	  	break; 
    	case GET_STATUS: 
     		DbgPrintf("[GS]"); 
    	  	CLR_EP0_OUT_PKT_RDY(); 
    	  	break; 
    	case SET_DESCRIPTOR:  
			DbgPrintf("[SD]"); 
			CLR_EP0_OUTPKTRDY_DATAEND(); 
    	  	ep0State=EP0_STATE_INIT; 
    	  	break; 
		case SET_FEATURE: 
			DbgPrintf("[SD]"); 
    	  	CLR_EP0_OUTPKTRDY_DATAEND(); 
    	  	ep0State=EP0_STATE_INIT; 
    	  	break; 
    	case SET_INTERFACE: 
			DbgPrintf("[SI]"); 
    	  	CLR_EP0_OUTPKTRDY_DATAEND();  
            ep0State=EP0_STATE_INIT; 
    	  	break; 
    	case SYNCH_FRAME: 
			DbgPrintf("[SF]"); 
    	  	ep0State=EP0_STATE_INIT; 
    	  	break; 
    	  ////////////////////////////////////////////////////////////// 
		case GET_MAX_LUN://存储设备的命令 
			DbgPrintf("[GET_MAX_LUN]"); 
			CLR_EP0_OUT_PKT_RDY();  
    	  	ep0State=0xf3; 
    	  	break;		 
  		default: 
			DbgPrintf("[UE:SETUP=%x]",descSetup.bRequest); 
    	    CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. 
			ep0State=EP0_STATE_INIT; 
			break; 
        } 
    }  
	 
    switch(ep0State) 
    {	 
		case EP0_STATE_INIT: 
			break; 
		case 0xf3: 
			temp = 0x01; 
		    WrPktEp0((U8 *)&temp,1);	 //EP0_PKT_SIZE 
            SET_EP0_INPKTRDY_DATAEND(); 
			ep0State=EP0_STATE_INIT; 
            break; 
		//=== GET_DESCRIPTOR:DEVICE === 
    	case EP0_STATE_GD_DEV_0: 
            DbgPrintf("[GDD0]"); 
            WrPktEp0((U8 *)&Device_Descriptor+0,8); //EP0_PKT_SIZE 
            SET_EP0_IN_PKT_RDY(); 
            ep0State=EP0_STATE_GD_DEV_1; 
            break;             
    	case EP0_STATE_GD_DEV_1: 
            DbgPrintf("[GDD1]"); 
            WrPktEp0((U8 *)&Device_Descriptor+8,8);  
            SET_EP0_IN_PKT_RDY();             
            ep0State=EP0_STATE_GD_DEV_2; 
            break; 
    	case EP0_STATE_GD_DEV_2: 
            DbgPrintf("[GDD2]"); 
            WrPktEp0((U8 *)&Device_Descriptor+0x10,2);   //8+8+2=0x12 
            SET_EP0_INPKTRDY_DATAEND(); 
            ep0State=EP0_STATE_INIT; 
            break;	 
        //=== GET_DESCRIPTOR:CONFIGURATION+INTERFACE+ENDPOINT0+ENDPOINT1 === 
        //Windows98 gets these 4 descriptors all together by issuing only a request. 
        //Windows2000 gets each descriptor seperately. 
    	case EP0_STATE_GD_CFG_0: 
            DbgPrintf("[GDC0]"); 
            WrPktEp0((U8 *)&Configuration_Descriptor_All+0,8); //EP0_PKT_SIZE 
            SET_EP0_IN_PKT_RDY(); 
            ep0State=EP0_STATE_GD_CFG_1; 
            break; 
    	case EP0_STATE_GD_CFG_1:			 
            DbgPrintf("[GDC1]");			 
            WrPktEp0((U8 *)&Configuration_Descriptor_All+8,8);  
            SET_EP0_IN_PKT_RDY();			 
            ep0State=EP0_STATE_GD_CFG_2;	 
            break; 
		case EP0_STATE_GD_CFG_2: 
            DbgPrintf("[GDC2]"); 
            WrPktEp0((U8 *)&Configuration_Descriptor_All+16,8);  
            SET_EP0_IN_PKT_RDY(); 
            ep0State=EP0_STATE_GD_CFG_3; 
            break; 
    	case EP0_STATE_GD_CFG_3: 
            DbgPrintf("[GDC3]"); 
            WrPktEp0((U8 *)&Configuration_Descriptor_All+24,8);  
            SET_EP0_IN_PKT_RDY(); 
            ep0State=EP0_STATE_GD_CFG_4;             
            break; 
    	case EP0_STATE_GD_CFG_4: 
            DbgPrintf("[GDC4]"); 
             //zero length data packit	 
            SET_EP0_INPKTRDY_DATAEND();	//表明数据阶段通讯结束	 
            ep0State=EP0_STATE_INIT;             
            break; 
 
		//=== GET_DESCRIPTOR:CONFIGURATION ONLY=== 
    	case EP0_STATE_GD_CFG_ONLY_0: 
            DbgPrintf("[GDCO0]"); 
            WrPktEp0((U8 *)&Configuration_Descriptor_All+0,8); //EP0_PKT_SIZE 
            SET_EP0_IN_PKT_RDY(); 
            ep0State=EP0_STATE_GD_CFG_ONLY_1; 
            break; 
     
    	case EP0_STATE_GD_CFG_ONLY_1: 
            DbgPrintf("[GDCO1]"); 
            WrPktEp0((U8 *)&Configuration_Descriptor_All+8,1);  
            SET_EP0_INPKTRDY_DATAEND(); 
            ep0State=EP0_STATE_INIT;             
            break; 
 
        //=== GET_DESCRIPTOR:INTERFACE ONLY=== 
    	case EP0_STATE_GD_IF_ONLY_0: 
            DbgPrintf("[GDI0]"); 
            ep0State=EP0_STATE_GD_IF_ONLY_1; 
            break; 
   		default:	 
			DbgPrintf("UE:G?D"); 
     		break;	 
	} 
	rINDEX_REG=save ;			 
} 
	 
/********************************************************************** 
// 描  述:  
// 返  回: void        
// 参  数: void 
// gyj											 
// 如果上一包数据被读走的情况下,则IN_PKT_READY被清零产生中断 
// 那么此处处理这个中断已准备好下一次要发送的数据 
**********************************************************************/ 
void Ep1Handler(void)						 
{     
	U8 in_csr1;	 
	int save = 0; 
	save = rINDEX_REG ; 
	rINDEX_REG=1; 
	in_csr1=rIN_CSR1_REG;	 
    DbgPrintf("<1:%x]",in_csr1);	 
    //I think that EPI_SENT_STALL will not be set to 1.					 
    if(in_csr1 & EPI_SENT_STALL)										 
    {    
		//USB控制器返回告诉MCU已经往USB主机发送了一个STALL命令。 
   		DbgPrintf("[STALL]");	 
   		CLR_EP1_SENT_STALL();	 
   		return;					 
    }	 
 
	if ((g_iIN_NextCount != 0)&&(g_pIN_NextData != NULL)) 
	{ 
		if (g_iIN_NextCount > BULK_PKT_SIZE)	//要分成多包发送	 
		{	 
			WrPktEp1(g_pIN_NextData,BULK_PKT_SIZE); 
			g_pIN_NextData = g_pIN_NextData +BULK_PKT_SIZE;	 
			g_iIN_NextCount = g_iIN_NextCount -BULK_PKT_SIZE; 
		} 
		else 
		{		 
			WrPktEp1(g_pIN_NextData,g_iIN_NextCount);	//最后一包 
			g_pIN_NextData = NULL;					// 
			g_iIN_NextCount = 0;					//		 
 
		} 
		SET_EP1_IN_PKT_READY();										 
	} 
	else if (g_iInNeeded == TRUE) 
	{ 
		TransmitCSW(); 
		g_iInNeeded =FALSE; 
	} 
	rINDEX_REG=save ; 
    return;														      
}																		 
 
 
/**********************************************************************	 
// 描  述: 接收Out端点上发来的命令并且做出回应				 
// 注: IN端点和OUT端点的协调传输是这里的关键,当然如果想例子程序那样,	 
//	   以查询的方式进行数据的传输的话会相对比较的简单一些。	 
// 返  回: void												 
// 参  数: void												 
**********************************************************************/	 
void Ep3Handler(void) 
{	 
    U8  out_csr3;			 
	int i;					 
    int fifoCnt;			 
	int temp;				 
					 
    rINDEX_REG=3;			 
    out_csr3=rOUT_CSR1_REG;	 
							 
    DbgPrintf("<3:%x]",out_csr3);			 
	//I think that EPO_SENT_STALL will not be set to 1. 
    if(out_csr3 & EPO_SENT_STALL)		 
    {									 
   		DbgPrintf("[STALL]");			 
   		CLR_EP3_SENT_STALL();			 
   		return;							 
    }									 
										 
	//接收缓冲区中已经有数据了			 
    if(out_csr3 & EPO_OUT_PKT_READY)	 
    {   	 
		fifoCnt=rOUT_FIFO_CNT1_REG;				//收到的数据的字节个数							 
		RdPktEp3((U8 *)ep3Buf,fifoCnt);			 
		 
		rINDEX_REG=3;							 
		out_csr3=rOUT_CSR1_REG;					 
		rOUT_CSR1_REG= (out_csr3 & (~0x0f)); 	//~EPO_OUT_PKT_READY	 
 
		out_csr3=rOUT_CSR1_REG;							 
		temp = rINDEX_REG;								 
 
		DbgPrintf("<1_3:%x,%d]",out_csr3,temp);		 	 
			 
		if (g_iOutNeeded == TRUE)					//(g_iOutNeeded==TRUE)&&(g_pOUT_NextData!=NULL)&&( 
		{	 
			DbgPrintf("= 0x2000000)	//总量为32M 
	{ 
		return ; 
	} 
	g_pIN_NextData = (unsigned char *)(MY_UDISK_STARTADDR + iLBA*512); 
	WrPktEp1(g_pIN_NextData,32);			//先发送第一个数据包,在中断处理函数中接着发送后续的包			 
	g_pIN_NextData = g_pIN_NextData + 32;	//第二包在中断中发送 
	g_iIN_NextCount = length*512 - 32;		//需要发送的字节数										  
	g_iInNeeded = TRUE;						//在所有的数据发送完成之后要接着CSW应答包 
	SET_EP1_IN_PKT_READY();					//  
}	 
 
/////////////////////////////////////////////	 
void SCSI_Write10(void)	//FLASH写操作 
{			 
    int iLBA; 
    unsigned char length; 
	DbgPrintf("= 0x2000000)		//总量为32M 
	{ 
		return ; 
	}										 
	g_pOUT_NextData = (unsigned char *)(MY_UDISK_STARTADDR+iLBA*512);	//目的地的起始地址		 
	g_iOUT_NextCount = 	length*512;										//需要接收的数据的长度	 
	g_iOutNeeded = TRUE;												 
	g_iOUT_Count = 0;	 																		 
	 
	//注:第一个数据包要到中断中去接收和发送端有所不同。										 
}