flash 模拟eeprom

STM32 的页擦除顺序为:

检查 FLASH_CR LOCK 是否解锁,如果没有则先解锁

检查 FLASH_SR 寄存器的 BSY 位,以确认没有其他正在进行的闪存操作

设置 FLASH_CR 寄存器的 PER 位为’1

FLASH_AR 寄存器选择要擦除的页

设置 FLASH_CR 寄存器的 STRT 位为’1

等待 BSY 位变为’0

读出被擦除的页并做验证

void	Up_E2Data(u32 e2address) 		//更新flash参数数据
{
	u8  i=0;
	if(Flag_UpdataE2)		//接收到新的参数
	{
		Flag_UpdataE2=0;
	 	if(FLASH->CR&(1<<7))			//解锁
		{
			FLASH->KEYR=0x45670123;
			FLASH->KEYR=0xCDEF89AB;
		}
		FLASH->CR|=1<<1;			   //擦除指定页数据,为新的数据作准备
		FLASH->AR=e2address;
		FLASH->CR|=1<<6;
		while(FLASH->SR&(1<<0));
	    FLASH->CR&=~(1<<1);
		FLASH->CR|=1<<0;
		while(FLASH->SR&(1<<0));
						  //写如新的数据
		while(i<2)				  //写如新的数据
		{
			while(FLASH->SR&(1<<0));
			*(volatile u16 *)e2address=Parameter[i];
			e2address+=2;
			i++;	
		}
		FLASH->CR&=~(1<<0);
		FLASH->CR|=1<<7;			//加锁,防止误操作
	}
}

STMFLASH_ReadHalfWor()函数的实现原理我们在前面已经详细讲解了。下面我们重点介

绍一下 STMFLASH_Write 函数,该函数用于在 STM32 的指定地址写入指定长度的数据,该函

数的实现基本类似第 29 章的 W25QXX_Write 函数,不过该函数对写入地址是有要求的,必须

保证以下两点:

1, 该地址必须是用户代码区以外的地址。

2, 该地址必须是 2 的倍数。

条件 1 比较好理解,如果把用户代码给卡擦了,可想而知你运行的程序可能就被废了,从

而很可能出现死机的情况。条件 2 则是 STM32 FLASH 的要求,每次必须写入 16 位,如果你写

的地址不是 2 的倍数,那么写入的数据,可能就不是写在你要写的地址了。

另外,该函数的 STMFLASH_BUF 数组,也是根据所用 STM32 FLASH 容量来确定的,

战舰 STM32 开发板的 FLASH 512K 字节,所以 STM_SECTOR_SIZE 的值为 512


//要写入到STM32 FLASH的字符串数组
const u8 TEXT_Buffer[]={"STM32F103 FLASH TEST"};
#define SIZE sizeof(TEXT_Buffer)        //数组长度
#define FLASH_SAVE_ADDR  0X08070000        //设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000)


FLASH的大小计算

在Keil MDK编译器编译后,信息栏都会显示编译情况,这其中就包含了FLASH跟SRAM的信息。如下图所示,

一方面它也说明程序在编译后会把相同性质的数据(比如变量,其中包括局部变量和全局变量。当然其中也包括代码)归放到同一域里面。

/*********************************************************************************************/

查看FLASH跟SRAM的占用空间问题主要看下面的语句。

Program Size: Code=29864 RO-data=123592 RW-data=60 ZI-data=3900

/*********************************************************************************************/

其中 要着重注意的是Code、RO-data、RW-data、ZI-data所代表的意思

Code:即代码域,它指的是编译器生成的机器码,它被存储在ROM区。也表示程序所占用 FLASH 的大小( FLASH)。


RO-data:即 Read Only-data,只读数据区, 它被存储在ROM区。表示程序定义的常量,如 const 类型( FLASH)。


RW-data:即 Read Write-data,可读可写数据区,它被存储在ROM区, 表示已被初始化的全局变量(这里的初始值是指非0值)( SRAM)

ZI-data:即 Zero Initialie data, 0初始化数据,它被存储在RAM区,表示未被初始化的全局变量(SRAM)

注:在查阅野火的<<零死角玩转STM32>>电子书的 “程序的组成、存储于运行” 这个章节时,发现还有一个区会被忽略,也许在查看了上面几个存储区域后,会发现在 RW-data 和 ZI-data 这两个区域都存储在RAM中,存储的都是全局变量,那么局部变量存储在哪里呢?答案是:存储在ZI-data 的栈空间(Stack)及堆空间(Heap)。

ZI-data 的栈空间(Stack)及堆空间(Heap):在 C 语言中,函数内部定义的局部变量属于栈空间,进入函数的时候从向栈空间申请内存给局部变量,退出时释放局部变量,归还内存空间。而使用 malloc 动态分配的变量属于堆空间。在程序中的栈空间和堆空间都是属于 ZI-data 区域的,这些空间都会被初始值化为 0值。编译器给出的 ZI-data占用的空间值中包含了堆栈的大小(经实际测
试,若程序中完全没有使用 malloc 动态申请堆空间,编译器会优化,不把堆空间计算在内)

/*********************************************************************************************/

那么FLASH和SRAM占用情况的计算方式如下所示:

flash = Code + RO-data + RW-data = 29864 + 123592 + 60 = 153516 bytes

sram = RW-data + ZI-data = 60+ 3900= 3960bytes

还有一个要特别注意的是程序的大小不是.hex文件的大小,而是编译结果的Code+RO-data。

在程序初始化的时候,RW-data会从FLASH中拷贝到RAM中。
————————————————
版权声明:本文为CSDN博主「JohnnyTim」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/johnnytim/article/details/75384412

程序编译完成 

对STM32容量选型或者 计算FLASH 充当EEPROM起始地址时会用到此参数。

按照下面截图  程序空间 = (16700+732+4580)/1024 = 21.5K

但需要注意的是  程序的起始地址 为0x08000000,所以 flash的 起始地址 必须是 0x08000000 + 0x55FC(22012的16进制)  = 0x080055FC之后

 

其余的空间都可以作为 其他功能使用。

程序的调试的小方法,

如果判断程序出问题了,在某一块,可以添加 

程序块

while(1); //将程序停留在此处  检测运行到此处是否出了问题,可一步一步的排除

发布了112 篇原创文章 · 获赞 120 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/qq_36958104/article/details/102497422