STM32 的内部 FLASH

1、STM32 的内部 FLASH 简介

  在 STM32 芯片内部有一个 FLASH 存储器,它主要用于存储代码,我们在电脑上编写好应用程序后,使用下载器把编译后的代码文件烧录到该内部 FLASH 中,由于 FLASH 存储器的内容在掉电后不会丢失,芯片重新上电复位后,内核可从内部 FLASH 中加载代码并运行,见下图:

  除了使用外部的工具(如下载器)读写内部 FLASH 外, STM32 芯片在运行的时候,也能对自身的内部 FLASH 进行读写,因此,若内部 FLASH 存储了应用程序后还有剩余的空间,我们可以把它像外部 SPI-FLASH 那样利用起来,存储一些程序运行时产生的需要掉电保存的数据。

  由于访问内部 FLASH 的速度要比外部的 SPI-FLASH 快得多,所以在紧急状态下常常会使用内部 FLASH 存储关键记录;为了防止应用程序被抄袭,有的应用会禁止读写内部FLASH 中的内容,或者在第一次运行时计算加密信息并记录到某些区域,然后删除自身的部分加密代码,这些应用都涉及到内部 FLASH 的操作。  

2. 内部 FLASH 的构成

  STM32 的内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及大小下表:

区域

名称

块地址

大小

主存储器

块 1

扇区 0

0x0800 0000 - 0x0800 3FFF

16 Kbytes

扇区 1

0x0800 4000 - 0x0800 7FFF

16 Kbytes

扇区 2

0x0800 8000 - 0x0800 BFFF

16 Kbytes

扇区 3

0x0800 C000 - 0x0800 FFFF

16 Kbyte

扇区 4

0x0801 0000 - 0x0801 FFFF

64 Kbytes

扇区 5

0x0802 0000 - 0x0803 FFFF

128 Kbytes

扇区 6

0x0804 0000 - 0x0805 FFFF

128 Kbytes

扇区 7

0x0806 0000 - 0x0807 FFFF

128 Kbytes

扇区 8

0x0808 0000 - 0x0809 FFFF

128 Kbytes

扇区 9

0x080A 0000 - 0x080B FFFF

128 Kbytes

扇区 10

0x080C 0000 - 0x080D FFFF

128 Kbytes

扇区 11

0x080E 0000 - 0x080F FFFF

128 Kbytes

块 2

扇区 12

0x0810 0000 - 0x0810 3FFF

16 Kbytes

扇区 13

0x0810 4000 - 0x0810 7FFF

16 Kbytes

扇区 14

0x0810 8000 - 0x0810 BFFF

16 Kbytes

扇区 15

0x0810 C000 - 0x0810 FFFF

16 Kbyte

扇区 16

0x0811 0000 - 0x0811 FFFF

64 Kbytes

扇区 17

0x0812 0000 - 0x0813 FFFF

128 Kbytes

扇区 18

0x0814 0000 - 0x0815 FFFF

128 Kbytes

扇区 19

0x0816 0000 - 0x0817 FFFF

128 Kbytes

扇区 20

0x0818 0000 - 0x0819 FFFF

128 Kbytes

扇区 21

0x081A 0000 - 0x081B FFFF

128 Kbytes

扇区 22

0x081C 0000 - 0x081D FFFF

128 Kbytes

扇区 23

0x081E 0000 - 0x081F FFFF

128 Kbytes

  系统存储区

0x1FFF 0000 - 0x1FFF 77FF

30 Kbytes

       OTP 区域

0x1FFF 7800 - 0x1FFF 7A0F

528 bytes

选项字节

块 1

0x1FFF C000 - 0x1FFF C00F

16 bytes

块 2

0x1FFE C000 - 0x1FFE C00F

16 bytes

  各个存储区域的说明如下:

  (1)主存储器

    一般我们说 STM32 内部 FLASH 的时候,都是指这个主存储器区域,它是存储用户应用程序的空间,芯片型号说明中的 1M FLASH、 2M FLASH 都是指这个区域的大小。

    主存储器分为两块,共 2MB,每块内分 12 个扇区,其中包含 4 个 16KB扇区、 1 个 64KB 扇区和 7 个 128KB 的扇区。如STM32F429IGT6 型号芯片,它的主存储区域大小为 1MB,所以它只包含有表中的扇区 0-扇区 11。

    与其它 FLASH 一样,在写入数据前,要先按扇区擦除,而有的时候我们希望能以小规格操纵存储单元,所以 STM32 针对 1MB FLASH 的产品还提供了一种双块的存储格式,见下表:

1M 字节单块存储器的扇区分配(默认)

1M 字节双块存储器的扇区分配

DB1M=0

DB1M=1

主存储器

扇区号

扇区大小

主存储器

扇区号

扇区大小

1MB

扇区 0

16 Kbytes

Bank 1

512KB

扇区 0

16 Kbytes

扇区 1

16 Kbytes

扇区 1

16 Kbytes

扇区 2

16 Kbytes

扇区 2

16 Kbytes

扇区 3

16 Kbytes

扇区 3

16 Kbytes

扇区 4

16 Kbytes

扇区 4

64 Kbytes

扇区 5

64 Kbytes

扇区 5

128Kbytes

扇区 6

128Kbytes

扇区 6

128Kbytes

扇区 7

128Kbytes

扇区 7

128Kbytes

扇区 8

128Kbytes

Bank 2

512KB

扇区 12

16 Kbytes

扇区 9

128Kbytes

扇区 13

16 Kbytes

扇区 10

128Kbytes

扇区 14

16 Kbytes

扇区 11

128Kbytes

扇区 15

16 Kbytes

 

 

扇区 16

64 Kbytes

 

 

扇区 17

128Kbytes

 

 

扇区 18

128Kbytes

 

 

扇区 19

128Kbytes

    通过配置 FLASH 选项控制寄存器 FLASH_OPTCR 的 DB1M 位,可以切换这两种格式,切换成双块模式后,扇区 8-11 的空间被转移到扇区 12-19 中,扇区细分了,总容量不变。

    注意如果您使用的是 STM32F40x 系列的芯片, 它没有双块存储格式,也不存在扇区 12-23,仅 STM32F42x/43x 系列产品才支持扇区 12-23。

  (2)系统存储区

    系统存储区是用户不能访问的区域,它在芯片出厂时已经固化了启动代码,它负责实现串口、 USB 以及 CAN 等 ISP 烧录功能。
  (3)OTP 区域

    OTP(One Time Program),指的是只能写入一次的存储区域,容量为 512 字节,写入后数据就无法再更改, OTP 常用于存储应用程序的加密密钥。
  (4)选项字节

    选项字节用于配置 FLASH 的读写保护、电源管理中的 BOR 级别、软件/硬件看门狗等功能,这部分共 32 字节。可以通过修改 FLASH 的选项控制寄存器修改。

3、 对内部 FLASH 的写入过程

  3.1、解锁

  由于内部 FLASH 空间主要存储的是应用程序,是非常关键的数据,为了防止误操作修改了这些内容,芯片复位后默认会结 FLASH 上锁,这个时候不允许设置 FLASH 的控制寄存器,并且不能对修改 FLASH 中的内容。

  所以对 FLASH 写入数据前,需要先给它解锁。解锁的操作步骤如下:

    (1) 往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY1 = 0x45670123
    (2) 再往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY2 = 0xCDEF89AB

  3.2、数据操作位数

  在内部 FLASH 进行擦除及写入操作时,电源电压会影响数据的最大操作位数,该电源电压可通过配置 FLASH_CR 寄存器中的 PSIZE 位改变,见下表。

电压范围

2.7 - 3.6 V
(使用外部 Vpp)

2.7 - 3.6 V

2.1 – 2.7 V

1.8 – 2.1 V

位数

64

32

16

8

PSIZE(1:0)配置

11b

10b

01b

00b


  最大操作位数会影响擦除和写入的速度,其中 64 位宽度的操作除了配置寄存器位外,还需要在 Vpp 引脚外加一个 8-9V 的电压源,且其供电时间不得超过一小时,否则 FLASH可能损坏,所以 64 位宽度的操作一般是在量产时对 FLASH 写入应用程序时才使用,大部分应用场合都是用 32 位的宽度。

  3.3、擦除扇区

  在写入新的数据前,需要先擦除存储区域, STM32 提供了扇区擦除指令和整个FLASH 擦除(批量擦除)的指令,批量擦除指令仅针对主存储区。

  扇区擦除的过程如下:

    (1) 检查 FLASH_SR 寄存器中的“忙碌寄存器位 BSY”,以确认当前未执行任何Flash 操作;
    (2) 在 FLASH_CR 寄存器中,将“激活扇区擦除寄存器位 SER ”置 1,并设置“扇区编号寄存器位 SNB”,选择要擦除的扇区;
    (3) 将 FLASH_CR 寄存器中的“开始擦除寄存器位 STRT ”置 1,开始擦除;
    (4) 等待 BSY 位被清零时,表示擦除完成。

  3.4. 写入数据

  擦除完毕后即可写入数据,写入数据的过程并不是仅仅使用指针向地址赋值,赋值前还还需要配置一系列的寄存器,步骤如下:

    (1) 检查 FLASH_SR 中的 BSY 位,以确认当前未执行任何其它的内部 Flash 操作;
    (2) 将 FLASH_CR 寄存器中的 “激活编程寄存器位 PG” 置 1;
    (3) 针对所需存储器地址(主存储器块或 OTP 区域内)执行数据写入操作;
    (4) 等待 BSY 位被清零时,表示写入完成。

 

posted @ 2020-10-11 16:06  孤情剑客  阅读(1364)  评论(0编辑  收藏  举报