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;i 0x9)//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; //注:第一个数据包要到中断中去接收和发送端有所不同。 }