📄 usb_disk.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 + -