STM32的Flash操做

说到STM32FLSAH,咱们的第一反应是用来装程序的,实际上,STM32的片内FLASH不只用来装程序,还用来装芯片配置、芯片ID、自举程序等等。固然, FLASH还能够用来装数据。 编程

 

FLASH分类 安全

根据用途,STM32片内的FLASH分红两部分:主存储块、信息块。 ui

主存储块用于存储程序,咱们写的程序通常存储在这里。 spa

信息块又分红两部分:系统存储器、选项字节。 指针

系统存储器存储用于存放在系统存储器自举模式下的启动程序(BootLoader),当使用ISP方式加载程序时,就是由这个程序执行。这个区域由芯片厂写入BootLoader,而后锁死,用户是没法改变这个区域的。 调试

选项字节存储芯片的配置信息及对主存储块的保护信息。 接口

 

FLASH的页面 开发

STM32FLASH主存储块按页组织,有的产品每页1KB,有的产品每页2KB。页面典型的用途就是用于按页擦除FLASH。从这点来看,页面有点像通用FLASH的扇区。 产品

 

STM32产品的分类 it

STM32根据FLASH主存储块容量、页面的不一样,系统存储器的不一样,分为小容量、中容量、大容量、互联型,共四类产品。

小容量产品主存储块1-32KB,每页1KB。系统存储器2KB

中容量产品主存储块64-128KB,每页1KB。系统存储器2KB

大容量产品主存储块256KB以上,每页2KB。系统存储器2KB

互联型产品主存储块256KB以上,每页2KB。系统存储器18KB

对于具体一个产品属于哪类,能够查数据手册,或根据如下简单的规则进行区分:

STM32F101xxSTM32F102xx STM32F103xx产品,根据其主存储块容量,必定是小容量、中容量、大容量产品中的一种,STM32F105xxSTM32F107xx是互联型产品。

互联型产品与其它三类的不一样之处就是BootLoader的不一样,小中大容量产品的BootLoader只有2KB,只能经过USART1进行ISP,而互联型产品的BootLoader18KB,能经过USAT14CAN等多种方式进行ISP。小空量产品、中容量产品的BootLoader与大容量产品相同

 

关于ISPIAP

ISPIn System Programming)在系统编程,是指直接在目标电路板上对芯片进行编程,通常须要一个自举程序(BootLoader)来执行。ISP也有叫ICPIn Circuit Programming)、在电路编程、在线编程。

IAPIn Application Programming)在应用中编程,是指最终产品出厂后,由最终用户在使用中对用户程序部分进行编程,实如今线升级。IAP要求将程序分红两部分:引导程序、用户程序。引导程序老是不变的。IAP也有叫在程序中编程。

ISPIAP的区别在于,ISP通常是对芯片整片从新编程,用的是芯片厂的自举程序。而IAP只是更新程序的一部分,用的是电器厂开发的IAP引导程序。综合来看,ISP受到的限制更多,而IAP因为是本身开发的程序,更换程序的时候更容易操做。

 

FPEC

FPEC(FLASH Program/Erase controller 闪存编程/擦除控制器)STM32经过FPEC来擦除和编程FLASHFPEC使用7个寄存器来操做闪存:

FPEC键寄存器(FLASH_KEYR)                                   写入键值解锁。

选项字节键寄存器(FLASH_OPTKEYR)               写入键值解锁选项字节操做。

闪存控制寄存器(FLASH_CR)                                选择并启动闪存操做。

闪存状态寄存器(FLASH_SR)                                查询闪存操做状态。

闪存地址寄存器(FLASH_AR)                                存储闪存操做地址。

选项字节寄存器(FLASH_OBR)                             选项字节中主要数据的映象。

写保护寄存器(FLASH_WRPR)                              选项字节中写保护字节的映象。

 

键值

为了加强安全性,进行某项操做时,需要向某个位置写入特定的数值,来验证是否为安全的操做,这些数值称为键值。STM32FLASH共有三个键值:

RDPRT   = 0x000000A5         用于解除读保护

KEY1          = 0x45670123          用于解除闪存锁

KEY2          = 0xCDEF89AB             用于解除闪存锁

 

闪存锁

FLASH_CR中,有一个LOCK位,该位为1时,不能写FLASH_CR寄存器,从而也就不能擦除和编程FLASH,这称为闪存锁。

LOCK位为1时,闪存锁有效,只有向FLASH_KEYR依次写入KEY1KEY2后,LOCK位才会被硬件清零,从而解除闪存锁。当LOCK位为1时,对FLASH_KEYR的任何错误写操做(第一次不是KEY1,或第二次不是KEY2),都将会致使闪存锁的完全锁死,一旦闪存锁完全锁死,在下一次复位前,都没法解锁,只有复位后,闪存锁才恢复为通常锁住状态。

复位后,LOCK位默认为1,闪存锁有效,此时,能够进行解锁。解锁后,可进行FLASH的擦除编程工做。任什么时候候,均可以经过对LOCK位置1来软件加锁,软件加锁与复位加锁是同样的,均可以解锁。

 

主存储块的擦除

主存储块能够按页擦除,也能够整片擦除。

页擦除

主存储块的任何一页均可以经过FPEC的页擦除功能擦除。

建议使用如下步骤进行页擦除:

1.检查FLASH_SR寄存器的BSY位。以确认没有其余正在进行的闪存操做。必须等待BSY位为0,才能继续操做。

              2.设置FLASH_CR寄存器的PER位为1。选择页擦除操做。

3.设置FLASH_AR寄存器为要擦除页所在地址,选择要擦除的页。FLASH_AR的值在哪一页范围内,就表示要擦除哪一页。

4.设置FLASH_CR寄存器的STRT位为1,启动擦除操做。

5.等待FLASH_SR寄存器的BSY位变为0,表示操做完成。

6.查询FLASH_SR寄存器的EOP位,EOP1时,表示操做成功。

              7.读出被擦除的页并作验证。擦完后全部数据位都为1

 

整片擦除

整片擦除功能擦除整个主存储块,信息块不受此操做影响。

建议使用如下步骤进行整片擦除:

       1.检查FLASH_SR寄存器的BSY位,以确认没有其余正在进行的闪存操做。

              2.设置FLASH_CR寄存器的MER位为1。选择整片擦除操做。

              3.设置FLASH_CR寄存器的STRT位为1。启动整片擦除操做。

              4.等待FLASH_SR寄存器的BSY位变为0,表示操做完成。

              5.查询FLASH_SR寄存器的EOP位,EOP1时,表示操做成功。

              6.读出全部页并作验证。擦完后全部数据位都为1

 

主存储块的编程

对主存储块编程每次能够写入16位。当FLASH_CR寄存器的PG位为1时,在一个闪存地址写入一个半字(16位)将启动一次编程;写入任何非半字的数据,FPEC都会产生总线错误。在编程过程当中(BSY位为1),任何读写闪存的操做都会使CPU暂停,直到这次闪存编程结束。

建议使用以下步骤对主存储块进行编:

       1.检查FLASH_SR寄存器的BSY位,以确认没有其余正在进行的编程操做。

       2.设置FLASH_CR寄存器的PG位为1。选择编程操做。

       3.在指定的地址写入要编程的半字。直接用指针写。

       4.等待FLASH_SR寄存器的BSY位变为0,表示操做完成。

       5.查询FLASH_SR寄存器的EOP位,EOP1时,表示操做成功。

6.读出写入的地址并验证数据。

 

关于主存储块擦除编程操做的一些疑问

1. 为何每次都要检查BSY位是否为0

由于BSY位为1时,不能对任何FPEC寄存器执行写操做,因此必需要等BSY位为0时,才能执行闪存操做。

2. 若是没有擦除就进行编程,会出现什么结果?

STM32在执行编程操做前,会先检查要编程的地址是否被擦除,若是没有,则不进行编程,并置FLASH_SR寄存器的PGERR位为1。惟一例外的是,当要编程的数据为0X0000时,即便未擦除,也会进行编程,由于0X0000即便擦除也能够正确编程。

3. 为何操做后要读出数据并验证?

STM32在某些特殊状况下(例如FPEC被锁住),可能根本就没有执行所要的操做,仅经过寄存器没法判断操做是否成功。因此,保险起见,操做后都要读出全部数据检查。

4. 等待BSY位为1的时间以多少为合适?

请参考STM32固件库中的数据。

5. FLASH编程手册上说进行闪存操做(擦除或编程)时,必须打开内部的RC振荡器(HSI),是否是必定要用HIS进行闪存的擦除及编程操做?

对于这点,个人理解是,进行闪存操做时,必需要保证HIS没有被关闭,可是操做时的系统仍然能够是HSE时钟。STM32复位后,HIS默认是开的,只要你不为了低功耗去主动关闭它,则用什么时钟均可以进行闪存操做的。我所编的程序也验证了这一点。

 

选项字节

选项字节用于存储芯片使用者对芯片的配置信息。

目前,全部的STM32101xxSTM32102xxSTM32103xxSTM32105xxSTM32107xx产品,选项字节都是16字节。可是这16字节,每两个字节组成一个正反对,即,字节1是字节0的反码,字节3是字节2的反码,...,字节15是字节14的反码,因此,芯片使用者只要设置8个字节就好了,另外8个字节系统自动填充为反码。所以,有时候,也说STM32的选项字节是8个字节,可是占了16字节的空间。

选项字节的8字节正码概述以下:

RDP                    字节0。读保护字节,存储对主存储块的读保护设置。

USER           字节2。用户字节,配置看门狗、停机、待机。

Data0           字节4。数据字节0,由芯片使用者自由使用。

Data1           字节6。数据字节1,由芯片使用者自由使用。

WRP0          字节8。写保护字节0,存储对主存储块的写保护设置。

WRP1          字节10。写保护字节1,存储对主存储块的写保护设置。

WRP2          字节12。写保护字节2,存储对主存储块的写保护设置。

WRP3          字节14。写保护字节3,存储对主存储块的写保护设置。3

 

选项字节写使能

FLASH­_CR中,有一个OPTWRE位,该位为0时,不容许进行选项字节操做(擦除、编程)。这称为选项字节写使能。只有该位为1时,才能进行选项字节操做。

该位不能软件置1,但能够软件清零。只有向FLASH_OPTKEYR依次写入KEY1KEY2后,硬件会自动对该位置1,此时,才容许选项字节操做。这称为解锁(打开)选项字节写使能。

该位为1后,能够由软件清零,关闭写使能。

复位后,该位为0。错误操做不会永远关闭写使能,只要写入正确的键序列,则又能够打开写使能。写使能已打开时,再次打开,不会出错,而且依然是打开的。

很显然,进行选项字节操做前,先要解开闪存锁,而后打开选项字节写使能,以后,才能进行选项字节操做。

 

选项字节擦除

建议使用以下步骤对选项字节进行擦除:

       1.检查FLASH_SR寄存器的BSY位,以确认没有其余正在进行的闪存操做。

       2.解锁FLASH_CR寄存器的OPTWRE位。即,打开写使能。

       3.设置FLASH_CR寄存器的OPTER位为1。选择选项字节擦除操做。

       4.设置FLASH_CR寄存器的STRT位为1

       5.等待FLASH_SR寄存器的BSY位变为0,表示操做完成。

       6.查询FLASH_SR寄存器的EOP位,EOP1时,表示操做成功。

7.读出选项字节并验证数据。

因为选项字节只有16字节,所以,擦除时是整个选项字节都被擦除了。

 

选项字节编程

