STM32单片机FLASH闪存详解

文章目录

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博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TENET-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值