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

📄 flash64.c

📁 mp3播放器软件
💻 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 + -