📄 flash64.c
字号:
/************************************************************/
/* FLASH.C */
/* T-SQUARE DESIGN */
/* */
/* BY CRAZY ZENG */
/* JUL.9 2002 */
/************************************************************/
/*
#pragma code debug small src
#include<flash.h>
#include<stdio.h>
#include<reg51.h>
#include<absacc.h>
#include<intrins.h>
*/
xdata struct AbsAddress DataBase; // record base address of data area
xdata struct AbsAddress DirectoryBase;//record base address of Directory Entry
xdata struct AbsAddress FatBase;//record base address of fat
xdata unsigned int Offset = 100;
void Wp(bit Mode)
{
if(Mode)
{
XBYTE[EGPIO_OUT+1]=XBYTE[EGPIO_OUT+1]|0x10;
}
else
{
XBYTE[EGPIO_OUT+1]=XBYTE[EGPIO_OUT+1]&0xef;
}
}
//--------------------------------------------------------------------
//Purpose : Select one nand flash for writing or reading
//Input : Number----card number
//Output : NONE
//Reference :
//Example :
//--------------------------------------------------------------------
void SelectCard(char Number)
{
XBYTE[SMC_CTL] = 0x88|(0x70&(Number<<4));
}
//--------------------------------------------------------------------
//Purpose : read nand flash
//Input : PageAddr---page address
//Output : the specified data is read into buffer
//Reference:
//Example :
//--------------------------------------------------------------------
bit SmcRead(unsigned long PageAddr)
{
xdata unsigned char c;
xdata unsigned int i;
i = (unsigned int)PageAddr;
if (PageAddr>=0x10000)
c = 1;
else c = 0;
XBYTE[SMC_CMD] = 0;
#ifdef Flash_64M
XBYTE[SMC_MADDR] = 0;
XBYTE[SMC_MADDR] = (unsigned char)i;
XBYTE[SMC_MADDR] = (unsigned char)(i>>8);
XBYTE[SMC_ADDR] = (unsigned char)c;
#else
XBYTE[SMC_MADDR] = 0;
XBYTE[SMC_MADDR] = (unsigned char)PageAddr;
XBYTE[SMC_ADDR] = (unsigned char)(PageAddr>>8);
#endif
if(WaitNotBusy()==FALSE)return FALSE;
XBYTE[SMC_DCTRL_L] = 0;
XBYTE[SMC_DCTRL_H] = 0x80;
i = 0;
while (!((c = XBYTE[SMC_ISR]) & 0x02)) {
if (i++ > 500)
return FALSE;
}
XBYTE[SMC_ISR] = 0x02;
return WaitNotBusy();
}
//--------------------------------------------------------------------
//Purpose : read status
//Input :
//Output :
//Reference:
//Example :
//--------------------------------------------------------------------
/*
bit SmcReadStatus(unsigned char BufferNo)
{
unsigned char i;
XBYTE[SMC_CMD] = 0x70;
XBYTE[SMC_DCTRL_L] = 1;
XBYTE[SMC_DCTRL_H] = 0x80;
i = 100;
while((XBYTE[SMC_ISR] &0x02) ==0)
{
if(--i==0)return FALSE;
}
XBYTE[SMC_ISR] = 0x02;
if(WaitNotBusy()==FALSE)return FALSE;
XBYTE[0x0e+BufferNo] = 0;
i = XBYTE[0x1000+BufferNo*0x200]&0x01;
if(i ==1)return FALSE;
return TRUE;
}
*/
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//Purpose : erase one block
//Input : BlockAddr----block address
//Output :
//Reference:
//Example :
//--------------------------------------------------------------------
bit SmcBlockErase(unsigned short BlockAddr)
{
unsigned long addr_b;
bit Flg;
Wp(1);
addr_b = BlockAddr;
addr_b = addr_b<<5;
XBYTE[SMC_CMD] = 0x60;
#ifdef Flash_64M
XBYTE[SMC_MADDR] = (unsigned char) addr_b;
XBYTE[SMC_MADDR] = (unsigned char)(addr_b >>8);
XBYTE[SMC_ADDR] = (unsigned char)(addr_b >>16);
#else
XBYTE[SMC_MADDR] = addr_b &0x0ff;
XBYTE[SMC_ADDR] = addr_b >>8;
#endif
XBYTE[SMC_CMD] = 0xd0;
Flg = WaitNotBusy();
Wp(0);
return Flg;
}
//--------------------------------------------------------------------
//Purpose : write one page data to nand flash
//Input : PageAddr---page address
//Output : the data of the selected buffer will be write to nand flash
//Reference:
//Example :
//--------------------------------------------------------------------
/*bit SmcPageProgram(unsigned short PageAddr)
{
xdata unsigned int i;
xdata unsigned char c;
xdata unsigned char Page;
Page = (unsigned int)(PageAddr>>16);
XBYTE[SMC_CMD] = 0;
XBYTE[SMC_CMD] = 0x80;
XBYTE[SMC_MADDR] = 0;
XBYTE[SMC_MADDR] = (unsigned char)PageAddr;
XBYTE[SMC_ADDR] = (unsigned char)(PageAddr>>8);
//XBYTE[SMC_ADDR] = Page;
XBYTE[SMC_DCTRL_L] = 0;
XBYTE[SMC_DCTRL_H] = 0xc0;
i = 0;
while (!((c = XBYTE[SMC_ISR]) & 0x02)) {
if (i++ > 500)
return FALSE;
}
XBYTE[SMC_ISR] = 0x02;
XBYTE[SMC_CMD] = 0x10;
return WaitNotBusy();
}*/
bit SmcPageProgram(unsigned long PageAddr)
{
xdata unsigned char c;
xdata unsigned int i;
bit Flg;
Wp(1);
i = (unsigned int)PageAddr;
if (PageAddr>=0x10000)
c = 1;
else c = 0;
XBYTE[SMC_CMD] = 0;
XBYTE[SMC_CMD] = 0X80;
#ifdef Flash_64M
XBYTE[SMC_MADDR] = 0;
XBYTE[SMC_MADDR] = (unsigned char)i;
XBYTE[SMC_MADDR] = (unsigned char)(i>>8);
XBYTE[SMC_ADDR] = (unsigned char)c;
#else
XBYTE[SMC_MADDR] = 0;
XBYTE[SMC_MADDR] = (unsigned char)PageAddr;
XBYTE[SMC_ADDR] = (unsigned char)(PageAddr>>8);
#endif
XBYTE[SMC_DCTRL_L] = 0;
XBYTE[SMC_DCTRL_H] = 0xc0;
i = 0;
while (!((c = XBYTE[SMC_ISR]) & 0x02)) {
if (i++ > 500)
{
Wp(0);
return FALSE;
}
}
XBYTE[SMC_ISR] = 0x02;
XBYTE[SMC_CMD] = 0x10;
Flg = WaitNotBusy();
Wp(0);
return Flg;
}
//--------------------------------------------------------------------
//Purpose : wait nand flash operation finished
//Input : NONE
//Output : if busy return FALSE
//Reference:
//Example :
//--------------------------------------------------------------------
bit WaitNotBusy()
{
xdata unsigned short cc;
cc = 1000;
while (1) {
if ((XBYTE[SMC_STATUS] & 0x01)==0x01)
return (1);
if (!cc--) return (0);
}
}
//--------------------------------------------------------------------
//Purpose : Get disk file struct information
//Input : NONE
//Output : this function will set global variable(PbrInfo,FatBase,DirectoryBase,DataBase) by PBR
//Reference:
//Example :
//--------------------------------------------------------------------
bit IniLogicDisk()
{
xdata unsigned int BootOffset;
xdata unsigned int DirectoryAddr;
xdata unsigned int DataAddr;
BootOffset = Offset*32;
do{
MemoryRw;
SmcRead(BootOffset);
McuRw;
if((XBYTE[0x11fe] == 0x55) && (XBYTE[0x11ff] == 0xaa))
{
break;
}
}while(++BootOffset < 3232);//fine PBR from block one to block 100
if(BootOffset == 3232)return FALSE;
PbrInfo.BytePerSector = XBYTE[0x100c];
PbrInfo.BytePerSector <<=8;
PbrInfo.BytePerSector += XBYTE[0x100b];
PbrInfo.SectorPerCluster = XBYTE[0x100d];
PbrInfo.NumFats = XBYTE[0x1010];
PbrInfo.RootDirEntry = XBYTE[0x1012];
PbrInfo.RootDirEntry <<= 8;
PbrInfo.RootDirEntry += XBYTE[0x1011];
if((XBYTE[0x1013] == 0)&&(XBYTE[0x1014] == 0))
{
PbrInfo.TotolSector = XBYTE[0x1023]; //Total Sector' width is double word
PbrInfo.TotolSector <<= 8;
PbrInfo.TotolSector += XBYTE[0x1022];
PbrInfo.TotolSector <<=8;
PbrInfo.TotolSector += XBYTE[0x1021];
PbrInfo.TotolSector <<=8;
PbrInfo.TotolSector += XBYTE[0x1020];
}else{
PbrInfo.TotolSector = 0; //Total Sector' width is word
PbrInfo.TotolSector = XBYTE[0x1014];
PbrInfo.TotolSector <<= 8;
PbrInfo.TotolSector += XBYTE[0x1013];
}
PbrInfo.MediaId = XBYTE[0x1015];
PbrInfo.NumFatSector = XBYTE[0x1017];
PbrInfo.NumFatSector <<=8;
PbrInfo.NumFatSector += XBYTE[0x1016];
if((XBYTE[0x1036] !='F')||(XBYTE[0x1037]!='A')||(XBYTE[0x1038]!='T'))return FALSE;
PbrInfo.FatFormat = XBYTE[0x1039] - 0x30;
PbrInfo.FatFormat <<= 4;
PbrInfo.FatFormat += (XBYTE[0x103a] - 0x30);
BootOffset = Offset*32;
do{
MemoryRw;
SmcRead(BootOffset);
McuRw;
if((XBYTE[0x1000] == 0xf8) && (XBYTE[0x1001] == 0xff))
{
break;
}
}while(++BootOffset < 3232);//fine PBR from block one to block 100
if(BootOffset == 3232)return FALSE;
FatBase.Block = (BootOffset)>>5;
FatBase.Page = (BootOffset) %32;
DirectoryAddr = PbrInfo.NumFatSector*PbrInfo.NumFats+ BootOffset ;
DirectoryBase.Block = DirectoryAddr>>5;
DirectoryBase.Page = DirectoryAddr%32;
DataAddr = DirectoryAddr + (PbrInfo.RootDirEntry>>4);
if((PbrInfo.RootDirEntry%16)!=0)
{
DataAddr++;
}
DataBase.Block = DataAddr>>5;
DataBase.Page = DataAddr%32;
return TRUE;
}
//--------------------------------------------------------------------
//Purpose : transfer logic address to absolute address and write data nand flash
//Input : LogicAddr---logic address
//Output : the specified data to buffer
//Reference:
//Example :
//--------------------------------------------------------------------
bit ReadLogicPage(struct LogicAddress* LogicAddr)
{
xdata unsigned long PageAddr;
xdata unsigned int Temp ;
xdata unsigned long Page;
if(LogicAddr->Cluster ==0)//the logic zero is map to FAT
{
PageAddr = FatBase.Block*32+FatBase.Page+LogicAddr->Sector;
}else{
if(LogicAddr->Cluster ==1)//The logic one is map to FCB
{
PageAddr = DirectoryBase.Block*32+DirectoryBase.Page+LogicAddr->Sector;
}else{
//That is data area after logic one
PageAddr = DataBase.Block*32 ;
PageAddr = PageAddr +DataBase.Page;
Page = LogicAddr->Cluster-2;
Page = Page * PbrInfo.SectorPerCluster;
PageAddr = PageAddr +Page;
PageAddr = PageAddr +LogicAddr->Sector;
}
}
Temp = 0;
Page = PageAddr;
while(1)
{
if(Page<15872)break;
Page = Page-15872;
Temp++;
}
PageAddr = PageAddr + Temp*512;
return SmcRead(PageAddr);
}
bit WriteLogicPage(struct LogicAddress* LogicAddr)
{
xdata unsigned long PageAddr;
xdata unsigned long Page;
xdata unsigned int Temp;
PageAddr = DataBase.Block*32 ;
PageAddr = PageAddr +DataBase.Page;
Page = LogicAddr->Cluster-2;
Page = Page * PbrInfo.SectorPerCluster;
PageAddr = PageAddr +Page;
PageAddr = PageAddr +LogicAddr->Sector;
Temp = 0;
Page = PageAddr;
while(1)
{
if(Page<15872)break;
Page = Page-15872;
Temp++;
}
PageAddr = PageAddr + Temp*512;
return SmcPageProgram(PageAddr);
}
//--------------------------------------------------------------------
//Purpose : finshed one fat chain
//Input : FurstLogicAddr---The first table item of chain that will be establish this time
// LogicLength------The logic length of chain that will be establish this time
// PreLastLogicAddr-The final logic address of the chain that was being establish last time
//Output :
//Reference:
//Example :
//--------------------------------------------------------------------
bit WriteFat(unsigned int PageOffset)
{
xdata unsigned int Block;
xdata unsigned char Page;
xdata unsigned long PageAddr;
PageAddr = FatBase.Block*32+FatBase.Page+PageOffset;
Block = PageAddr>>5;
Page = PageAddr%32;
BackupData(Block,Page,0);
}
bit WriteFcb(unsigned int PageOffset)
{
unsigned long PageAddrSrc;
unsigned int Block;
unsigned char Page;
PageAddrSrc = DirectoryBase.Block*32 + DirectoryBase.Page + PageOffset;
Page = PageAddrSrc%32;
Block= PageAddrSrc>>5;
BackupData(Block,Page,0);
}
//--------------------------------------------------------------------
//Purpose : backup the other page when write one page or erase multi page in one Block .
//Input : BlockSrc---the Block address,some page of this block will not be write in erase this block
// PageStart--the page number in BlockSrc
// Length-----the number of not being write page.
//Output :
//Reference:
//Example :
//--------------------------------------------------------------------
bit BackupData(unsigned int BlockSrc,unsigned char PageStart,unsigned char Length)
{
xdata unsigned int BlockDst;
xdata unsigned long PageAddrSrc;
xdata unsigned long PageAddrDst;
xdata unsigned char i;
xdata unsigned char LogicLength;
BlockDst = (BlockSrc>>9)*512 + 496;
McuRw;
for(i = 0;i<16;i++)
{
if(SmcBlockErase(BlockDst)==TRUE)break;
BlockDst++;
}
if(i == 16)return FALSE;
PageAddrSrc = BlockSrc*32;
PageAddrDst = BlockDst*32;
LogicLength=Length;
if(Length == 0)
{
Length++;
MemoryRw;
SmcPageProgram(PageAddrDst+PageStart);
McuRw;
}
for(i=0;i<32;i++)
{
if(i == PageStart)
{
i+=Length;
}
if(i==32)break;
//MemoryRw;
XBYTE[0x0f] = 1;
SmcRead(PageAddrSrc+i);
SmcPageProgram(PageAddrDst+i);
XBYTE[0x0f] = 0;
//McuRw;
}
if(SmcBlockErase(BlockSrc)==FALSE)return FALSE;
for(i=0;i<32;i++)
{
if(i == PageStart)
{
i+=LogicLength;
}
if(i==32)break;
//MemoryRw;
XBYTE[0x0f] = 1;
SmcRead(PageAddrDst+i);
SmcPageProgram(PageAddrSrc+i);
XBYTE[0x0f] = 0;
//McuRw;
}
bit ReqDiskSpace(unsigned int FirstLogicAddrLow,unsigned int FirstLogicAddrHigh,unsigned int LogicLength,bit Mode)
{
unsigned long PageAddrSrc;
unsigned long PageAddrDst;
unsigned int BlockStart;
unsigned int BlockEnd;
unsigned char PageStart;
unsigned char PageEnd;
unsigned int ICount;
unsigned char CCount;
if(Mode==Remov_Mode)
{
PageAddrSrc = FirstLogicAddrHigh;//The parameter FirstLogicAddrLow/High is absoulte address
PageAddrSrc <<= 16;
PageAddrSrc +=FirstLogicAddrLow+Offset*32;
PageAddrDst = PageAddrSrc+LogicLength-1;
}
else
{
//The parameter FirstLogicAddrLow/High is logic cluster number
//PageAddrSrc = DataBase.Block*32+DataBase.Page+(FirstLogicAddrLow-2)*PbrInfo.SectorPerCluster;
PageAddrSrc = FirstLogicAddrLow-2;
PageAddrSrc = PageAddrSrc * PbrInfo.SectorPerCluster;
PageAddrSrc = PageAddrSrc + DataBase.Block*32+DataBase.Page;
PageAddrDst = PageAddrSrc + LogicLength*PbrInfo.SectorPerCluster-1;
}
BlockStart = PageAddrSrc>>5;
BlockStart+= (BlockStart/496)*16;
PageStart = PageAddrSrc % 32;
////////////////////////////////////
BlockEnd = PageAddrDst>>5;
BlockEnd += (BlockEnd/496)*16;
PageEnd = PageAddrDst % 32;
///////////////////////////////////
if(BlockStart != BlockEnd)
{
BackupData(BlockStart,PageStart,32-PageStart);
BackupData(BlockEnd,0,PageEnd+1);
}
else
{
BackupData(BlockStart,PageStart,PageEnd-PageStart+1);
}
////////////////////////////////////
for(ICount = BlockStart+1;ICount<BlockEnd;ICount++)
{
if((ICount%512)==496)
ICount+=16;
if(SmcBlockErase(ICount)==FALSE)return FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -