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); //将程序停留在此处 检测运行到此处是否出了问题,可一步一步的排除