找回密码
 注册
关于网站域名变更的通知
查看: 1461|回复: 1
打印 上一主题 下一主题

STM32读写内部Flash

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-11-7 17:14 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
本帖最后由 行者~ABC 于 2019-11-7 17:16 编辑 * O& }$ ?6 T- w

- \* d* N* J, T9 VSTM32学习笔记:读写内部Flash(附代码)! k0 C% ~$ P. ~8 @& w0 j
一、介绍
首先我们需要了解一个内存映射:
stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片flash大小不同。
RAM起始地址是0x2000 0000,结束地址是0x2000 0000加上芯片的RAM大小。不同的芯片RAM也不同。
Flash中的内容一般用来存储代码和一些定义为const的数据,断电不丢失, % h# U* v; x, h0 i9 [
RAM可以理解为内存,用来存储代码运行时的数据,变量等等。掉电数据丢失。
STM32将外设等都映射为地址的形式,对地址的操作就是对外设的操作。 5 V  i$ w" j2 u
stm32的外设地址从0x4000 0000开始,可以看到在库文件中,是通过基于0x4000 0000地址的偏移量来操作寄存器以及外设的。
一般情况下,程序文件是从 0x0800 0000 地址写入,这个是STM32开始执行的地方,0x0800 0004是STM32的中断向量表的起始地址。 0 `- s) S: n0 h
在使用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 区域以及选项字节区域,它们的地址分布及大小如下:
; E  @  ~+ J+ |6 G, l
注意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 的选项控制寄存器修改。
    ' k9 T. g7 B- d0 h+ ]
1.2、对内部Flash的写入过程:
1. 解锁 (固定的KEY值)- n- [( N) G9 N, ^6 s
(1) 往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY1 = 0x45670123
3 K1 Y  T) t" ]% D4 u(2) 再往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY2 = 0xCDEF89AB " `) x/ b( J, B, t. @3 l; e
2. 数据操作位数 0 e( P, X5 c: N2 y
最大操作位数会影响擦除和写入的速度,其中 64 位宽度的操作除了配置寄存器位外,还需要在 Vpp 引脚外加一个 8-9V 的电压源,且其供电间不得超过一小时,否则 FLASH可能损坏,所以 64 位宽度的操作一般是在量产时对 FLASH 写入应用程序时才使用,大部分应用场合都是用 32 位的宽度。
% m+ [/ l5 t$ k- o3. 擦除扇区 3 Z+ N0 `8 a9 L! s1 W
在写入新的数据前,需要先擦除存储区域, STM32 提供了扇区擦除指令和整个FLASH 擦除(批量擦除)的指令,批量擦除指令仅针对主存储区。 + L$ g' d5 q2 Z4 J, G# K
扇区擦除的过程如下:
' a1 I( v5 W+ T) G; v, H% `' u(1) 检查 FLASH_SR 寄存器中的“忙碌寄存器位 BSY”,以确认当前未执行任何
5 @) t' l9 u% E% @8 i% q% [Flash 操作; 7 l+ s, K$ @8 R
(2) 在 FLASH_CR 寄存器中,将“激活扇区擦除寄存器位 SER ”置 1,并设置“扇 ' Z! Q  y8 a" M, w' D* C1 _$ j
区编号寄存器位 SNB”,选择要擦除的扇区;
, X7 K. C) t, C4 X* F, T7 [(3) 将 FLASH_CR 寄存器中的“开始擦除寄存器位 STRT ”置 1,开始擦除;
  U7 W7 y* ]' J# |) ?(4) 等待 BSY 位被清零时,表示擦除完成。
( O8 e# k2 z' }% h3 _; ~# g4. 写入数据
3 a' T& z+ G( }) d8 Z擦除完毕后即可写入数据,写入数据的过程并不是仅仅使用指针向地址赋值,赋值前还还需要配置一系列的寄存器,步骤如下: ) N8 P' Y7 \2 I6 E$ p; M- N
(1) 检查 FLASH_SR 中的 BSY 位,以确认当前未执行任何其它的内部 Flash 操作;
3 Y$ S. x! m" w  A5 a7 t  V3 ^(2) 将 FLASH_CR 寄存器中的 “激活编程寄存器位 PG” 置 1; # }+ n" h$ _0 Z* Y$ T/ j, `$ m. ]7 \
(3) 针对所需存储器地址(主存储器块或 OTP 区域内)执行数据写入操作;
/ \9 a( K6 _* H, k; q7 G(4) 等待 BSY 位被清零时,表示写入完成。
1.3、查看工程内存的分布:
由于内部 FLASH 本身存储有程序数据,若不是有意删除某段程序代码,一般不应修改程序空间的内容,所以在使用内部 FLASH 存储其它数据前需要了解哪一些空间已经写入了程序代码,存储了程序代码的扇区都不应作任何修改。通过查询应用程序编译时产生的“ *.map”后缀文件, 7 r( g. `' L. N( l! E1 i  y& N
打开 map 文件后,查看文件最后部分的区域,可以看到一段以“ Memory Map of the , P3 S. ?- V. @3 v
image”开头的记录(若找不到可用查找功能定位),
【注】ROM加载空间
这一段是某工程的 ROM 存储器分布映像,在 STM32 芯片中, ROM 区域的内容就是 指存储到内部 FLASH 的代码。 7 G; X8 |7 a; @' c
在上面 map 文件的描述中,我们了解到加载及执行空间的基地址(Base)都是0x08000000,它正好是 STM32 内部 FLASH 的首地址,即 STM32 的程序存储空间就直接是执行空间;它们的大小(Size)分别为 0x00000b50 及 0x00000b3c,执行空间的 ROM 比较小的原因就是因为部分 RW-data 类型的变量被拷贝到 RAM 空间了;它们的最大空间(Max)均为 0x00100000,即 1M 字节,它指的是内部 FLASH 的最大空间。
计算程序占用的空间时,需要使用加载区域的大小进行计算,本例子中应用程序使用
& ^% o. q! x; X7 c! A9 E6 U的内部 FLASH 是从 0x08000000 至(0x08000000+0x00000b50)地址的空间区域。
& X* T! B1 }5 `所以从扇区 1(地址 0x08004000)后的存储空间都可以作其它用途,使用这些存储空间时不会篡改应用程序空间的数据。 5 ~7 H; y5 ^' a7 Z* Z) b/ T
具体可参考原子的例程:实验四十一:FLASH 模拟 EEPROM 实验

5 B# o( q- {0 y$ P
二、代码拆分介绍(以STM32F105系列为例,如上图表5所示)
2.1 读/写入数据流程
                        
                                      写数据流程
2.1.1、Flash 解锁,直接调用#include "stm32f10x_flash.h"中的void FLASH_Unlock(void)函数,这个函数是官方提供的,其内部代码如下:
# B& _+ Q0 n! x, p' b2 _: _% n. _6 n; T- X
! k3 f0 E  |3 Y0 _2 ~
: A. z7 x0 a+ @- u+ B3 ]9 p

该用户从未签到

2#
发表于 2019-11-7 17:21 | 只看该作者
不错,很详细
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-22 07:01 , Processed in 0.078125 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表