stm32的flash
最近总感觉改程序工程的时候心慌慌的,
原因之一是版本的问题,因为调来调去,又加上中间会夹杂一些其他工作,总是导致忘了哪个版本了.
第二个就是对程序中的不熟悉.对单片机内部存储也不是很熟悉.
单片机里面总共有两种存储结构.
1.flash
2.RAM
Flash中的内容一般用来存储代码和一些定义为const的数据,断电不丢失,
RAM可以理解为内存,用来存储代码运行时的数据,变量等等。掉电数据丢失。
至于其他 SRAM , nada flash, ROM ,RAM ,DRAM ,都是制作工艺的不同.
下面比较详细:
https://blog.csdn.net/HLYL7923/article/details/80496148?utm_source=blogxgwz7
(一)ROM(Read Only Memory)
只读存储器,在单片机运行时,只能从中读取数据,不能向里面写数据。特点是掉电不丢失数据,在单片机中主要用来存储代码和常量等内容。
(二)RAM(Random Access Memory)
随机存储器,可读可写,特点是掉电会丢失数据。RAM又分为SRAM(Static RAM)和DRAM(Dynamic RAM),SRAM是读写速度非常快的存储设备,但价格昂贵。DRAM比ROM速度快,但是比SRAM速度慢,价格低于SRAM,计算机内存使用的就是DRAM。
(三)FLASH
闪存,这种存储器结合了ROM和RAM的优点,既可以保证掉电不丢失又可以有很高的读写速度。可以用来存储一些用户不希望掉电丢失的一些数据。
在以往,单片机内部包含ROM和RAM,ROM的硬件实现主要EEPROM,但近年来Flash逐渐取代了他的位置,成为ROM实现的主要硬件。例如,51单片机有4KB的ROM和256B的RAM,这里的ROM实现为EEPROM,而STM31F103有64KB的Flash和20K的SRAM,这里Flash的一部分作为ROM来使用。
关于stm32的flash
结合STM32f2xx_datasheet,根据工程生成的map,总结如下:
FLASH / ROM(ro): 0x0000 0000 ~ 0x000F FFFF : intvec(startup_stm32f2xx.s)。
0x0800 0000 ~ 0x080F FFFF :函数(包含静态函数)、带有const修饰的全局变量 。
SRAM(rw): 0x2000 0000 ~ 0x2001 FFFF : 全局变量、CSTACK(栈:局部变量)、HEAP(堆:使用到malloc时 才用)、静态变量
便已完成后
Code是代码占用的空间;
RO-data是 Read Only 只读常量的大小,如const型;
RW-data是(Read Write) 初始化了的可读写变量的大小;
ZI-data是(Zero Initialize) 没有初始化的可读写变量的大小。ZI-data不会被算做代码里因为不会被初始化;
简单的说就是在烧写的时候是FLASH中的被占用的空间为:Code + RO Data + RW Data
程序运行的时候,芯片内部RAM使用的空间为: RW Data + ZI Data
我的代码中,Flash占用空间code =24586字节+RO-data=626字节,RAM占用空间为RW-data=220字节+ZI-data=8308字节
下面介绍如何压缩RAM空间,主要是一些全局变量的定义,大家可以打开自己工程文件夹下面的OBJ文件夹,找到一个后缀为.MAP的文件,可以找到
如图 可以看到不同变量占用RAM空间的大小及地址,可以根据这个删除不必要的变量或空间,可以节省RAM空间,选择小RAM的芯片,降低成本
仿真memory
再到Keil打开memory窗口,输入地址
ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写,RAM是Random Access Memory的缩写。ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是在掉电之后就丢失数据,典型的RAM就是计算机的内存。
RAM有两大类,一种称为静态RAM(Static RAM/SRAM),SRAM速度非常快,是目前读写最快的存储设备了,但是它也非常昂贵,所以只在要求很苛刻的地方使用,譬如CPU的一级缓冲,二级缓冲。另一种称为动态。
RAM(Dynamic RAM/DRAM),DRAM保留数据的时间很短,速度也比SRAM慢,不过它还是比任何的ROM都要快,但从价格上来说DRAM相比SRAM要便宜很多,计算机内存就是DRAM的。
DRAM分为很多种,常见的主要有FPRAM/FastPage、EDORAM、SDRAM、DDR RAM、RDRAM、SGRAM以及WRAM等,这里介绍其中的一种DDR RAM。
DDR RAM(Date-Rate RAM)也称作DDR
SDRAM,这种改进型的RAM和SDRAM是基本一样的,不同之处在于它可以在一个时钟读写两次数据,这样就使得数据传输速度加倍了。这是目前电脑中用得最多的内存,而且它有着成本优势,事实上击败了Intel的另外一种内存标准-Rambus
DRAM。在很多高端的显卡上,也配备了高速DDR RAM来提高带宽,这可以大幅度提高3D加速卡的像素渲染能力。
FLASH存储器又称闪存,它结合了ROM和RAM的长处,不仅具备电子可擦除可编程(EEPROM)的性能,还不会断电丢失数据同时可以快速读取数据(NVRAM的优势),U盘和MP3里用的就是这种存储器。在过去的20年里,嵌入式系统一直使用ROM(EPROM)作为它们的存储设备,然而近年来Flash全面代替了ROM(EPROM)在嵌入式系统中的地位,用作存储Bootloader以及操作系统或者程序代码或者直接当硬盘使用(U盘)。
目前Flash主要有两种NOR Flash和NADN Flash。
NOR Flash的读取和我们常见的SDRAM的读取是一样,用户可以直接运行装载在NOR FLASH里面的代码,这样可以减少SRAM的容量从而节约了成本。
NAND
Flash没有采取内存的随机读取技术,它的读取是以一次读取一块的形式来进行的,通常是一次读取512个字节,采用这种技术的Flash比较廉价。用户不能直接运行NAND
Flash上的代码,因此好多使用NAND Flash的开发板除了使用NAND Flah以外,还作上了一块小的NOR Flash来运行启动代码。
一般小容量的用NOR Flash,因为其读取速度快,多用来存储操作系统等重要信息,而大容量的用NAND FLASH,最常见的NAND
FLASH应用是嵌入式系统采用的DOC(Disk On Chip)和我们通常用的"闪盘",可以在线擦除。目前市面上的FLASH
主要来自Intel,AMD,Fujitsu和Toshiba,而生产NAND Flash的主要厂家有Samsung和Toshiba。
http://news.eeworld.com.cn/mcu/2018/ic-news071040225.html
1.stm32内部flash写操作只能是两个byte写入,不能一个byte一个byte的写
2.写之前需要擦除,擦除后数据均为FF
3.内部flash为512kb为大容量,小于512为小容量。在stm32的stm32f10x_flash.c里面FLASH_Status FLASH_ErasePage擦除页函数有区别擦2k还是擦1k,大容量擦2k,小容量擦1k
4.读可以只读一个字节,例如:*(uint8_t*)(Address)
5.我的代码中,擦除和写过程没有加延时函数,因为库函数里面已经有一个确保操作完成的函数。
6.擦写前先调用解锁函数。
https://www.cnblogs.com/pertor/p/9484663.html
从下面这个图,可以看出大小端模式,stm32是小端模式:
stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片flash大小不同。
RAM起始地址是0x2000 0000,结束地址是0x2000 0000加上芯片的RAM大小。不同的芯片RAM也不同。
Flash中的内容一般用来存储代码和一些定义为const的数据,断电不丢失,
RAM可以理解为内存,用来存储代码运行时的数据,变量等等。掉电数据丢失。
STM32将外设等都映射为地址的形式,对地址的操作就是对外设的操作。
stm32的外设地址从0x4000 0000开始,可以看到在库文件中,是通过基于0x4000 0000地址的偏移量来操作寄存器以及外设的。
一般情况下,程序文件是从 0x0800 0000 地址写入,这个是STM32开始执行的地方,0x0800 0004是STM32的中断向量表的起始地址。
在使用keil进行编写程序时,其编程地址的设置一般是这样的:
程序的写入地址从0x08000000(数好零的个数)开始的,其大小为0x80000也就是512K的空间,换句话说就是告诉编译器flash的空间是从0x08000000-0x08080000,RAM的地址从0x20000000开始,大小为0x10000也就是64K的RAM。这与STM32的内存地址映射关系是对应的。
M3复位后,从0x08000004取出复位中断的地址,并且跳转到复位中断程序,中断执行完之后会跳到我们的main函数,main函数里边一般是一个死循环,进去后就不会再退出,当有中断发生的时候,M3将PC指针强制跳转回中断向量表,然后根据中断源进入对应的中断函数,执行完中断函数之后,再次返回main函数中。大致的流程就是这样。
stm32的flash部分:
STM32F429 的内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及大小如下:
(如果想要保存一些数据,比如,mp3 上电之后会接着播放上次关机时的歌曲,这样就需要保存歌名到flash中)
STM32F103的中容量内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及大小如下:
注意STM32F105VC的是有64K或128页x2K=256k字节的内置闪存存储器,用于存放程序和数据。
- 主存储器:一般我们说 STM32 内部 FLASH 的时候,都是指这个主存储器区域它是存储用户应用程序的空间,芯片型号说明中的 1M FLASH、 2M FLASH 都是指这个区域的大小。与其它 FLASH 一样,在写入数据前,要先按扇区擦除,
- 系统存储区:系统存储区是用户不能访问的区域,它在芯片出厂时已经固化了启动代码,它负责实现串口、 USB 以及 CAN 等 ISP 烧录功能。
- OTP 区域:OTP(One Time Program),指的是只能写入一次的存储区域,容量为 512 字节,写入后数据就无法再更改, OTP 常用于存储应用程序的加密密钥。
- 选项字节:选项字节用于配置 FLASH 的读写保护、电源管理中的 BOR 级别、软件/硬件看门狗等功能,这部分共 32 字节。可以通过修改 FLASH 的选项控制寄存器修改。
1.2、对内部Flash的写入过程:
1. 解锁 (固定的KEY值)
(1) 往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY1 = 0x45670123
(2) 再往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY2 = 0xCDEF89AB
2. 数据操作位数
最大操作位数会影响擦除和写入的速度,其中
64 位宽度的操作除了配置寄存器位外,还需要在 Vpp 引脚外加一个 8-9V 的电压源,且其供电间不得超过一小时,否则
FLASH可能损坏,所以 64 位宽度的操作一般是在量产时对 FLASH 写入应用程序时才使用,大部分应用场合都是用 32 位的宽度。
3. 擦除扇区
在写入新的数据前,需要先擦除存储区域, STM32 提供了扇区擦除指令和整个FLASH 擦除(批量擦除)的指令,批量擦除指令仅针对主存储区。
扇区擦除的过程如下:
(1) 检查 FLASH_SR 寄存器中的“忙碌寄存器位 BSY”,以确认当前未执行任何
Flash 操作;
(2) 在 FLASH_CR 寄存器中,将“激活扇区擦除寄存器位 SER ”置 1,并设置“扇
区编号寄存器位 SNB”,选择要擦除的扇区;
(3) 将 FLASH_CR 寄存器中的“开始擦除寄存器位 STRT ”置 1,开始擦除;
(4) 等待 BSY 位被清零时,表示擦除完成。
4. 写入数据
擦除完毕后即可写入数据,写入数据的过程并不是仅仅使用指针向地址赋值,赋值前还还需要配置一系列的寄存器,步骤如下:
(1) 检查 FLASH_SR 中的 BSY 位,以确认当前未执行任何其它的内部 Flash 操作;
(2) 将 FLASH_CR 寄存器中的 “激活编程寄存器位 PG” 置 1;
(3) 针对所需存储器地址(主存储器块或 OTP 区域内)执行数据写入操作;
(4) 等待 BSY 位被清零时,表示写入完成。
1.3、查看工程内存的分布:
由于内部 FLASH 本身存储有程序数据,若不是有意删除某段程序代码,一般不应修改程序空间的内容,所以在使用内部 FLASH
存储其它数据前需要了解哪一些空间已经写入了程序代码,存储了程序代码的扇区都不应作任何修改。通过查询应用程序编译时产生的“
*.map”后缀文件,
打开 map 文件后,查看文件最后部分的区域,可以看到一段以“ Memory Map of the
image”开头的记录(若找不到可用查找功能定位),
【注】ROM加载空间
这一段是某工程的 ROM 存储器分布映像,在 STM32 芯片中, ROM 区域的内容就是 指存储到内部 FLASH 的代码。
在上面
map 文件的描述中,我们了解到加载及执行空间的基地址(Base)都是0x08000000,它正好是 STM32 内部 FLASH
的首地址,即 STM32 的程序存储空间就直接是执行空间;它们的大小(Size)分别为 0x00000b50 及
0x00000b3c,执行空间的 ROM 比较小的原因就是因为部分 RW-data 类型的变量被拷贝到 RAM
空间了;它们的最大空间(Max)均为 0x00100000,即 1M 字节,它指的是内部 FLASH 的最大空间。
计算程序占用的空间时,需要使用加载区域的大小进行计算,本例子中应用程序使用
的内部 FLASH 是从 0x08000000 至(0x08000000+0x00000b50)地址的空间区域。
所以从扇区 1(地址 0x08004000)后的存储空间都可以作其它用途,使用这些存储空间时不会篡改应用程序空间的数据。
具体可参考原子的例程:实验四十一:FLASH 模拟 EEPROM 实验
文章引用地址:https://blog.csdn.net/qq_33559992/article/details/77676716
感谢原文作者