STM32单片机FLASH闪存详解

发布于:2024-06-26 ⋅ 阅读:(33) ⋅ 点赞:(0)

文章目录

1. FLASH简介

2. 闪存模块组织

3. FLASH基本结构

4. FLASH解锁

3. 使用指针访问储存器

4. 程序储存器编程(写入)

5. 程序储存器页擦除

6. 程序储存器全擦除

7. 选项字节

8. 选项字节编程

9. 选项字节擦除

10. 器件电子签名

11. 代码示例


1. FLASH简介

STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程。

读写FLASH的用途:

  • 利用程序存储器的剩余空间来保存掉电不丢失的用户数据

通过在程序中编程(IAP),实现程序的自我更新

  • 在线编程(In-Circuit Programming – ICP)用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载程序。
  • 在程序中编程(In-Application Programming – IAP)可以使用微控制器支持的任一种通信接口下载程序。

2. 闪存模块组织

C8T6的主存储器从1到63,一共64页

主存储器(程序存储器)

功能和结构:

  • 用于存放程序代码,是存储器中最主要和容量最大的一部分。
  • 进行了分页管理,擦除和写保护都是以页为单位进行的。

操作特点:

  • 写入前必须进行擦除操作,且擦除必须以最小单位进行。
  • 擦除后数据位全变为1,数据只能从1写为0,不能从0写为1。
  • 每次擦除和写入操作后,都需要等待忙(等待操作完成)。

信息块:

  • 启动程序代码(系统存储器):存放原厂写入的Bootloader,用于串口下载。
  • 用户选择字节(选项字节):存放一些独立的参数。
  • 闪存存储器接口存储器(闪存管理员):类似GPIO等的外设,地址为0x40000000,不属于闪存,存储介质是SRAM,用于控制擦除和编程过程。

页的起始地址:

  • 程序存储器的起始地址为0x08000000,之后是一个字节一个地址,依次线性分配。
  • 每页起始地址的规律是地址以000、400、800、C00结尾,这些地址一定是页的起始地址。

3. FLASH基本结构

4. FLASH解锁

FPEC共有三个键值:

  • RDPRT键 = 0x000000A5
  • KEY1 = 0x45670123
  • KEY2 = 0xCDEF89AB

解锁:

  • 复位后,FPEC被保护,不能写入FLASH_CR
  • 在FLASH_KEYR先写入KEY1,再写入KEY2,解锁
  • 错误的操作序列会在下次复位前锁死FPEC和FLASH_CR

解锁方式:通过在键寄存器写入指定的键值

FPEC共有三个键值:

  • RDPRT键:用于解除读保护的密钥。
  • KEY1和KEY2:解锁时需要的两个键值,这两个键值可以随便定义。

默认状态:复位后的FLASH默认是锁定的。

解锁过程:

  • 写入KEY1键值到KEYR寄存器,然后再写入KEY2键值,只有按顺序写入这两个键值,才能成功解锁。

注意事项:

  • 如果程序尝试错误操作解锁,一旦没有按顺序写入KEY1和KEY2,整个模块将被完全锁死,除非复位。

加锁:设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR

加锁方式:控制寄存器中LOCK位置1,用于锁定模块。

3. 使用指针访问储存器

使用指针读指定地址下的存储器:

uint16_t Data = *((__IO uint16_t *)(0x08000000));

使用指针写指定地址下的存储器:

*((__IO uint16_t *)(0x08000000)) = 0x1234;

其中:

#define    __IO    volatile

因为STM32内部的存储器是直接挂在总线上的,直接使用C语言的指针,来访问即可

使用指针写指定地址下的存储器

1. 先确定地址,再强制转换为指针,最后通过指针取内容:

  • 这将完成指定地址的写操作。

2. 直接对指定地址赋值:

*(__IO uint16_t *)(0x08000000) = 0x1234;
  • 将值 0x1234 写入到指定地址 0x08000000

写操作注意事项:

  • 写入的数据一般是存储在闪存中的,闪存是只读的,不能轻易更改。因此,需要先解锁并进行存储器编程设置。

如果指定的地址是 SRAM 的地址(例如 0x20000000),可以直接写入:

  • 因为 SRAM 在程序运行时是可读可写的。

通过上述步骤,可以使用指针完成对指定地址存储器的写操作。注意,针对不同存储器类型(如闪存和 SRAM),写操作的步骤和要求可能有所不同。

4. 程序储存器编程(写入)

写入流程

  1. 检查擦除状态

    • 在 STM32 的闪存写入之前,会检查指定地址是否已经擦除。如果地址未擦除且尝试写入非全零数据,STM32 将不执行写入操作。只有在写入全零数据时,即使地址未擦除,写入操作也能进行,因为写入全零不会导致错误。
  2. 解锁闪存

    • 首先需要解锁闪存,解除写保护。
  3. 置位 PG 位

    • 设定控制寄存器的 PG(编程)位为 1,以表示即将进行数据写入。
  4. 写入数据

    • 在指定地址写入半字(16 位数据),代码:
*(__IO uint16_t *)(0x08000000) = 0x1234;

写入数据触发开始写入操作。写入半字后,芯片进入忙状态(BSY 位为 1)。需要等待 BSY 位清零,表示写入完成。

优化读写闪存的方法

  • 如果需要频繁读写闪存,最好的方法是先将闪存的一页读到 SRAM 中,进行读写操作后,再擦除闪存页,最后将修改后的数据整体写回闪存。这种方法可以使闪存的读写操作更加灵活,类似于对 SRAM 的读写操作。

5. 程序储存器页擦除

  1. 检查 LOCK 位

    • 读取 LOCK 位以检查芯片是否上锁。
    • 如果 LOCK=1,表示芯片上锁,需要执行解锁过程。在 KEYR 寄存器中,先写入 KEY1,再写入 KEY2。
    • 如果 LOCK=0,则芯片未上锁,无需解锁。
  2. 设置 PER 位

    • 置控制寄存器的 PER(Page Erase)位为 1,表示即将执行页擦除操作。
  3. 设置 AR 寄存器

    • 在地址寄存器(AR)中选择要擦除的页。提前将要擦除页的起始地址写入 AR 寄存器。
  4. 触发擦除操作

    • 置控制寄存器的 STRT 位为 1,触发擦除操作。STRT 为 1 时,芯片开始执行擦除操作。
    • 芯片会检查 PER=1,知道要执行页擦除,然后继续查看 AR 寄存器中的页起始地址以确定要擦除的具体页。
  5. 等待 BSY 位清零

    • 擦除开始后,等待芯片的忙状态(BSY)位清零,表示擦除操作完成。
  6. 读出并验证数据(可选):

    • 最后,可以读出并验证数据以确保擦除成功。对于测试程序来说,通常不需要进行此操作,因为工作量较大。

6. 程序储存器全擦除

检查 LOCK 位

  • 读取 LOCK 位以检查芯片是否上锁。
  • 如果 LOCK=1,表示芯片上锁,需要执行解锁过程。在 KEYR 寄存器中,先写入 KEY1,再写入 KEY2。
  • 如果 LOCK=0,则芯片未上锁,无需解锁。

设置 MER 位

  • 解锁后,置控制寄存器中的 MER(Mass Erase)位为 1,表示即将执行全片擦除操作。

触发擦除操作

  • 置控制寄存器的 STRT(Start)位为 1,触发擦除操作。STRT 为 1 后,芯片开始执行擦除操作。
  • 芯片检查到 MER 位为 1,就知道要执行全片擦除,内部电路自动开始全片擦除过程。

等待擦除完成

  • 擦除需要时间。擦除开始后,程序需执行等待,判断状态寄存器的 BSY(Busy)位是否为 1。
  • BSY 位为 1 表示芯片处于忙状态,等待 BSY 位清零表示擦除操作完成。

7. 选项字节

RDP:写入RDPRT键(0x000000A5)后解除读保护

USER:配置硬件看门狗和进入停机/待机模式是否产生复位

Data0/1:用户可自定义使用

WRP0/1/2/3:配置写保护,每一个位对应保护4个存储页(中容量)

nRDPRDP 的意义在于,当你写入 RDP 数据时,需要同时在 nRDP 写入该数据的反码。其目的是确保数据写入的有效性和安全性。如果芯片检测到这两个存储器中的数据不是反码的关系,说明数据无效且有错误,对应功能将不会执行。这是一种保障措施。写入反码的过程由硬件自动计算并写入。

RDP(Read Protect,读取保护)

  • 这是读保护配置位。
  • 如果 RDP 不为 A5,闪存将处于读取保护状态,无法通过调试器读取程序,从而避免被盗取。

WRP0/1/2/3

  • 这四个字节(共32位)对应每一位的保护页。
  • 每一位保护 4 页,总共保护 32*4=128 页。
  • 这样正好对应中密度容量的最大 128 页。

8. 选项字节编程

  1. 检查FLASH_SR的BSY位,以确认没有其他正在进行的编程操作
  2. 解锁FLASH_CR的OPTWRE位
  3. 设置FLASH_CR的OPTPG位(Option Programming)为1 -> 表示即将写入选项字节
  4. 写入要编程的半字到指定的地址 -> 指针写入操作
  5. 等待BSY位变为0
  6. 读出写入的地址并验证数据

9. 选项字节擦除

  1. 解锁闪存
  2. 检查FLASH_SR的BSY位,以确认没有其他正在进行的闪存操作(事前等待)
  3. 解锁FLASH_CR的OPTWRE位(Option Write Enable) -> 选项字节的解锁(选项字节有单 独的锁) -> 在FLASH_OPTKETR里先写入KEY1,再写入KEY2。
  4. 设置FLASH_CR的OPTER位(Option Erase)为1 -> 表示即将要擦除选项字节
  5. 设置FLASH_CR的STRT位为1 -> 触发芯片,开始干活,这样芯片就会启动擦除选项字 节的工作
  6. 等待BSY位变为0
  7. 读出被擦除的选择字节并做验证

10. 器件电子签名

电子签名存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名(STM32的ID号)。

闪存容量寄存器:

  • 基地址:0x1FFF F7E0
  • 大小:16位

产品唯一身份标识寄存器:

  • 基地址: 0x1FFF F7E8
  • 大小:96位

可以使用唯一ID号进行加密操作,写入一段程序在指定设备运行 -> 在程序中加入ID号判断.

11. 代码示例

STM32读写内部FLASH

STM32读写内部FLASH-CSDN博客


网站公告

今日签到

点亮在社区的每一天
去签到