关于Flash的学习(二,操作Flash时,Flash延长寿命的写法)

承蒙项目和同事的要求,因Flash擦除、写入太过于频繁,所以需要更换Flash地址写数据。

背景简介:嵌入式开发,需要关机保存数据,C语言写。用512K Byte Flash。

看了一篇网上文章后,借鉴前人的做法,写了以下代码,本人是运用前人原理中的一种(一部分),所以来说,应该看起来更加简单明了。前人源链接如下https://blog.csdn.net/baidu_37541954/article/details/64122655

代码简介:用容量512k Byte的Flash,在0x20000 Byte起始的地址,在0x20000~0x3FFFF之间(总共128k Byte)进行循环存储数据。因Flash每次擦除最小单位为4K Byte的扇区,所以在0x20000~0x3FFFF之间一个周期总共能存储32次。

存储数据原理简介:每个扇区的第一个32位数据,存储数据有效标志位(比如我写入1),第二个32位,保存我想要存储的数据。循环读取32个扇区的第一个32位,查询时如果不是0xFFFFFFFF,则认为此段扇区已经写入,则进行擦除此段,进而在下一段扇区写入数据。

读取数据原理简介:循环读取32个扇区的第一个32位,查询时如果不是0xFFFFFFFF,则认为此段扇区中是有效数据,进行读取。(当然读取时防止出错,加上出错时返回默认值)

本人写尚处于学习进步阶段,写此博客记录所学。且尚有很多不足,往多多指教。欢迎添加QQ进一步学习探讨1742037504.

#define POWEROFF_SAVE_ADDR			0x10020000
#define POWEROFF_SAVE_LENGTH		0x20000

void flashOperation( UINT32 erushAddress , UINT32 erushNumber, UINT32 * writeData)
{
	//保存相关参数
	UINT32 argv[5];
	UINT32 saveData[2];			//保存数据仅2个
	saveData[0] = 1;			//第一个数据位有效位标志
	saveData[1] = * writeData;	//第二个数据位存储的数据
	argv[0] = 0;
	argv[1] = 0;
	argv[2] = erushAddress&0x0FFFFFFF;
	argv[3] = erushNumber*4;	//Erasure POWEROFF_SAVE_NUMBER Bit32 data,so Mul 4.
	FTSPI020_xip_port_sel(0);													//cmd port
	SpiFlashErase(4, argv);			//如果擦除失败,重新进行擦除
	
	erushAddress += 4096;//擦除上一个扇区,给下一个扇区写入。相隔一个扇区(4KByte)
	if( erushAddress >= (POWEROFF_SAVE_ADDR + POWEROFF_SAVE_LENGTH))
	{//如果保存数据地址已经到末尾,则循环至开头。进行写操作
		erushAddress = POWEROFF_SAVE_ADDR;
	}
	argv[0] = 0;
	argv[1] = 0;
	argv[2] = erushAddress&0x0FFFFFFF;
	argv[3] = erushNumber*4;	//Save POWEROFF_SAVE_NUMBER Bit32 data,so Mul 4.
	argv[4] = (UINT32)&saveData[0];
	SpiFlashWrite(5, argv);
	FTSPI020_xip_port_sel(1);													//cmd port
}


UINT8 SaveEffModeProcess(UINT32* address, UINT32* data, UINT32 saveDataNumber)//比如,0x10020000,32,data
{
	UINT32 availFlag;
	UINT8 i;
	UINT8 saveCheckLoopNum = (POWEROFF_SAVE_LENGTH/4096);	//长度除以4KByte
	UINT32 curDataNumber = (saveDataNumber + 1);			//因还有第一个标志数据,所以长度+1;
	for( i = 0; i < saveCheckLoopNum ; i++ )
	{//循环检查看哪个地址有保存过数据
		availFlag = *address;
		if( availFlag != 0xFFFFFFFF )
		{//找到已经写过的地址,进行擦除当前数据,写入保存数据操作
			flashOperation((UINT32)address , curDataNumber, data);
			return 1;
		}
		address += (4096>>2);//因此数据为32位,所以所加数据要除以4
	}
	//在存储范围内未检查到有存储数据记录,则进行对起始空间进行保存操作
	address = (UINT32*)POWEROFF_SAVE_ADDR;
	flashOperation((UINT32)address , curDataNumber, data);
	return 0;
}

UINT8 ReadEffModeProcess(UINT32* address )
{
	UINT32 availFlag;
	UINT8 readEffMode;
	UINT8 i;
	UINT8 saveCheckLoopNum = (POWEROFF_SAVE_LENGTH/4096);	//长度除以4KByte
	for( i = 0; i < saveCheckLoopNum ; i++ )
	{//循环检查看哪个地址有保存过数据
		availFlag = *address;
		if( availFlag != 0xFFFFFFFF )
		{//找到已经写过的地址,读取数据
			readEffMode = *(address+1);//因第一个是存储数据标志位,第二个数据是存储的有效值
			if( readEffMode > 2)//防止读到的数据出错,出错时置为默认值
			{
				readEffMode = 0;//这里我默认值为0
			}
			return readEffMode;
		}
		address += (4096>>2);//因此数据为32位,所以所加数据要除以4
	}
	//在存储范围内未检查到有存储数据记录,则返回默认值
	readEffMode = 0;			//这里我默认值为0	
	return readEffMode;
}

//调用读取函数入口
	eqModeNum = ReadEffModeProcess((UINT32*)POWEROFF_SAVE_ADDR);

//调用写入入口
	address = (UINT32*) POWEROFF_SAVE_ADDR;
	SaveData = (UINT32)eqModeNum;
	saveDataNumber = 1;
	SaveEffModeProcess(address, (UINT32*)&SaveData, saveDataNumber);

本人新建了个QQ群,如想进一步沟通可添加:947187213。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值