建议使用以下步骤对选项字节进行编程:

       1.检查FLASH_SR寄存器的BSY位,以确认没有其余正在进行的编程操做。

       2.解锁FLASH_CR寄存器的OPTWRE位。即,打开写使能。

       3.设置FLASH_CR寄存器的OPTPG位为1。选择编程操做。

       4.写入要编程的半字到指定的地址。启动编程操做。

       5.等待FLASH_SR寄存器的BSY位变为0,表示操做完成。

       6.查询FLASH_SR寄存器的EOP位,EOP1时,表示操做成功。

7.读出写入的选项字节并验证数据。

对选项字节编程时,FPEC使用半字中的低字节并自动地计算出高字节(高字节为低字节的反码),并开始编程操做,这将保证选项字节和它的反码始终是正确的。

 

主存储块的保护

能够对主存储块中的数据进行读保护、写保护。

读保护用于保护数据不被非法读出。防止程序泄密。

写保护用于保护数据不被非法改写,加强程序的健壮性。

读保护

主存储块启动读保护后,简单的说具备如下特性:

1.从主存储块启动的程序,能够对整个主存储块执行读操做,不容许对主存储块的前4KB进行擦除编程操做,能够对4KB以后的区域进行擦除编程操做。

2.从SRAM启动的程序,不能对主存储块进行读、页擦除、编程操做,但能够进行主存储块整片擦除操做。

       3.使用调试接口不能访问主存储块。

这些特性足以阻止主存储器数据的非法读出,又能保证程序的正常运行。

只有当RDP选项字节的值为RDPRT键值时,读保护才被关闭,不然,读保护就是启动的。所以,擦除选项字节的操做,将启动主存储块的读保护。若是要关闭读保护,必须将RDP选项字节编程为RDPRT键值。而且,若是编程选项字节,使RDP由非键值变为键值(即由保护变为非保护)时,STM32将会先擦除整个主存储块,再编程RDP

芯片出厂时,RDP会事先写入RDPRT键值,关闭写保护功能。

 

写保护

STM32主存储块能够分域进行写保护。

若是试图对写保护的域进行擦除或编程操做,在闪存状态寄存器(FLASH_SR)中会返回一个写保护错误标志。

STM32主存储块每一个域4KBWRP0-WRP3选项字节中的每一位对应一个域,位为0时,写保护有效。对于超过128KB的产品,WRP315保护了域31及以后的全部域。

显然,擦除选项字节将致使解除主存储块的写保护。

 

选项字节与它的寄存器映象

咱们知道,FPEC有两个寄存器存储了选项字节的映象。那么,选项字节本体(在FLASH中)与映象(在寄存器中)究竟有什么区别呢?

选项字节的本体只是个FLASH,它的做用只是掉电存储选项字节内容而以,真正起做用的是寄存器中的映象。即,一个配置是否有效,不是看本体,而是看映象。而映象是在复位后,用本体的值加载的,此后,除非复位,映象将再也不改变。因此,更改本体的数据后,不会当即生效,只有复位加载到映象中后,才会生效。

有一点要注意的是,当更改本体的值,使主存储块读保护变为不保护时,会先擦除整片主存储块,而后再改变本体。这是惟一一个改变本体会引起的动做。但即便这样,读保护依然要等到复位后,加载到映象后,才会解除。

 

 

关于FLASH编程手册中文版的几处错误(不必定是,可是与个人理解不符)

1.选项字节编程一节中:

FPEC解锁后,必须分别写入KEY1KEY2(2.3.1)FLASH_OPTKEYR寄存器,再设置FLASH_CR寄存器的OPTWRE位为’1’,此时能够对选项字节进行编程

实际上,对FLASH_OPTKEYR写入KEY1KEY2后,OPTWRE位会被硬件置1,而不是用软件写1。这一点在后面的寄存器描述中也能够获得验证。

2.对读保护的描述中:

对读保护的数值对没法理解。正确的应该是,RDPRDPRT键值时,解除读保护,为其它值时,读保护生效。