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

📄 usb_disk.c

📁 32M 优盘源码 AT89C51SND1C K9F5608
💻 C
字号:
#include "Gloab.H"
#include "UDISK_DEF.H"

extern void ReadFlash();	 //Defined in FLASH_RW.C
extern void WriteFlash();

#define FLASH_RD_BUSY				P5_2

// 写入地址字段
static void NfWriteAddr(unsigned char adr)
{
	*((unsigned char volatile xdata  *)0xF002) = adr;
}

// 命令写入
static void NfWriteCmd(unsigned char cmd)
{
	*((unsigned char volatile xdata  *)0xF001) = cmd;
}

// FLASH测忙
static void NfWaitBusy(void)
{
	while (!FLASH_RD_BUSY);
}

code unsigned char Device_Descriptor[18] = {
				    	 0x12,			   //设备描述符的字节数大小
						 0x01,             //设备描述符类型编号
						 0x10, 0x01,       //USB版本号
						 0x00,             //USB分配的设备类代码
						 0x00,             //USB分配的子类代码
						 0x00,             //USB分配的设备协议代码
						 0x20,             //端点0的最大包大小
						 0xEB, 0x03,       //厂商编号
						 0x02, 0x20,       //产品编号 
						 0x00, 0x01,       //设备出厂编号 
						 0x00,             //设备厂商字符串的索引  
						 0x00,             //描述产品字符串的索引  
						 0x00,             //描述设备序列号字符串的索引   
						 0x01              //可能的配置数量	
						};

code unsigned char Configuration_Descriptor_All[32] = {
								        	    //配置描述符
						0x09,              //配置描述符的字节数大小
					    0x02,              //配置描述符类型编号
					    0x20,0x00,         //Total length in bytes of data returned  LSB  //MSB          
						0x01,              //只包含一个接口
						0x01,              //该配置的编号
					    0x00,              //iConfiguration字段
						0x80,			   //采用总线供电,不支持远程唤醒
						0xfa,              //Maximum Power Consumption in 2mA units 
					    //接口描述符
						0x09,			   //接口描述符的字节数大小
					    0x04,			   //接口描述符类型编号
					    0x00,              //接口编号为0
					    0x00,              //该接口描述符的编号
						0x02,              //非0端点数量为2,只使用端点主端点输入和输出
						0x08,              //USB大容量存储设备
						0x06,	           //使用的子类,为简化块命令 1=RBC,2=SFF,3=QIC,4=UFI,5=SFF,6=SCSI
						0x50,              //使用的协议,这里使用单批量传输协议
						0x00,              //接口描述符字符串索引
						//主端点输入描述                  
						0x07,              //端点描述符的字节数大小  
						0x05,              //端点描述符类型编号
						0x81,              //端点号,主输入端点
						0x02,              //使用的传输类型,批量传输    
						0x40, 0x00,        //该端点支持的最大包尺寸,64字节 
						0x00,               //中断扫描时间,对批量传输无效
						//主端点输出描述   
						0x07,              //端点描述符的字节数大小   
						0x05,              //端点描述符类型编号
						0x02,              //端点号,主输出端点
						0x02,              //使用的传输类型,批量传输
						0x40, 0x00,        //该端点支持的最大包尺寸,64字节
						0x00                //中断扫描时间,对批量传输无效
					};


code 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 
							'J', 'I', 'A', 'N', 'G', 'S', 'H', 'A',	       //Vendor Information
							'U', 'S', 'B', '-', 'M', 'P', '3', ' ', 'V', '3', '.', '0', ' ', ' ', ' ', ' ',//Product Identification
							0, 0, 0, 0					   //Product Revision Level n.nn
							};	               

//SCSI-Read_Format_capacities命令的返回数据	 
code 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
									0x00, 0x00, 0x07, 0xfd,	0x00, 0x00, 0x02, 0x00  //Formattable Capacity Descriptors
									};

//SCSI-Read_Capacity命令的返回数据
code 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命令的返回数据    	   		
code unsigned char B_Mode_Sense_ALL[] = {0x0b, 0x00,       //Mode Data Length
							0x00, 0x08, 0x00, 0x00,
							0x7d, 0, 0, 0, 0x02, 0x00
							};
//SCSI-Mode_Sense命令的返回数据			
code 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命令的返回数据			
code 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 data 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 data bulk_CBW;



void AtmelUSBInit()
{
	int data i;	
	PLLNDIV	=	0x04;
	PLLCON |=	(0x3&Rdiv)<<6;
	PLLRDIV	=	(0x3ff&Rdiv)>>2;
	USBCLK=0;
	PLLCON&=(~PLLRES);
	PLLCON|=PLLEN;
	USBCON&=(~USBE);
	for(i=0;i<3000;i++);
	USBCON|=USBE;

}	

void EpEnable(void)
{
	UEPNUM=0x00;	UEPCONX=0x80;
	UEPNUM=0x01;	UEPCONX=0x86;
	UEPNUM=0x02;	UEPCONX=0x82;
	UEPRST=0x07;	UEPRST= 0x00;
	UEPIEN=0x07;	USBIEN|=EEOFINT;
	USBADDR=FEN;
}

unsigned char ReadEp(unsigned char EpNum,unsigned char *Data)
{
	unsigned char data i=0;
	UEPNUM=EpNum;
	while(i<UBYCTLX)
	{
		Data[i++]=UEPDATX;
	}	
	UEPSTAX&=~(RXOUTB0|RXOUTB1|RXSETUP);
	return(i);
}

void WriteEp(unsigned char EpNum,unsigned char nLength,unsigned char *Data)
{
	unsigned char data i=0;
	UEPNUM=EpNum;
	UEPSTAX|=DIR;
	while(nLength--) UEPDATX=Data[i++];	
	UEPSTAX|=TXRDY;
	while(!(UEPSTAX&TXCMP)) ;
	UEPSTAX&=(~(TXCMP));
}



void Set_Address(unsigned char EpNum)
{
	WriteEp(0,0,0);
	USBADDR|=EpNum;
	USBADDR|=FEN;
	USBCON|=FADDEN;
}


void Get_Descriptor(unsigned char DesType,unsigned char nLength)
{
	if(DesType==0x01)
		WriteEp(0,18,Device_Descriptor);

	else if(DesType==0x02)
	{
		if(nLength==0x09)
		{
			WriteEp(0,9,Configuration_Descriptor_All);
		}
		else if(nLength==0xff)
		{
			WriteEp(0,32,Configuration_Descriptor_All);
	    	WriteEp(0,2,&Device_Descriptor[4]);
		}
		else if(nLength==0x20)
		{
			WriteEp(0,32,Configuration_Descriptor_All);
		}
	}	
}

void Set_Configuration(unsigned char wValue)
{
  if(wValue == 0)
  {
		UEPNUM=0x00;	UEPCONX=0x80;
		UEPNUM=0x01;	UEPCONX=0x86;
		UEPNUM=0x02;	UEPCONX=0x82;
		USBCON&=(~CONFG);
		WriteEp(0,0,0);	
  }
  else if(wValue == 1) 
  {
		UEPNUM=0x00;	UEPCONX=0x80;
		UEPNUM=0x01;	UEPCONX=0x86;
		UEPNUM=0x02;	UEPCONX=0x82;
		USBCON|=CONFG;
		WriteEp(0,0,0);	
  }
}

void Ep0()
{
  unsigned char data DT[32]={0,};
  unsigned char data i;
  i = ReadEp(0,DT);
  if (((DT[0] & 0x60)==0) && i)
  {
    switch (DT[1])
    {
      case set_address				:Set_Address(DT[2]);			break;
      case get_descriptor			:Get_Descriptor(DT[3],DT[6]);	break;
      case set_configuration	    :Set_Configuration(DT[2]);		break;
      default						:;					            break;
	}
  }
  else if(DT[0]==0xa1)
	{
		WriteEp(0,0,0);
	}							  						
}


void WriteEpBulk(unsigned char EpNum,unsigned char nLength,unsigned char *Data)
{
	unsigned char data i;
	UEPNUM=EpNum;
	UEPSTAX|=DIR;
	for(i=0;i<nLength;i++) UEPDATX=Data[i];
	UEPSTAX|=TXRDY;
}

void TransmitCSW()
{
  WriteEpBulk(1, sizeof(bulk_CSW), bulk_CSW);
  while(!(UEPSTAX&TXCMP)) ;
  UEPSTAX&=(~(TXCMP));
}

void main_txdone()
{
  UEPSTAX&=(~(TXCMP));
  TransmitCSW();
}

 void SCSI_Mode_Sense()
{
  if(bulk_CBW.CBWCB[2] == SCSI_MSPGCD_TPP)                 //Page Code=Timer and Potect Page
    {WriteEpBulk(1, sizeof(B_Mode_Sense_TPP), B_Mode_Sense_TPP);}
  else if(bulk_CBW.CBWCB[2] == SCSI_MSPGCD_RETALL)		   //Page Code=All
    {WriteEpBulk(1, sizeof(B_Mode_Sense_ALL), B_Mode_Sense_ALL);}
  else {WriteEpBulk(1, sizeof(B_Mode_Sense_ZERO), B_Mode_Sense_ZERO);}
}

void SCSI_Read_Format_Capacities()
{
  if(bulk_CBW.CBWCB[7]==0 && bulk_CBW.CBWCB[8]==0)return;
  WriteEpBulk(1, sizeof(B_Read_Format_capacities), B_Read_Format_capacities);
}

void SCSI_Read10()
{
  unsigned char i;
	union
	{
		unsigned long   Block;
		unsigned char	Addr[4];
	}BLK;
    unsigned char length;

	BLK.Addr[2] = bulk_CBW.CBWCB[4];
	BLK.Addr[3] = bulk_CBW.CBWCB[5];

    length = bulk_CBW.CBWCB[8];
    while(length>0)
    {
	  NfWriteCmd(0x00);
	  NfWriteAddr(0);
	  NfWriteAddr(BLK.Addr[3]);
	  NfWriteAddr(BLK.Addr[2]);

	  UEPNUM=0x01;
	  UEPSTAX|=DIR;
	  NfWaitBusy();

	  for(i=0;i<4;i++)
	  {
		  ReadFlash();
		  UEPSTAX|=TXRDY;
		  while(!(UEPSTAX&TXCMP));
		  UEPSTAX&=(~(TXCMP));
	  }
	  NfWriteCmd(0x01);
	  NfWriteAddr(0);
	  NfWriteAddr(BLK.Addr[3]);
	  NfWriteAddr(BLK.Addr[2]);

	  UEPNUM=0x01;
	  UEPSTAX|=DIR;
	  NfWaitBusy();

	  for(i=0;i<4;i++)
	  {
		  ReadFlash();
		  UEPSTAX|=TXRDY;
		  while(!(UEPSTAX&TXCMP));
		  UEPSTAX&=(~(TXCMP));
	  }
	  length--;	
	  BLK.Block ++;
     }
  TransmitCSW();
}

void SCSI_Write10()	
{
    union
     {
	   unsigned long page;
	   unsigned char addr[4];
     }PG; 

    unsigned char i=0,length=0,nBeginPage=0;

 	NfWriteCmd(0x60);
	NfWriteAddr(BuffBlock);
	NfWriteAddr(0xff);
	NfWriteCmd(0xd0);

    NfWaitBusy();
	
	NfWriteCmd(0x60);
	NfWriteAddr(BuffBlock|0x20);
	NfWriteAddr(0xff);
	NfWriteCmd(0xd0);
	
	PG.addr[2] = bulk_CBW.CBWCB[4];
	PG.addr[3] = bulk_CBW.CBWCB[5];
	length = bulk_CBW.CBWCB[8];

	nBeginPage = PG.addr[3]&0x1f;
	UEPNUM = 0x02;	
    NfWaitBusy();

    if(nBeginPage>0)
	  {
	     for(i=0;i<nBeginPage;i++)
		 { 
			  NfWriteCmd(0x00);
			  NfWriteAddr(0);			 //A0-A7
			  NfWriteAddr((PG.addr[3]&0xe0)|i);	//A9-A16
			  NfWriteAddr(PG.addr[2]);		   //A17-A24
    		  NfWaitBusy();

			  NfWriteCmd(0x8a);
			  NfWriteAddr(0);							  //A0-A7
			  NfWriteAddr(BuffBlock|(PG.addr[3]&0x20)|i); //A9-A16 
	          NfWriteAddr(0xff);						  //A17-A24				          
    		  NfWaitBusy();
		 }
		 nBeginPage=0;
	  }

	while(length>0)
	  {
	  	 NfWriteCmd(0x80);
	     NfWriteAddr(0);						  	//A0-A7	 
		 NfWriteAddr((PG.addr[3]&0x3f)|BuffBlock);  //A9-A16  
		 NfWriteAddr(0xff);				 		  	//A17-A24
		 for(i=0;i<8;i++)
		 {
			  while (!(UEPINT & EP2));	
			  WriteFlash();
			  UEPSTAX &= 0xB9;
		 }
		 NfWriteCmd(0x10);
		 length--;	
		 NfWaitBusy();

	     if(((PG.addr[3]&0x1f)==0x1f)||(length==0))
		 {
			 for(i=((PG.addr[3]&0x1f)+1);i<32;i++)
	         {
				   NfWriteCmd(0x00);
			  		NfWriteAddr(0);			 //A0-A7
			  		NfWriteAddr((PG.addr[3]&0xe0)|i);	//A9-A16
			  		NfWriteAddr(PG.addr[2]);		   //A17-A24
    		  		NfWaitBusy();

			  		NfWriteCmd(0x8a);
			  		NfWriteAddr(0);							  //A0-A7
			  		NfWriteAddr((PG.addr[3]&0x20)|BuffBlock|i); //A9-A16 
	          		NfWriteAddr(0xff);						  //A17-A24				          
    		  		NfWaitBusy();
	          }
			  
			  NfWriteCmd(0x60);			 //擦除当前block
			  NfWriteAddr(PG.addr[3]);	 //A9-A16
			  NfWriteAddr(PG.addr[2]);	 //A17-A24
			  NfWriteCmd(0xd0);
			  NfWaitBusy();				  //等待操作完成        

			  for(i=0;i<32;i++)	
			  {
			  		NfWriteCmd(0x00);
			  		NfWriteAddr(0);			 //A0-A7
			  		NfWriteAddr((PG.addr[3]&0x20)|BuffBlock|i);	//A9-A16
			  		NfWriteAddr(0xff);		   //A17-A24
    		  		NfWaitBusy();

			  		NfWriteCmd(0x8a);
			  		NfWriteAddr(0);							  //A0-A7
			  		NfWriteAddr((PG.addr[3]&0xe0)|i); //A9-A16 
	          		NfWriteAddr(PG.addr[2]);						  //A17-A24				          
    		  		NfWaitBusy();
  			  }

			  if(length>0)
			  {
			  		NfWriteCmd(0x60);			 				//擦除block
			  		NfWriteAddr((PG.addr[3]&0x20)|BuffBlock);	 //A9-A16
			  		NfWriteAddr(0xff);	 						//A17-A24
			  		NfWriteCmd(0xd0);
			  		NfWaitBusy();				  //等待操作完成    
				}
 		   }
		  PG.page++;
	  }

	TransmitCSW();	
}	

void main_rxdone()
{
  	unsigned char i;
  	unsigned char Buf[64];

  	i = ReadEp(2,Buf);
  	bulk_CSW[4] = Buf[4];  bulk_CSW[5] = Buf[5]; bulk_CSW[6] = Buf[6]; bulk_CSW[7] = Buf[7];
	for(i=0;i<12;i++) bulk_CBW.CBWCB[i] = Buf[i+15];
	switch(bulk_CBW.CBWCB[0])
	{
			case Inquiry			     :WriteEpBulk(1,36,B_InquiryData);break;
			case Mode_Sense			     :SCSI_Mode_Sense();              break;
			case Read10				     :SCSI_Read10();                  break;
			case Read_Capacity		     :WriteEpBulk(1, sizeof(B_Read_Capacity), B_Read_Capacity);break;
			case Read_Format_Capacities	 :SCSI_Read_Format_Capacities();  break;
			case Test_Unit_Ready	     :TransmitCSW();                  break;
			case Verify				     :TransmitCSW();                  break;
			case Write10			     :SCSI_Write10();                 break;
			case Medium_Removal		     :TransmitCSW();                  break;
			//响应PC机删除U盘设备的命令
			case Sync_Cache				 :TransmitCSW();                  break;
			case Start_Unit				 :TransmitCSW();                  break;
	}
}

void Flash_Reset(void)		                                     //flash reset
{ 
	uint i;
	NfWriteCmd(0xFF);
	for (i=0; i<3000; i++) ;	                                 //delay 	
}

⌨️ 快捷键说明

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