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

📄 sst39vf1601.c

📁 用norflash进行树形目录文件管理
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
* 文件名:SST39VF1601.C
* 功能:对SST39VF1601进行控制
* 说明:对flash读、写、擦除,并实现文件管理
****************************************************************************/
#include  "config.h"

// FLASH的起始地址(分配为Bank1块)

uint8 Date[8];
uint8 Set_Date[8]={0x15,0x58,0x23,0x20,0x08,0x08,0x01,0x20};
//日期BCD码格式----秒---分---时---日---月---年---星期---年

uint8 IP[4]={192,168,1,2};
uint8 size;
uint8 X1226_Setb=1;
uint16 dat;
void Gettime(void)
{
	IRcvStr(X1226_CCR|read,0x0030,2,Date,8);
	if(Date[5]>=0x80)
	{
		Date[5]-=0x80;
	}
}
/****************************************************************************
* 名称:DelayNS()
* 功能:长软件延时。
* 入口参数:dly		延时参数,值越大,延时越久
* 出口参数:无
****************************************************************************/
void  DelayNS(uint32  dly)
{  uint32  i;

   for(; dly>0; dly--) 
      for(i=0; i<5000; i++);
}
/****************************************************************************
* 名称:WordRead()
* 功能:半字(16位)数据读。
* 入口参数:Addr		回读地址(SST39VF1601内部地址)	
* 
* 出口参数:返回Addr地址16位数据
****************************************************************************/
uint16 WordRead(uint32 Addr)
{    
	 volatile uint16  *ip;
	 uint16  temp1,temp2;
	 
	 if(Addr>MaxAddr)
        return FALSE;
	 ip = GetAddr(Addr);
	 while(1)
	 {
		  temp1 = *ip;			
	      temp2 = *ip;
	      if (temp1 == temp2)
	      {  
	           return temp1;
	      }
	 }
	 
}
/****************************************************************************
* 名称:WordProgram()
* 功能:半字(16位)数据编程。
* 入口参数:Addr	编程地址(SST39VF1601内部地址)	000000H-0FFFFFH Byte
*           Data	编程数据
* 出口参数:返回TRUE表示操作成功,返回FALSE表示操作失败
****************************************************************************/
uint8  WordProgram(uint32 Addr, uint16 Data) 
{  
   volatile uint16  *ip;
   uint16  temp1,temp2;
   
   if(Addr>MaxAddr)
      return FALSE;
   //for test
   /*
   if(Addr==481*2*1024+7||Addr==481*2*1024+15)//Addr地址坏
   {
   		return(FALSE);
   }
   if(Addr==496*2*1024+5||Addr==496*2*1024+15)//Addr地址坏
   {
   		return(FALSE);
   }
   */
   ip = GetAddr(0x5555);// 转换地址0x5555
   *ip = 0xaa;			// 第一个写周期,地址0x5555,数据0xAA
   ip = GetAddr(0x2aaa);
   *ip = 0x55;			// 第二个写周期,地址0x2aaa,数据0x55
   ip = GetAddr(0x5555);
   *ip = 0xa0;			// 第三个写周期,地址0x5555,数据0xA0
    
   ip = (volatile uint16  *)(FLASH_ADDR|((Addr<<1)&0x1FFFFF));
   *ip = Data;				// 第四个写周期,地址Addr,数据Data
   
   while (1)				// 等待操作完成 (若编程操作没有完成,每次读操作DQ6会跳变)
   {  temp1 = *ip;			
      temp2 = *ip;
      if (temp1 == temp2)
      {  if (temp1 != Data)
         {  
         	return(FALSE);
         }
         else
         {  
         	return(TRUE);
         }
      }
   }
   
   return(TRUE);
}

/****************************************************************************
* 名称:SectorErase()
* 功能:芯片扇区擦除。
* 入口参数:扇区0-511
* 出口参数:返回TRUE表示操作成功,返回FALSE表示操作失败
****************************************************************************/
uint8  SectorErase(uint32 sector_index) 
{  
   volatile uint16  *ip;
   uint16  temp1,temp2;

   if(sector_index>(MaxAddr/1024/2))
      return FALSE;
   ip = GetAddr(0x5555);
   *ip = 0xaa;			// 第一个写周期,地址0x5555,数据0xAA
   ip = GetAddr(0x2aaa);
   *ip = 0x55;			// 第二个写周期,地址0x2aaa,数据0x55
   ip = GetAddr(0x5555);
   *ip = 0x80;			// 第三个写周期,地址0x5555,数据0x80
   ip = GetAddr(0x5555);
   *ip = 0xaa;			// 第四个写周期,地址0x5555,数据0xAA
   ip = GetAddr(0x2aaa);
   *ip = 0x55;			// 第五个写周期,地址0x2aaa,数据0x55
   ip = (uint16 *)(FLASH_ADDR|sector_index<<12);
   *ip = 0x30;			// 第六个写周期,扇区地址,数据0x30

   while (1)				// 等待操作完成 (若擦除操作没有完成,每次读操作DQ6会跳变)
   {  temp1 = *ip;
      temp2 = *ip;
      if (temp1 == temp2)
      {  if (temp1 != 0xffff)
         {  return(FALSE);
         }
         else
         {  return(TRUE);
         }
      }
   }
   return(TRUE);
}

/****************************************************************************
* 名称:BlockErase()
* 功能:芯片块擦除。
* 入口参数:块0-31
* 出口参数:返回TRUE表示操作成功,返回FALSE表示操作失败
****************************************************************************/
uint8  BlockErase(uint8 block_index) 
{  
   volatile uint16  *ip;
   uint16  temp1,temp2;
   if(block_index>(MaxAddr/1024/32))
      return FALSE;

   ip = GetAddr(0x5555);
   *ip = 0xaa;			// 第一个写周期,地址0x5555,数据0xAA
   ip = GetAddr(0x2aaa);
   *ip = 0x55;			// 第二个写周期,地址0x2aaa,数据0x55
   ip = GetAddr(0x5555);
   *ip = 0x80;			// 第三个写周期,地址0x5555,数据0x80
   ip = GetAddr(0x5555);
   *ip = 0xaa;			// 第四个写周期,地址0x5555,数据0xAA
   ip = GetAddr(0x2aaa);
   *ip = 0x55;			// 第五个写周期,地址0x2aaa,数据0x55
   ip = (uint16 *)(FLASH_ADDR|block_index<<16);
   *ip = 0x50;			// 第六个写周期,块地址,数据0x30


   while (1)				// 等待操作完成 (若擦除操作没有完成,每次读操作DQ6会跳变)
   {  temp1 = *ip;
      temp2 = *ip;
      if (temp1 == temp2)
      {  if (temp1 != 0xffff)
         {  return(FALSE);
         }
         else
         {  return(TRUE);
         }
      }
   }
   return(TRUE);
}

/****************************************************************************
* 名称:ChipErase()
* 功能:芯片全片擦除。
* 入口参数:无
* 出口参数:返回TRUE表示操作成功,返回FALSE表示操作失败
****************************************************************************/
uint8  ChipErase(void) 
{  
   volatile uint16  *ip;
   uint16  temp1,temp2;

   ip = GetAddr(0x5555);
   *ip = 0xaa;			// 第一个写周期,地址0x5555,数据0xAA
   ip = GetAddr(0x2aaa);
   *ip = 0x55;			// 第二个写周期,地址0x2aaa,数据0x55
   ip = GetAddr(0x5555);
   *ip = 0x80;			// 第三个写周期,地址0x5555,数据0x80
   ip = GetAddr(0x5555);
   *ip = 0xaa;			// 第四个写周期,地址0x5555,数据0xAA
   ip = GetAddr(0x2aaa);
   *ip = 0x55;			// 第五个写周期,地址0x2aaa,数据0x55
   ip = GetAddr(0x5555);
   *ip = 0x10;			// 第六个写周期,地址0x5555,数据0x10

   while (1)				// 等待操作完成 (若擦除操作没有完成,每次读操作DQ6会跳变)
   {  temp1 = *ip;
      temp2 = *ip;
      if (temp1 == temp2)
      {  if (temp1 != 0xffff)
         {  return(FALSE);
         }
         else
         {  return(TRUE);
         }
      }
   }
   return(TRUE);
}
/****************************************************************************
* 名称:Ram_Flash_Copy()
* 功能:从ram中拷贝size个数据到flash
****************************************************************************/
/*
uint8	Ram_Flash_Copy( uint8* ram_ptr,uint16* flash_ptr, uint32 size )				
{
	uint32	cnt;
	uint16  dat=0;


	if( ( size % 2 ==1))   	//   size  should be  even
		size++;
	for(cnt =0 ;cnt< (size/2) ;cnt++)
	{
		dat = *ram_ptr++;			// low byte
		dat = dat + (*ram_ptr++)* 256;// high byte
		WordProgram( flash_ptr ,dat);
		flash_ptr++	;
	}
	return 1;
}
*/

/****************************************************************************
* 名称:Create_log()
* 功能:创建一个日志
****************************************************************************/
uint8 Create_log(uint16 *array,uint8 len)
{
	uint16 *p,
	       total_log=0,//日志总数
	       log_len=0;//待创建日志长度
	uint32 w_addr,
	       index_start_address=0,//目录起始地址
	       old_index_start_address=0,//写出错时目录起始地址备份
	       index_address=0,//待创建日志目录地址
	       log_address=0;//待创建日志存储地址
	uint16 i=0;

	//查找目录起始地址和带创建日志存储地址
	total_log=WordRead(480*2*1024);//第480 sector第一个Word为总日志数
	
	if(total_log>Max_log)
	{
	    total_log=0;
	    
	    BlockErase(30);
	    
	    BlockErase(31);
	}    
	if(!total_log)   
	{    
	    index_start_address=Log_index_Init_Addr;//目录起始地址为初始地址
	    
	    log_address=Log_Init_Addr;//日志存储地址为初始地址
    }
    else
    {
    	
    	index_start_address=((uint32)WordRead(480*2*1024+1)<<16)+WordRead(480*2*1024+2);//读目录起始地址
    	
    	if(index_start_address+(total_log-1)*3<496*2*1024-2)//查找最新日志存储地址
	    {	
	    	log_address=((uint32)WordRead(index_start_address+(total_log-1)*3)<<16)
	    	            +WordRead(index_start_address+1+(total_log-1)*3)
	    	             +WordRead(index_start_address+2+(total_log-1)*3);
    	}
    	else if(index_start_address+(total_log-1)*3==496*2*1024-2)
    	{
    		log_address=((uint32)WordRead(496*2*1024-2)<<16)
	    	            +WordRead(496*2*1024-1)
	    	             +WordRead(481*2*1024);
    	}
    	else if(index_start_address+(total_log-1)*3==496*2*1024-1)
    	{
    		log_address=((uint32)WordRead(496*2*1024-1)<<16)
	    	            +WordRead(491*2*1024)
	    	             +WordRead(481*2*1024+1);	
    	}
    	else
    	{
    		log_address=((uint32)WordRead(index_start_address+(total_log-1)*3-(496-481)*2*1024)<<16)
	    	            +WordRead(index_start_address+1+(total_log-1)*3-(496-481)*2*1024)
	    	             +WordRead(index_start_address+2+(total_log-1)*3-(496-481)*2*1024);
    	}
    	
    	if(log_address>512*2*1024-1)
    	{   
    	   log_address=Log_Init_Addr+(log_address-512*2*1024);
    	}
    }
    
    //将最新日志存储(496-511 sector),若遇到坏地址,跳过并将日志重新写入
    if(len%2)
   		log_len=(len+1)/2;
    else
   		log_len=len/2;   
   		
	p=array;
	
	w_addr=log_address;
	
	for(i=0;i<log_len;)
	{
		if(!WordProgram(w_addr, *p))
		{
			w_addr++;
			
			if(!(w_addr%(2*1024)))
			{
				if((w_addr/(2*1024))<512)
				{  	
				   SectorErase(w_addr/(2*1024));
				}
		        else
		        {
		           SectorErase(496);
		           w_addr=496*2*1024;
		        }
			}
			p=array;
			
			i=0;
			
			log_address=w_addr;
		}
		else
		{   
			w_addr++;
			
			if(!(w_addr%(2*1024)))
			{
				if((w_addr/(2*1024))<512)
				{  	
				   SectorErase(w_addr/(2*1024));
				}
		        else
		        {
		           SectorErase(496);
		           w_addr=496*2*1024;
		        }
			}		
			p++;
			
			i++;
		}      			
	}
	
	//更新最新日志目录(481-495 sector),若遇到坏地址,将所有日志目录复制到连续空间
	index_address=index_start_address+total_log*3;
	
	if(index_address>496*2*1024-1)
	{
		index_address-=15*2*1024;
		if(!(index_address%(2*1024)))
		{
			if((index_address/(2*1024))<496)
			{  	
			   SectorErase(index_address/(2*1024));
			}
	        else
	        {
	           SectorErase(481);
	           index_address=481*2*1024;
	        }
		}		
	}
L1: if(!WordProgram(index_address,log_address>>16))//1.写新日志存储地址高16位到日志目录
	{
		old_index_start_address=index_start_address;
		
L2:     if(!(++index_address%(2*1024)))
		{
			if((index_address/(2*1024))<496)
			{  	
			   SectorErase(index_address/(2*1024));
			}
	        else
	        {
	           SectorErase(481);
	           index_address=481*2*1024;
	        }
		}		
		
		index_start_address=index_address;
		
		for(i=0;i<total_log*3;i++)//将旧日志目录拷贝至好地址开始的连续空间
		{
			if(index_address==old_index_start_address)
			{
				return Flash_log_ERROR;//返回Flash_log_ERROR指示该flash日志不能使用
			}
			if(old_index_start_address+i<496*2*1024)
			{
				if(!WordProgram(index_address,WordRead(old_index_start_address+i)))
				{		
					if(!(++index_address%(2*1024)))
					{
						if((index_address/(2*1024))<496)
						{  	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -