⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myudisk.c

📁 这是我学USB时候
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#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( "<SUS]");	
    }								
    if(usbdIntpnd&RESUME_INT)	//恢复中断	
    {
    	rUSB_INT_REG=RESUME_INT;
    	DbgPrintf("<RSM]");		
    }
    if(usbdIntpnd&RESET_INT)	//复位中断
    {
    	DbgPrintf( "<RST]");		
    	InitUsbd();					
    	rUSB_INT_REG=RESET_INT;   
        //PrepareEp1Fifo();				
    }

    if(epIntpnd&EP0_INT)								
    {
		rEP_INT_REG=EP0_INT;  //清除相应的中标志位断	
    	Ep0Handler();		  //						
    }
    if(epIntpnd&EP1_INT)	  
    {		
    	rEP_INT_REG=EP1_INT;	
    	Ep1Handler();			
    }				
    if(epIntpnd&EP2_INT)		
    {
    	rEP_INT_REG=EP2_INT;	//Ep2没有使用
    	DbgPrintf("<2:TBD]");   //not implemented yet	
    }
    if(epIntpnd&EP3_INT)
    {
    	rEP_INT_REG=EP3_INT;	
    	Ep3Handler();			
    }

    if(epIntpnd&EP4_INT)	
    {
    	rEP_INT_REG=EP4_INT;	//Ep4没有使用
    	DbgPrintf("<4:TBD]");   //not implemented yet	
    }

    ClearPending(BIT_USBD); 					
    rINDEX_REG=saveIndexReg;    //恢复原来的中断寄存器状态
}

//**********************************************************************
// 描  述: 中断二次初始化函数
// 返  回: void       
// 参  数: void
//**********************************************************************
void Isr_Init(void)
{
    rINTMOD=0x0;					// All=IRQ mode
    rINTMSK=BIT_ALLMSK;				// All interrupt is masked.
    pISR_USBD =(unsigned)IsrUsbd;	//USB设备中断处理程序	 
    ClearPending(BIT_USBD); 		//					
}

/**********************************************************************/
// 描  述: 初始化USB相关结构
// 返  回: void       
// 参  数: void
/**********************************************************************/
void InitUsbd(void)
{

	//初始设备描述表              

	//配置端点信息//这些寄存器的设置的含义必须要搞清楚//主要是和数据处理相关的设置
	// *** End point information ***
	//   EP0: control
	//   EP1: bulk in end point
	//   EP2: not used
	//   EP3: bulk out end point
	//   EP4: not used
    rPWR_REG=PWR_REG_DEFAULT_VALUE;	//disable suspend mode
    rINDEX_REG	=0;			
    rMAXP_REG	=FIFO_SIZE_8;   	//EP0 max packit size = 8 //因为EndPoint0 的FIFO缓冲也就只有8个Byte
    rEP0_CSR	=EP0_SERVICED_OUT_PKT_RDY|EP0_SERVICED_SETUP_END;	
 									//EP0:clear OUT_PKT_RDY & SETUP_END
    rINDEX_REG=1;
    #if (EP1_PKT_SIZE==32)
        rMAXP_REG=FIFO_SIZE_32;		//EP1:max packit size = 32
    #else
		rMAXP_REG=FIFO_SIZE_64;		//EP1:max packit size = 64
    #endif	
    rIN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT;		
    rIN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK|EPI_BULK; //IN mode, IN_DMA_INT=masked    
    rOUT_CSR1_REG=EPO_CDT;   	
    rOUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;   		

    rINDEX_REG=3;
    #if (EP3_PKT_SIZE==32)
        rMAXP_REG=FIFO_SIZE_32;		//EP3:max packit size = 32
    #else
		rMAXP_REG=FIFO_SIZE_64;			//EP3:max packit size = 64
    #endif	
    rIN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT;
    rIN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK|EPI_BULK; //OUT mode, IN_DMA_INT=masked    
    rOUT_CSR1_REG=EPO_CDT;   	
	//clear OUT_PKT_RDY, data_toggle_bit.
	//The data toggle bit should be cleared when initialization.
    rOUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;   	
    
	//Clear all usbd pending bits//现将中断清掉
    rEP_INT_REG=EP0_INT|EP1_INT|EP2_INT|EP3_INT|EP4_INT;
    rUSB_INT_REG=RESET_INT|SUSPEND_INT|RESUME_INT;//			

    //EP0,1,3 & reset interrupt are enabled		
    rEP_INT_EN_REG=EP0_INT|EP1_INT|EP3_INT;		
    rUSB_INT_EN_REG=RESET_INT;					
	
	//使能USB中断
    rINTMSK&=~(BIT_USBD);  
}	


/**********************************************************************
// 描  述: USB处理的主函数
// 返  回: void       
// 参  数: void
**********************************************************************/
void Main(void)
{   
	int i;
	//设定时钟分频值
	ChangeClockDivider(1,1);		//1:2:4				
    ChangeMPllValue(82,1,1);		//FCLK=180.0Mhz 	
	
	//IO管脚的基本功能的初始化						
	Port_Init();	

	//把GPH10和GPH9中的两个引脚设置成输出OutPut			
	rGPHCON = rGPHCON&~(0xf<<18)|(0x5<<18);	//=>等价于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<slen;i++)
    	_WrDbgStrFifo(string[i]);

    va_end(ap);
}

//打印出USB控制端点收到的SETUP包的8个字节的内容    
void PrintEp0Pkt(U8 *pt)
{
    int i;
    DbgPrintf("[RCV:");
    for(i=0;i<EP0_PKT_SIZE;i++)
        DbgPrintf("%x,",pt[i]);
    DbgPrintf("]");
}
	
void RdPktEp0(U8 *buf,int num)
{	
    int i;	
    for(i=0;i<num;i++)
    {
        buf[i]=(U8)rEP0_FIFO;	
    }	
}		
    
	
void WrPktEp0(U8 *buf,int num)
{	
    int i;
	
    for(i=0;i<num;i++)
    {
        rEP0_FIFO=buf[i];	
    }
}	
	  
void WrByteEp0(U8 value)
{	
    rEP0_FIFO= value;
}	
	
	
void WrPktEp1(U8 *buf,int num)
{
    int i; 	
    for(i=0;i<num;i++)
    {
        rEP1_FIFO=buf[i];	
    }
}


void WrPktEp2(U8 *buf,int num)
{
    int i;
    	
    for(i=0;i<num;i++)
    {
        rEP2_FIFO=buf[i];	
    }
}


void RdPktEp3(U8 *buf,int num)
{
    int i;    	
    for(i=0;i<num;i++)
    {
        buf[i]=(U8)rEP3_FIFO;	
    }
}


void RdPktEp4(U8 *buf,int num)
{
    int i;
    	
    for(i=0;i<num;i++)
    {
        buf[i]=(U8)rEP4_FIFO;	
    }
}


/**********************************************************************
// 描  述: 端口0处理函数
// 返  回: void
// 注: 我觉得这里才是重点和难点!!!!!//状态机的处理相一致。
// 这  个处理函数表征了对USB标准协议中的请求命令的支持       
**********************************************************************/ 
void Ep0Handler(void)
{
    U8 ep0_csr;
	U8 temp ;
	int save = 0;
	save = rINDEX_REG ;

    rINDEX_REG=0;		
    ep0_csr=rEP0_CSR;	
    
    DbgPrintf("<0:%x]",ep0_csr);

    //DATAEND interrupt(ep0_csr==0x0) will be ignored 
    //because ep0State==EP0_STATE_INIT when the DATAEND interrupt is issued.
    if(ep0_csr & EP0_SETUP_END)
    {   
    	// Host may end GET_DESCRIPTOR operation without completing the IN data stage.
    	// If host does that, SETUP_END bit will be set.
    	// OUT_PKT_RDY has to be also cleared because status stage sets OUT_PKT_RDY to 1.
   		DbgPrintf("[SETUPEND]");	//表示USB在SetUp阶段异常中止
		CLR_EP0_SETUP_END();
		if(ep0_csr & EP0_OUT_PKT_READY) 
		{
			FLUSH_EP0_FIFO(); //(将缓冲区中的数据全部清除掉)
	    	//I think this isn't needed because EP0 flush is done automatically.   
			CLR_EP0_OUT_PKT_RDY();
		}
		ep0State=EP0_STATE_INIT;	//状态机回到初始态
		return;
    }	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -