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

📄 复件 flash.c.bak

📁 在SoC单片机上实现对内部Flash的操作,基于uc/os-II.
💻 BAK
📖 第 1 页 / 共 2 页
字号:
/******************文件名 upsd_flash.c**********************
*马斌 05/10/28
*修改 05/10/30   
*  05/10/31  在底层函数 擦除,读写中增加清零看门狗和延时 OSTimeDly(3);  // now delay 3 msec per dat sheet
*修改 05/11/11   加锁  
**************说明********************
*(1)    先初始化置位Sector_Status为UNUSED,为了以后扩充flash状态定义为字节型.
*(2)  对flash的读写擦除操作都只有当Sector_Status为UNUSE时能够执行,并将置位Sector_Status为USED,
*       操作完毕置位Sector_Status为UNUSED,释放flash  .(可考虑用ucos的信号量,研究中.....)
*     也就是说对flash的操作是完全占有式.
*(3)    本模块是在以下前提下编写:
*     对用户而言仅仅只有一个256k大小的flash存储器 ,可在0x0000 0000 --->0x003F FFFF 内随意读写,
*     但,读写不能同时发生.
*     从0地址开始写,当所给地址是0x8000(32k)的倍数时,说明要写下一个扇区,此时擦除改扇区后再写.
*(4)    初始化时没必要擦除flash,只要置位Sector_Status为UNUSED表示flash闲置既可.因为如果按照正规
*     的写法从0开始写,一旦发现所给地址是扇区的第一个地址会自动擦除该扇区.
**************缺点************************
*(1)  写的时候不能读:ucos采用抢占式优先,当有任务中正在采集数据,写flash的时候其它任务等待.
*   按说应该是当分配的时间片用完就要转到次优先级任务,但是当我测试一次写64k的数据时待等待了
*   近30秒,才执行下一任务.测试写入1k时,不受影响.
*(2)   擦除的时候不能读. 比如擦除0扇区的时候,不能读扇区1的内容.
**************************************************************/
#include "includes.h"
extern PSD_REGS PSD8xx_reg _at_ 0x8000;
unsigned char MemLock;    //锁只加到用户API上
/***************************API**********************/
 
void init_flash(void)reentrant
{
   MemLock = UNUSED;
}
/***************************************************************
函数名:              ycc_mem_read
功能描述:   从flash存储器中的指定位置读取指定长度的字节
参数 :      buf 数据缓冲区地址
            len 要读取的数据数目
            pos flash的相对地址
注意:       该函数面向用户,flash的内部操作通过该函数对用户透明
说明 :      成功返回1,失败返回0
**************************************************************/


unsigned char ycc_mem_read(unsigned int *buf, int len,unsigned long pos)reentrant
{
  unsigned long Input_flash_addr;
	unsigned int xdata * Real_Flash_Addr;   //扇区绝对地址
	if(pos<0||pos>=0x40000)  return(0); //判断越界
	Input_flash_addr = pos;                                          //由flash状态判断
 
	 FlashLock();  

            //选择扇区 0~~7
    switch(Input_flash_addr/0x8000) 
	{
		case 0 :PSD8xx_reg.PAGE = SECTOR_0;
		        // Input_Flash_Addr -= 0 ;
		         break;
		case 1 :PSD8xx_reg.PAGE = SECTOR_1;
		        Input_flash_addr -= 0x8000;
		        break;
		
		case 2 :PSD8xx_reg.PAGE = SECTOR_2;
		        Input_flash_addr -= 0x10000;		        
		        break;
		case 3 :PSD8xx_reg.PAGE = SECTOR_3;
		        Input_flash_addr -= 0x18000;		        
		        break;
		case 4 :PSD8xx_reg.PAGE = SECTOR_4;
		        Input_flash_addr -= 0x20000;		        
		        break;
		case 5 :PSD8xx_reg.PAGE = SECTOR_5;
		        Input_flash_addr -= 0x28000;
		        break;
		case 6 :PSD8xx_reg.PAGE = SECTOR_6;
		        Input_flash_addr -= 0x30000;		        
		        break;
		case 7 :PSD8xx_reg.PAGE = SECTOR_7;
		        Input_flash_addr -= 0x38000;
		        break;
		default :
		             ;  //越界	
		        break;
	 }
	 //获得flash存储器的绝对地址
	 Real_Flash_Addr = SECTOR_BASE_ADDRESS + (unsigned int)Input_flash_addr; 
		      //检查所在扇区
	 Move_from_flash ( Real_Flash_Addr,buf, len);  //从flash中读数据到缓冲区
  FlashUnLock(); 

	 return(1);

}
/***************************************************************
函数名:              ycc_mem_write
功能描述:   向flash存储器中的相对位置写入指定长度的字节
参数 :      buf 数据缓冲区地址
            len 要写入的数据数目
            pos flash的相对地址
注意:       该函数面向用户,flash的内部操作通过该函数对用户透明
说明 :      成功返回1,失败返回0
**************************************************************/
unsigned char ycc_mem_write(unsigned char *buf, int len,unsigned long pos)reentrant
{
//	unsigned long Input_Flash_Addr;
	unsigned int xdata * Real_Flash_Addr;   //扇区绝对地址
	if(pos<0||pos>=0x40000)  return(0); //判断越界
  FlashLock();      
    switch(pos/0x8000)       //选择扇区 0~~7
	{
		case 0 :PSD8xx_reg.PAGE = SECTOR_0;
		        // Input_Flash_Addr -= 0 ;
		         break;
		case 1 :PSD8xx_reg.PAGE = SECTOR_1;
		        pos -= 0x8000;
		        break;
		
		case 2 :PSD8xx_reg.PAGE = SECTOR_2;
		        pos -= 0x10000;		        
		        break;
		case 3 :PSD8xx_reg.PAGE = SECTOR_3;
		        pos -= 0x18000;		        
		        break;
		case 4 :PSD8xx_reg.PAGE = SECTOR_4;
		       pos -= 0x20000;		        
		        break;
		case 5 :PSD8xx_reg.PAGE = SECTOR_5;
		        pos -= 0x28000;
		        break;
		case 6 :PSD8xx_reg.PAGE = SECTOR_6;
		        pos -= 0x30000;		        
		        break;
		case 7 :PSD8xx_reg.PAGE = SECTOR_7;
		        pos -= 0x38000;
		        break;
		default :
		             ;  //越界	
		        break;
	 }
	 //获得flash存储器的绝对地址
	 Real_Flash_Addr = SECTOR_BASE_ADDRESS + (unsigned int)pos ; 
     //检查所在扇区,如果绝对地址在扇区开始的位置,则先擦除扇区.
	 if( Real_Flash_Addr ==	SECTOR_BASE_ADDRESS) flash_erase_sector(Real_Flash_Addr); 
	  Move_to_flash( buf,Real_Flash_Addr, len) ;  //把缓冲区的数据编程到flash中
	 FlashUnLock(); 
}
/***********************底层函数****************************/
/***************************************************************
函数名:              flash_write_with_poll
功能描述:   在flash中写入一个字节,用数据轮询方式
参数 :      volatile unsigned char xdata* addr 待写入字节的位置
            unsigned char dat 待写入的字节
注意:       传入的地址应该和flash存储器的分页关系无关,否则,在调用该函数前,应给PSD中页寄存器赋正确的值.
            成功返回1,失败返回0.
**************************************************************/

unsigned char flash_write_with_poll(volatile unsigned char xdata* addr, unsigned char dat)reentrant
{	
	unsigned char done;
	unsigned char error;
	unsigned char err;
	unsigned char poll;
	done = FALSE;
   	err = FALSE;
  EA = 0;
	*(FLASH_COMMON_X555) = 0xAA;     // unlock main flash, write 0xAA to addess 0xX555
	*(FLASH_COMMON_XAAA) = 0x55;     // unlock main flash, write 0x55 to addess 0xXAAA
	*(FLASH_COMMON_X555) = 0xA0;     // write 0xA0 command to program
  EA =1;
	*(addr) = dat;                  // write byte to flash   
	
	dat = dat & NVM_DATA_POLL;     // get bit DQ7 of original dat   
	
	do                               // now use dat polling method to verify successful write
    {  

   		poll = *(addr);          // Read the location that was just programmed

		error = poll & NVM_ERROR;   // save timeout error bit at DQ5

		poll = poll & NVM_DATA_POLL;  // get DQ7 of poll byte read from flash  

		if (dat == poll)        // compare DQ7 

			done = TRUE;     // dat byte programmed into flash OK,
                                         // indicate successful exit criteria

		else if (error ==  NVM_ERROR )	 // check for timeout error   
			err = TRUE;      // indicate timeout error occurred

    } while((done == FALSE) && (err == FALSE)); 


	if (err == TRUE)                 // make sure timeout error and dat poll didn't 
                                         // occur simultaneously
	{
		poll = *(addr);          // Read location in flash again

		poll = poll & NVM_DATA_POLL;   // get DQ7 of poll byte read from flash  

		if (dat == poll)        // compare DQ7 

			done = TRUE;     // dat byte programmed into flash OK at the same
                                         // time timout error occured, indicate successful 
		                        // exit criteria

		*(FLASH_COMMON_X555) = 0xF0;  // reset the flash array (short reset instruction) 
//		OSTimeDly(3);        // 不用延时似乎也没问题
    }
   	return(done);         // a successful flash write returns 1, timeout error returns 0
   
}


/***************************************************************
函数名:              flash_erase_bulk
功能描述:   擦除整个主flash所有扇区
参数 :      volatile unsigned char xdata* flash_bulk_erase_address 该地址
            位于任何一个具有片选信号的flash段中
            
注意:       传入的地址应该和flash存储器的分页关系无关,否则,在调用该函数前,应给PSD中页寄存器赋正确的值.
**************************************************************/


unsigned char flash_erase_bulk(
    volatile unsigned char xdata* flash_bulk_erase_address)reentrant
{
   	unsigned char done;
 	unsigned char poll;
 	unsigned char error;
 	unsigned char err;
  WDRST = 0x00;                     //清零看门狗
	done = FALSE;
   	err = FALSE;

	//  Note:  the following constants (FLASH_COMMON_XXXX)
	//     are declared type volatile in the header file 
	//	   so they are not optimized away by the compiler
  EA = 0;
	*(FLASH_COMMON_X555) = 0xAA;		// unlock main flash, write 0xAA to addess 0xX555
	*(FLASH_COMMON_XAAA) = 0x55;		// unlock main flash, write 0x55 to addess 0xXAAA
	*(FLASH_COMMON_X555) = 0x80;		// write 0x80 command to erase entire chip
	*(FLASH_COMMON_X555) = 0xAA;        	// continue unlock sequence
	*(FLASH_COMMON_XAAA) = 0x55;		// continue unlock sequence
	*(FLASH_COMMON_X555) = 0x10;		// write 0x10 command to complete erase command
  EA = 1;
	do		  			// now use dat polling method to verify successful erase
         {  
		poll = *(flash_bulk_erase_address); 	// read flash status from any address
		                                // within the defined flash address space

		error = poll & NVM_ERROR;	// save timeout error bit at DQ5

		poll = poll & NVM_DATA_POLL;	// look at D7   

		if (poll == NVM_DATA_POLL)	// compare DQ7 

			done = TRUE;		// bulk erase OK,
						// indicate successful exit criteria

		else if (error == NVM_ERROR)	// check for timeout error   
			err = TRUE;		// indicate timeout error occurred

          } while((done == FALSE) && (err == FALSE)); 


	if (err == TRUE)			// make sure timeout error and dat poll didn't 
						// occur simultaneously
         {
		poll = *(flash_bulk_erase_address); 	// Read flash status again

		poll = poll & NVM_DATA_POLL;	// get DQ7 of poll byte read from flash  

		if (poll == NVM_DATA_POLL)	// compare DQ7 

			done = TRUE;		// the flash erased OK at the same
						// time timout error occured, indicate successful 

⌨️ 快捷键说明

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