📄 mass_stg.c
字号:
name: System_Config
function: Config the IO Port and Interrupt source
pars: no
renturns: no
*******************************************************************************************/
void System_Config(void)
{
PCA0MD &= ~0x40; //Disable WDT
//PCA0MD = 0x00;
P0MDOUT = 0x02;
P1MDOUT = 0x00; //Open Drain mode
P2MDOUT = 0xBF; //Push-pull output
XBR1 = 0x40; //Enable Weak Pull-up
REG0CN = 0x10; //Enable internal LDO, Low Power mode
GND = 1;
WP = 1;
RE = 1;
WE = 1;
CE = 1;
ALE = 0;
CLE = 0;
}
/******************************************************************************************
name: USB_Config
function: USB SIE function Config
pars: no
returns: no
********************************************************************************************/
void USB_Config(void)
{
RSTSRC &= ~0x80; //Disable USB VBUS Reset
IE = 0x80;
EIE1 = 0x02; //Enable USB interrupt
USB0XCN = 0xE0; //Enable Tranceiver, Full Speed Mode
SFR_WR(CLKREC, 0x89); //Enable USB clock Recovery Ciruit
SFR_WR(CMIE, 0x04); //Enable Reset Interrupt
SFR_WR(INIE, 0x0F); //Enable EndPoint0-3 input Interrupt
SFR_WR(OUTIE, 0x0F); //Enable EndPoint0-3 output Interrupt
SFR_WR(INDEX, 0x01); //Split the FIFO into two halfs for input
SFR_WR(EINCSRH, 0x4); //Endpoint and output Endpoint
SFR_WR(EOUTCSRH,0x0); //Endpoint 1, 2, 3 are configured Double Buffer
SFR_WR(INDEX, 0x02);
SFR_WR(EINCSRH, 0x4);
SFR_WR(EOUTCSRH,0x0);
SFR_WR(INDEX, 0x03);
SFR_WR(EINCSRH, 0x4);
SFR_WR(EOUTCSRH,0x0);
SFR_WR(INDEX, 0x00);
SFR_WR(POWER, 0x00); //Enable USB0
}
/*******************************************************************************************
name: SFR_WR
function: wirte the cmd or data to the desired USB FSR by USB0ADDR and USB0DAT
pars: addr(SFR's address), dat(cmd or data)
returns: no
********************************************************************************************/
void SFR_WR(uchar addr, uchar dat)
{
while(USB0ADR>>7);
USB0ADR = addr;
USB0DAT = dat;
}
/********************************************************************************************
name: SFR_RD
function: read the content of the address in USB0ADR
pars: addr
returns: dat
*********************************************************************************************/
uchar SFR_RD(uchar addr)
{
uchar dat;
while(USB0ADR>>7);
USB0ADR = 0x80 + addr;
while(USB0ADR>>7);
dat = USB0DAT;
return dat;
}
/**********************************************************************************************
name: Swap
function: Swap the 8bit High and 8bit Low
pars: dat
renturns: Swap_dat
***********************************************************************************************/
uint Swap(uint dat)
{
uint Swap_dat;
Swap_dat = dat>>8 | dat<<8;
return Swap_dat;
}
/**********************************************************************************************
name: FIFO_WR
function: write data to the output fifo
pars: ptr(data pointer), addr(fifo address), num(length)
returns: no
***********************************************************************************************/
void FIFO_WR(uchar *ptr, uchar addr, uint num) reentrant
{
uint i;
USB0ADR = addr;
for(i=0;i<num;i++)
{
while(USB0ADR>>7);
USB0DAT = *(ptr + i);
}
}
/*void FIFO_RD(uchar addr, uchar num)
{
uchar i;
while(USB0ADR>>7);
USB0ADR = addr + 0xC0;
for(i=0;i<num;i++)
{
while(USB0ADR>>7);
buf[i] = USB0DAT;
}
}*/
/**********************************************************************************************
name: Analysis_Requst
function: analysis the requst report and ackownlage the host
pars: Requst pointer pReq
returns: no
Note: DATAEND is Stage shakehand signal, INPRDY and OPRDY are Phase shakehand signal
EndPoint 0 Control Registor
----------------------------------------------------------------------
| SSUEND | SOPRDY | SDSTL| SUEND | DATAEND | STSTL | INPRDY | OPRDY |
| | | | | | | | |
----------------------------------------------------------------------
***********************************************************************************************/
void Analysis_Requst(Requst * ptr)
{
uchar type, index; //Variables must be defined in front of
uint requst;
uint value;
uint num; //the Code Area
Config_Descriptor * pConfig;
Interface_Descriptor * pInterface;
Config_Long * pConfig_Long;
Device_Descriptor * pDevice; //fore Convert the Structure Type to
pDevice = & device_descriptor; //unsigned character
pConfig = & config_descriptor;
pInterface = & interface_descriptor;
pConfig_Long = & config_long;
value = ptr->wValue;
requst = ptr->bRequst;
num = Swap(ptr->wLength);
type = (uchar)(ptr->wValue & 0x00FF);
index = (uchar)((ptr->wValue & 0xFF00)>>8);
switch (requst)
{
case Set_Addr:
{
//SFR_WR(FADDR, index);
//Must not Read Address first, should always return ZERO Length Packet First, then save the Address
//Otherwise the FADDR is always the Default Address 0x0, the Assigned Address is Random Between 0~127
SFR_WR(E0CSR, 0x0A); //Send ACK and indicate DATA END
SFR_WR(FADDR, index);
while(SFR_RD(FADDR) & BIT7);
break;
}
case Get_Descriptor:
switch (type)
{
case DEVICE:
FIFO_WR((uchar *)pDevice, FIFO0, num);
SFR_WR(E0CSR, 0x0A);
break;
case CONFIG:
if(num<65) //Requst Config Descriptor Only
{
FIFO_WR((uchar *)pConfig, FIFO0, num);
SFR_WR(E0CSR, 0x0A);
}
else
{
FIFO_WR((uchar *)pConfig_Long, FIFO0, 0x20); //Requst Full Configuration
SFR_WR(E0CSR, 0x0A);
}
break;
case STRING:
break;
case INTERFACE:
break;
case ENDPOINT:
break;
}
case Set_Config:
break;
case Set_Interface:
break;
case Get_Max_Lun: //Get the max Logic Unit Number of Device
SFR_WR(FIFO0, 0x0);
SFR_WR(E0CSR, 0x0A);
break;
case Mass_Storage_Reset: //Reset the Device
USB_Config();
break;
}
}
/***************************************************************************************
name: CLR_Flags
function: clear the bulk endpoint interrupt flags
pars: no
returns: no
****************************************************************************************/
void CLR_Flags(void)
{
flags.epin1 = 0;
flags.epout1 = 0;
}
/****************************************************************************************
name: Analysis_UFI
function: analysis the SCSI-UFI commands
pars: no
returns: no
*****************************************************************************************/
void Analysis_UFI(void)
{
if(flags.epin1 && csw) //Bulk in interrupt
{
flags.epin1 = 0;
SFR_WR(INDEX, 0x01);
FIFO_WR((uchar *)pCS, FIFO1, 0x0D);
SFR_WR(EINCSRL, 0x01);
//while(SFR_RD(EINCSRL) & BIT0);
csw = 0;
}
if(flags.epout1) //Bulk out interrupt
{
flags.epout1 = 0;
BulkOut_Process();
}
}
/******************************************************************************************
name: exchange
function: exchange the Big Endian to the Little Endian
pars: dat
returns: temp
******************************************************************************************/
ulong exchange(ulong dat)
{
uint temp1,temp2;
ulong temp;
temp1 = (uint)(dat>>16);
temp2 = (uint)dat;
temp1 = temp1>>8 | temp1<<8;
temp2 = temp2>>8 | temp2<<8;
temp = ((ulong)temp2<<16) | ((ulong)temp1);
return temp;
}
/*****************************************************************************************
name: BulkOut_Process
function: bulk out endpoint process
par: no
returns: no
******************************************************************************************/
void BulkOut_Process()
{
uchar temp1, temp2,temp3,temp4, status, LBAL, LBAH,lbal,lbah,flag, SaddrL, SaddrH;
ulong temp;
uint cnt, i, j, t, PageNum, LBA, lba;
xdata uchar CBWbuf[31];
CBW *pCB;
CSW CSW0;
SFR_WR(INDEX, 1);
status = SFR_RD(EOUTCSRL);
if(status & BIT0) //get the received data length
{
temp1 = SFR_RD(EOUTCNTL);
temp2 = SFR_RD(EOUTCNTH);
cnt = (((uint)temp2)<<8) | ((uint)temp1);
}
for(i=0;i<31;i++)
CBWbuf[i] = SFR_RD(FIFO1); //buffer the Bulk out data
temp1 = SFR_RD(EOUTCSRL);
temp1 &= ~BIT0;
SFR_WR(EOUTCSRL, temp1);
pCB = (pCBW)CBWbuf; //Converte to the CBW format
//make the CSW blok
CSW0.CSWTag = pCB->CBWTag;
CSW0.CSWSignature = 0x55534253;
temp = exchange(pCB->CBWDataLength);
if(temp<MaxSize)
{
CSW0.CSWDataLength = 0;
}
else
{
CSW0.CSWDataLength = 0;
}
pCS = & CSW0; //Send the address of CSW to the write FIFO
//analysis the CBWCB
temp1 = pCB->CBWCB[0];
LBAL = pCB->CBWCB[5];
LBAH = pCB->CBWCB[4];
SaddrH = 0xFF;
if(LBAL & 0x20)
SaddrL = 0xE0;
else
SaddrL = 0xC0;
LBA = (uint)LBAL | ((uint)LBAH)<<8;
PageNum = (0x00FF & (uint)(pCB->CBWCB[8])) | (0x00FF & (uint)(pCB->CBWCB[7])) << 8;
switch (temp1)
{
case Format_Unit:
break;
case Inquiry: //SCSI Inquiry Command process
FIFO_WR(Return_Inquiry, FIFO1, 0x24);
SFR_WR(EINCSRL, 1);
csw = 1;
while(SFR_RD(EINCSRL) & BIT0); //WAIT for send compelete
break;
case Read_Format: //SCSI Read Format Capacity process
FIFO_WR(Return_Read_Format,FIFO1, 0x14);
SFR_WR(EINCSRL, 1);
csw = 1;
while(SFR_RD(EINCSRL) & BIT0); //Wait for send compelete
break;
case Read_Cap:
FIFO_WR(Return_Read_Cap, FIFO1, 0x8); //SCSI Read Capacity process
SFR_WR(EINCSRL, 1);
CSW0.CSWStatus = 0;
csw = 1;
while(SFR_RD(EINCSRL) & BIT0); //Wait for Send compelete
break;
case Prevent_Allow:
FIFO_WR((uchar *)pCS, FIFO1, 0x0D);
SFR_WR(EINCSRL, 1);
csw = 0;
while(SFR_RD(EINCSRL) & BIT0);
break;
case Test_Ready:
//FIFO_WR((uchar *)pCS, FIFO1, 0x0D);
//SFR_WR(EINCSRL, 1);
flags.epin1 = 1;
csw = 1; //Wait for send compelete
break;
case Read_10:
for(t=0;t<PageNum;t++) //SCSI READ10 Process, read data from Flash and send to HOST
{
page_read(0x0, LBAL+(uchar)t, LBAH);
for(i=0;i<8;i++)
{
FIFO_WR(buf + i*MaxSize, FIFO1, MaxSize);
SFR_WR(EINCSRL, 1);
while(SFR_RD(EINCSRL) & BIT0);
}
}
csw = 1;
break;
case Mode_Sense6:
FIFO_WR(Sense, FIFO1, 0x08);
SFR_WR(EINCSRL, 1);
csw = 1;
while(SFR_RD(EINCSRL) & BIT0);
//csw = 1;
break;
case Verify:
flags.epin1 = 1;
csw = 1;
break;
case Write_10: //SCSI WIRTE10 Process, write data to NandFlash
lba = LBA;
block_buffer(LBA);
for(i=0;i<PageNum;i++) //write Host send data to the 512B xdata buffer
{
lbal = (uchar)(lba & 0x00ff);
lbah = (uchar)((lba & 0xff00)>>8);
for(j=0;j<8;j++)
{
for(t=0;t<64;t++)
buf[t+64*j] = SFR_RD(FIFO1);
SFR_WR(EOUTCSRL, 0x0);
}
if(flag = page_program(buf, 0, lbal, lbah, 512)) //program one Sector data to NandFlash
LED = 0;
lba++;
if((i+1)%32==0)
{
LBA += 32;
block_buffer(LBA);
}
}
if(LBA%32)
{
LBAL = (uchar)(LBA & 0x00ff);
LBAH = (uchar)((LBA & 0xff00)>>8);
temp3 = LBAL & 0xE0;
temp4 = LBAL & 0x1F;
for(i=0;i<temp4;i++) //Sector address before Write Sector address
if(flag = copy_back(0, SaddrL+(uchar)i, SaddrH, 0, temp3+(uchar)i, LBAH)) //recover the Sector data before erase
LED = 0;
temp4 = temp4 + PageNum;
for(i=temp4;i<32;i++) //Sector address after Write Sector address
if(flag = copy_back(0, SaddrL+(uchar)i, SaddrH, 0, temp3+(uchar)i, LBAH)) //recover the Sector data before erase
LED = 0;
}
flags.epin1 = 1;
csw = 1;
break;
}
}
/***************************************************************************************
name: Read_ID
function: Read Flash Device ID
pars: no
returns: no
****************************************************************************************/
void Read_ID(void)
{
//Nandflash reset
uchar Data_in;
CE = 0;
CLE = 1;
_nop_();
_nop_();
WE = 0;
DIO = 0xFF;
_nop_();
_nop_();
WE = 1;
_nop_();
_nop_();
CLE =0;
CE = 1;
Delay_mS(10);
//read device ID
CE = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -