STM32学习笔记:读写内部Flash

一、介绍
首先我们需要了解一个内存映射:
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函数中。大致的流程就是这样。
1.1、内部flash的构成:
stm32f429 的内部 flash 包含主存储器、系统存储器、 otp 区域以及选项字节区域,它们的地址分布及大小如下:
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
感谢原文作者
二、代码拆分介绍(以stm32f105系列为例,如上图表5所示)
2.1 读/写入数据流程
写数据流程
2.1.1、flash 解锁,直接调用#include stm32f10x_flash.h中的void flash_unlock(void)函数,这个函数是官方提供的

人工智能将带来哪些改变?
BrandZ 2019最具价值中国品牌100强”排行榜,阿里巴巴首次荣膺榜首
手机恢复出厂设置,会不会对我们手机造成什么损害或影响?
友善之臂Tiny2451规格
2020年中国移动通信基数达931万个
STM32学习笔记:读写内部Flash
熔喷无纺布瑕疵检测系统的原理及功能
英特尔在产品组合方面面临新的竞争
C语言那些"令人震惊"的结构分析
国产工业机器人与国外差距到底有多大?
京东方称霸笔记电脑面板 柔性显示产品成为未来盈利主力
linux系统如何进行磁盘分区?
政策支持芯片设计 中国芯如何成功
科普互电容式触控技术
华为被迫退出,台积电5nm工艺现在被矿机看上了
采用USB接口解决分组无线网传输速度的受限问题
Intel推出低功耗显示技术,续航延长到了28个小时
索尼智能手机图像传感器市场排名第一
洗涤电机的控制原理图
灌区取水计量方式