📄 usb.c
字号:
{
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);
}
extern void ReadFlash();
extern void WriteFlash();
void SCSI_Read10()
{
unsigned char data i;
union
{
unsigned long Block;
unsigned char Addr[4];
}data BLK;
unsigned char length; //传输的簇数
//将起始地址变换为K9F5608适合的模式;
// BLK.Addr[0] = bulk_CBW.CBWCB[2];
// BLK.Addr[1] = bulk_CBW.CBWCB[3];
BLK.Addr[2] = bulk_CBW.CBWCB[4];
BLK.Addr[3] = bulk_CBW.CBWCB[5];
//将扇区数填入计数变量每循环一次读出一扇区的值;
// PG.Addr[0] = bulk_CBW.CBWCB[7];
// PG.Addr[1] = bulk_CBW.CBWCB[8];
length = bulk_CBW.CBWCB[8];
while(length>0)
{
K9F_FUN = COMMAND; //读出一个page
*((unsigned char xdata *)K9F5608) = 0x00;
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = 0; //A0-A7
*((unsigned char xdata *)K9F5608) = BLK.Addr[3]; //A9-A16
*((unsigned char xdata *)K9F5608) = BLK.Addr[2]; //A17-A24
K9F_FUN = D_DATA;
UEPNUM=0x01; //指向端点
UEPSTAX|=DIR; //传输方向
while(!(K9F_FUN & RB));
for(i=0;i<8;i++) //读出512个字节的数据发送到usb
{
ReadFlash();
UEPSTAX|=TXRDY;
while(!(UEPSTAX&TXCMP)); //等待发送完成
UEPSTAX&=(~(TXCMP)); //清中断标志clear TXCMP
UEPINT=0;
}
*((unsigned char xdata *)K9F5608) = INACTIVE;
length--; //传输的簇数减1
BLK.Block ++; //flash的页地址加1
}
TransmitCSW(); //返回CSW
}
void delay() //延时20us
{
unsigned char data i=20;
while(i-->0);
}
#define BuffBlock (0xc0) //缓冲区为从偶数块开始的连续两个Block 这里定为2046和2047两个Block
//BuffBlock只代表块号的低字节
void SCSI_Write10() //之所以选用两个Block作为缓冲区,与Flash的Copy - Back功能的特性相关,
{ //清仔细阅读Flash 的datasheet
union
{
unsigned long page;
unsigned char addr[4];
}data PG;
unsigned char data i=0,length=0,nBeginPage=0;
//所有写入都要缓冲,所以先清除缓冲区
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x60; //擦除第2046个Block作为缓冲区
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = BuffBlock; //A9-A16
*((unsigned char xdata *)K9F5608) = 0xff; //A17-A24
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0xd0;
K9F_FUN = D_DATA;
delay();
// printuf(" %x",PG.addr[0]);printuf(" %x",PG.addr[1]);printuf(" %x",PG.addr[2]);printuf(" %x",PG.addr[3]);
// printuf(" %x",length); printuf(" %x",nBeginPage);
while(!(K9F_FUN & RB)); //等待擦除操作的完成
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x60; //擦除第2047个Block作为缓冲区
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = BuffBlock|0x20; //A9-A16
*((unsigned char xdata *)K9F5608) = 0xff; //A17-A24
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0xd0;
K9F_FUN = D_DATA;
//从SCSI命令中分离出逻辑地址
// PG.addr[0] = bulk_CBW.CBWCB[2];
// PG.addr[1] = bulk_CBW.CBWCB[3];
PG.addr[2] = bulk_CBW.CBWCB[4];
PG.addr[3] = bulk_CBW.CBWCB[5];
length = bulk_CBW.CBWCB[8]; //windows 系统每次写入的最大长度为0x80个扇区取一字节已够用
nBeginPage = PG.addr[3]&0x1f; //计算出要写入块内的要写入的起始扇区号
UEPNUM = 0x02; //指向Bulk端点2
delay();
while(!(K9F_FUN & RB)); //等待擦除操作的完成
if(nBeginPage>0) //如果起始写入page与flash的Block未对齐,则将当前Block中的前nBeginPage页
{ //拷贝到缓冲区的相同位置
for(i=0;i<nBeginPage;i++)
{
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x00; //命令的第一个字节
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = 0; //A0-A7
*((unsigned char xdata *)K9F5608) = (PG.addr[3]&0xe0)|i; //A9-A16
*((unsigned char xdata *)K9F5608) = PG.addr[2]; //A17-A24
K9F_FUN = D_DATA;
delay();
while(!(K9F_FUN & RB)); //等待操作的完成
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x8a; //命令的第二个字节
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = 0; //A0-A7
*((unsigned char xdata *)K9F5608) = BuffBlock|(PG.addr[3]&0x20)|i; //A9-A16
*((unsigned char xdata *)K9F5608) = 0xff; //A17-A24
K9F_FUN = D_DATA;
delay();
while(!(K9F_FUN & RB)); //等待操作的完成
}
nBeginPage=0; //起始扇区值赋为0
}
while(length>0) //传输的扇区数大于0
{
K9F_FUN = COMMAND; //数据写入到缓冲区的对应位置
*((unsigned char xdata *)K9F5608) = 0x80;
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = 0; //A0-A7
*((unsigned char xdata *)K9F5608) = (PG.addr[3]&0x3f)|BuffBlock; //A9-A16
*((unsigned char xdata *)K9F5608) = 0xff; //A17-A24
K9F_FUN = D_DATA;
for(i=0;i<8;i++) //端点数据写入到Flash的缓冲区
{
while (!(UEPINT & 0x04)); //等待接收数据RXOUTB1
//写64字节
WriteFlash();
UEPSTAX &= 0xB9; //准备再接收
UEPINT = 0;
}
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x10;
K9F_FUN = D_DATA;
length--; //传输的扇区数减1
delay();
while(!(K9F_FUN & RB)); //等待操作的完成
if(((PG.addr[3]&0x1f)==0x1f)||(length==0)) //缓冲区写满即写满32页或传输数据结束时
{
for(i=((PG.addr[3]&0x1f)+1);i<32;i++) //如果当length==0时并且(PG.addr[3]&0x1f)!=0x1f
{ //拷贝从((PG.addr[3]&0x1f)+1)到32号页的数据到缓冲区的对应位置
K9F_FUN = COMMAND; //执行Flash的COPY-BACK命令
*((unsigned char xdata *)K9F5608) = 0x00;
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = 0; //A0-A7
*((unsigned char xdata *)K9F5608) = (PG.addr[3]&0xe0)|i; //A9-A16
*((unsigned char xdata *)K9F5608) = PG.addr[2]; //A17-A24
K9F_FUN = D_DATA;
delay();
while(!(K9F_FUN & RB)); //等待操作的完成
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x8a;
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = 0; //A0-A7
*((unsigned char xdata *)K9F5608) = (PG.addr[3]&0x20)|BuffBlock|i; //A9-A16
*((unsigned char xdata *)K9F5608) = 0xff; //A17-A24
K9F_FUN = D_DATA;
delay();
while(!(K9F_FUN & RB)); //等待操作的完成
}
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x60; //擦除当前block
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = PG.addr[3]; //A9-A16
*((unsigned char xdata *)K9F5608) = PG.addr[2]; //A17-A24
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0xd0;
K9F_FUN = D_DATA;
delay();
while(!(K9F_FUN & RB)); //等待操作的完成
for(i=0;i<32;i++) //将缓冲Block中的内容拷贝到当前Block中
{
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x00;
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = 0; //A0-A7
*((unsigned char xdata *)K9F5608) = (PG.addr[3]&0x20)|BuffBlock|i; //A9-A16
*((unsigned char xdata *)K9F5608) = 0xff; //A17-A24
K9F_FUN = D_DATA;
delay();
while(!(K9F_FUN & RB)); //等待操作的完成
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x8a;
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = 0; //A0-A7
*((unsigned char xdata *)K9F5608) = (PG.addr[3]&0xe0)|i; //A9-A16
*((unsigned char xdata *)K9F5608) = PG.addr[2]; //A17-A24
K9F_FUN = D_DATA;
delay();
while(!(K9F_FUN & RB)); //等待操作的完成
}
if(length>0) //传输未完成时
{
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x60; //擦除相应的缓冲区
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = (PG.addr[3]&0x20)|BuffBlock; //A9-A16
*((unsigned char xdata *)K9F5608) = 0xff; //A17-A24
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0xD0;
K9F_FUN = D_DATA;
delay();
while(!(K9F_FUN & RB)); //等待操作的完成
}
}
PG.page++; //逻辑簇地址加1
}
TransmitCSW(); //向Host返回CSW
// printuf(" %x",PG.addr[0]);printuf(" %x",PG.addr[1]);printuf(" %x",PG.addr[2]);printuf(" %x\n",PG.addr[3]);
}
void main_rxdone()
{
unsigned char data i;
unsigned char data Buf[64];
i = ReadEp(2,Buf); //读出端点数据
// if(Buf[0] == 0x55) //命令数据包
// {
P3_5 =0; //指示灯亮
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;
}
P3_5 =1; //指示灯灭
// }
// else
// SCSI_Write10();
}
//flash芯片复位函数
void Flash_Reset(void) //flash reset
{
unsigned int data i;
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0xff; //reset command
for (i=0; i<3000; i++) ; //delay
}
//读取一个page的内容
void ReadPage(unsigned int block, unsigned int page, unsigned char *pPage)
{
int i;
unsigned int blockPage = (block << 5) | page;
K9F_FUN = COMMAND;
*((unsigned char xdata *)K9F5608) = 0x00;
K9F_FUN = ADDRESS;
*((unsigned char xdata *)K9F5608) = 0; //A0-A7
*((unsigned char xdata *)K9F5608) = blockPage & 0xff; //A9-A16
*((unsigned char xdata *)K9F5608) = (blockPage >> 8) & 0xff; //A17-A24
K9F_FUN = D_DATA;
i = 512;
while(!(K9F_FUN & RB)); //等待操作的完成
while((i--)>0)
{
*pPage++ = *((unsigned char xdata *)K9F5608);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -