stm32 Flash闪存

Flash闪存(掉电不丢失的存储器)

  1. STM32F1系列的FLASH包含程序存储器(起始地址:0x0800 0000)、系统存储器(起始地址0x1FFFF000)和选项字节(起始地址:0x1FFFF800)三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程

  1. 读写FLASH的用途:
  2. 1. 利用程序存储器的剩余空间来保存掉电不丢失的用户数据
  3. 2. 通过在程序中编程(IAP),实现程序的自我更新

  1. 在线编程(In-Circuit Programming – ICP)用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载程序

  1. 在程序中编程(In-Application Programming – IAP)可以使用微控制器支持的任一种通信接口下载程序

  • 闪存模块组织:

  1. 闪存的部分:
  • 主存储器:程序存储器,用来存放数据代码的,这个C8T6芯片自带的flash(只有64K(页),中容量的一半)只有一个单位就是页(1KB),不像W25Q64那样有块、扇区、页那么复杂并且分页是为了更好的管理闪存,同时擦除和写保护都是以页为单位的。

注:地址只要以000、400、800、C00结尾的都是页的起始地址

  • 信息块:
  1. 启动程序代码(程序存储器):存放原厂写入的bootloader,用于串口下载,
  2. 用户选择字节(选项字节):存放一些独立的参数

注:平时说的,芯片闪存容量是64K,128K是主存储器容量,信息块里的东西虽然也是闪存,但是并不统计在这个容量里面。

  1. 闪存的管理员部分:
  • 闪存存储器接口寄存器:这些存储器就是用来控制擦除和编程这个过程的,实际并不算flash,因为他们地址首位都是4开头,基本和GPIO、定时器等等是一个性质的东西。并且这些存储器它们的存储介质,也都是SRAM。

注:闪存存储器接口寄存器里包括了KEYR键寄存器,SR,CR等等寄存器,外设起始地址为0x4002 2000,每个寄存器都是4个字节(32位)

  1. Flash的基本结构图:

整个闪存分为程序存储器、系统存储器、选项字节三部分。

闪存存储器接口(也称为闪存编程和擦除控制器(FPEC)):

它可以对程序存储器进行编程和擦除,同时也可以对选项字节进行擦除和编程

选项字节

选项字节里有很大一部分配置位,主要是用来配置主程序存储器的读写保护

  1. Flash的解锁操作(配置FPEC(闪存编程和擦除控制器))
  1. FPEC共有三个键值:
  2.      RDPRT键 = 0x000000A5
  3.    KEY1 = 0x45670123
  4.      KEY2 = 0xCDEF89A

  1. 解锁操作:
  2. 1. 复位后,FPEC被保护,不能写入FLASH_CR

(就是复位后flash默认是锁着的)

2. 在FLASH_KEYR先写入KEY1,再写入KEY2,解锁

3. 错误的操作序列会在下次复位前锁死FPEC和FLASH_CR

(就是发现有程序在尝试撬锁,没有按照先key1再key2的操作开锁,整个模块就会锁死,除非复位)

  1. 加锁操作:
  2.      设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR

  • 如何使用指针访问存储器:

因为stm32的内部存储器都是挂在总线上的,所以想读写某个寄存器就很简单直接使用c中的指针访问即可。

volatile是c语言中的关键字,直译是易变的数据

volatile的作用是:

添加一个安全保障措施,防止编译器优化;

编译器优化等级:用途是可以去除无用的繁杂代码,降低代码空间,提升运行效率。

Keil编译器默认情况下是最低优化等级,如果要提高编译器优化等级编译器在有些地方就会弄巧成。总之,如果想运用一些方法完成或实现某种功能就在变量定义前面加上volatile告诉编译器不要将其优化掉了,原封不动的去执行即可。

  • 其中:   

#define    __IO    volatile

  • 使用指针读指定地址下的存储器(不用解锁):
  •      uint16_t Data = *((__IO uint16_t *)(0x08000000));

将0x08000000强制类型转换成uint16_t * 类型且是防止编译器优化的类型,然后用*取出指针内容。

  • 使用指针写指定地址下的存储器:
  •      *((__IO uint16_t *)(0x08000000)) = 0x1234;

先给定地址,再强转为指针,最*号取内容

同时,闪存在程序运行时,是只读的,不能轻易更改,而现在需要对闪存进行修改,所以需要权限较高,需要提前解锁,并且还要套一个下面的程序存储器编程过程的流程。

  1. 程序存储器编程图(写入)

Stm32的闪存会在写入之前检查指定地址有没有擦除,如果没有擦除就写入,stm32就不执行写入操作。除非写入的都是0,这个除外因为不擦除写入会导致写入错误。

流程:

  1. 读取lock位,查看锁没锁,锁住执行解锁操作
  2. 置CR寄存器的PG(Programming)为1,表示即将写入数据。
  3. 在指定的地址写入半字(16位)(同时也是触发),就是用上面的使用指针在指定地址写入数据

注:写入操作,只能以半字(16位的形式)的形式写入

  1. 因为擦除是要时间的,所以程序要执行等待,也就是判断BSY(busy)位是否为1,busy位表示芯片是否处于忙状态,为1表示芯片在忙,所以这里要一直等到BSY位0,跳出循环
  2. 最后,读出并验证所有页的流程,这个是验证程序干的,我们不需要执行这个操作。
  • 程序存储器页擦除

Stm32的闪存也是写入前必须擦除,擦除后,所有数据位变为1

擦除的最小位就是1页(1K(1024字节))

流程:

  1. 读取lock位,查看锁没锁,锁住执行解锁操作

2. 置CR寄存器里的PER(Page Erase)位为1,然后在AR地址寄存器中选择要擦除的页,最后置CR寄存器中STRT(Start)位(触发位)为1,当触发位为1时,芯片开始运行

然后芯片看到PER位置1,就会执行页擦除流程,同时查看Address Register中的数据指定地址。

  1. 因为擦除是要时间的,所以程序要执行等待,也就是判断BSY(busy)位是否为1,busy位表示芯片是否处于忙状态,为1表示芯片在忙,所以这里要一直等到BSY位0,跳出循环
  2. 最后,读出并验证所有页的流程,这个是验证程序干的,我们不需要执行这个操作
  1. 程序存储器全擦除:

作用:将所有页都擦除掉

流程:

  1. 读取lock位,查看锁没锁,锁住执行解锁操作
  2. 置CR寄存器里的MER(Mass Erase)位为1,然后再置STRT(Start)位(触发位)为1,当触发位为1时,芯片开始运行

然后芯片看到MER位置1,就会执行全擦除流程

  1. 因为擦除是要时间的,所以程序要执行等待,也就是判断BSY(busy)位是否为1,busy位表示芯片是否处于忙状态,为1表示芯片在忙,所以这里要一直等到BSY位0,跳出循环
  2. 最后,读出并验证所有页的流程,这个是验证程序干的,我们不需要执行这个操作。

注:这三个操作库函数已经封装好了,直接调用整体函数即可。

  1. 选项字节

这个图中是选项字节(16个字节)的展开

同时有些位前有个n,意思是例如RDP和nRDP,就是在写入RDP的数据时,同时也要在nRDP中写入与之对应的反码,其他的也是一样,写入的同时要在带n的对应的寄存器中写入反码,这样写入才有效。这是个安全措施,同时硬件会自动帮我们检查,不需要调试。

RDP:Read Protect(读保护配置位)若写入RDPRT键(0x000000A5)后解除读保护

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

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

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

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

  1. 选项字节的擦除:
  1. 检查FLASH_SR的BSY位,以确认没有其他正在进行的闪存操作
  2. 解锁FLASH_CR的OPTWRE位(选项字节的解锁)
  3. 设置FLASH_CR的OPTER位为1(选择字节开始擦除)
  4. 设置FLASH_CR的STRT位为1
  5. 等待BSY位变为0
  6. 读出被擦除的选择字节并做验证

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

  1. 闪存容量寄存器:
  2.      基地址:0x1FFF F7E0
  3.      大小:16位

  1. 产品唯一身份标识寄存器:
  2.      基地址: 0x1FFF F7E8
  3.      大小:96位
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值