说到STM32的FLSAH,我们的第一反应是用来装程序的,实际上,STM32的片内FLASH不仅用来装程序,还用来装芯片配置、芯片ID、自举程序等等。当然, FLASH还可以用来装数据。

FLASH分类

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

主存储块用于存储程序,我们写的程序一般存储在这里。

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

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

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

FLASH的页面

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

STM32产品的分类

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

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

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

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

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

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

STM32F101xx、STM32F102xx 、STM32F103xx产品,根据其主存储块容量,一定是小容量、中容量、大容量产品中的一种,STM32F105xx、STM32F107xx是互联型产品。

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

关于ISPIAP

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

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

ISP与IAP的区别在于,ISP一般是对芯片整片重新编程,用的是芯片厂的自举程序。而IAP只是更新程序的一部分,用的是电器厂开发的IAP引导程序。综合来看,ISP受到的限制更多,而IAP由于是自己开发的程序,更换程序的时候更容易操作。

FPEC

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

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

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

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

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

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

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

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

键值

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

RDPRT键   = 0x000000A5         用于解除读保护

KEY1          = 0x45670123          用于解除闪存锁

KEY2          = 0xCDEF89AB             用于解除闪存锁

闪存锁

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

当LOCK位为1时,闪存锁有效,只有向FLASH_KEYR依次写入KEY1、KEY2后,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位,EOP为1时,表示操作成功。

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位,EOP为1时,表示操作成功。

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位,EOP为1时,表示操作成功。

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默认是开的,只要你不为了低功耗去主动关闭它,则用什么时钟都可以进行闪存操作的。我所编的程序也验证了这一点。

选项字节

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

目前,所有的STM32101xx、STM32102xx、STM32103xx、STM32105xx、STM32107xx产品,选项字节都是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依次写入KEY1和KEY2后,硬件会自动对该位置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位,EOP为1时,表示操作成功。

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位,EOP为1时,表示操作成功。

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

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

主存储块的保护

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

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

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

读保护

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

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

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

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

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

只有当RDP选项字节的值为RDPRT键值时,读保护才被关闭,否则,读保护就是启动的。因此,擦除选项字节的操作,将启动主存储块的读保护。如果要关闭读保护,必须将RDP选项字节编程为RDPRT键值。并且,如果编程选项字节,使RDP由非键值变为键值(即由保护变为非保护)时,STM32将会先擦除整个主存储块,再编程RDP。

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

写保护

STM32主存储块可以分域进行写保护。

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

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

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

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

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

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

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

关于FLASH编程手册中文版的几处错误(不一定是,但是与我的理解不符)

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

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

实际上,对FLASH_OPTKEYR写入KEY1和KEY2后,OPTWRE位会被硬件置1,而不是用软件写1。这一点在后面的寄存器描述中也可以得到验证。

2.对读保护的描述中:

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

关于STM32的FLASH操作【转载】的更多相关文章

  1. stm32的flash操作注意事项

    从STM32编程手册中,可以知道:在进行写或擦除操作时,不能进行代码或数据的读取操作. 比如:你在写Flash期间有接收串口数据,很有可能会丢串口数据. 因为比较耗时,所以,在写数据时,CPU不会执行 ...

  2. u-boot移植总结(三)(转)S3C2440对Nand Flash操作和电路原理(基于K9F2G08U0A)

    S3C2440对Nand Flash操作和电路原理(基于K9F2G08U0A) 转载自:http://www.cnblogs.com/idle_man/archive/2010/12/23/19153 ...

  3. STM32位带操作

    STM32的位带操作是基于cortex内核自带的,而不是st公司独创.基本的思路就是用一个32位的地址空间访问一个bit,因为stm32只支持32位数据的读取,不像51单片机一样,是可以单独对一位操作 ...

  4. STM32的Flash

    STM32中存储区分为:随机存取存储器RAM和只读存储器ROM. 其中: RAM为常说的内存,比如手机的2G内存4G内存等,就是程序跑起来的时候所占用的存储空间,特点是掉电数据丢失. ROM为常说的硬 ...

  5. STM32串口寄存器操作(转)

    源:STM32串口寄存器操作 //USART.C /************************************************************************** ...

  6. SqlServer中的merge操作(转载)

    SqlServer中的merge操作(转载)   今天在一个存储过程中看见了merge这个关键字,第一个想法是,这个是配置管理中的概念吗,把相邻两次的更改合并到一起.后来在technet上搜索发现别有 ...

  7. flash stm32的flash编写

    定义一个全局变量数组:const u8 TEXT_Buffer[]={"STM32F103 FLASH TEST"};    //u8和char* 写入到内存里会有什么区别???? ...

  8. 安卓自定义View进阶-Canvas之画布操作 转载

    安卓自定义View进阶-Canvas之画布操作 转载 https://www.gcssloop.com/customview/Canvas_Convert 本来想把画布操作放到后面部分的,但是发现很多 ...

  9. STM32的SPI2操作Flash

    关于STM32F107的SPI标志 SPI_I2S_FLAG_BSY和SPI_I2S_FLAG_TXE的疑问  http://www.openedv.com/posts/list/23579.htm ...

随机推荐

  1. PHP与Golang如何通信?

    PHP与Golang如何通信? 最近遇到的一个场景:php项目中需要使用一个第三方的功能(结巴分词),而github上面恰好有一个用Golang写好的类库.那么问题就来了,要如何实现不同语言之间的通信 ...

  2. 谈谈pooling?

    使用pooling的目的之一是获取一定的特征不变性,目前用的比较多的是Max..,非线性对于Deep的重要性不用多说,pooling是主要贡献之一,当然少不了relu类的激活函数.pooling还有一 ...

  3. 【Mocha.js 101】Mocha 入门指南

    序 说到质量控制,不得不提起测试驱动开发(TDD)和行为驱动开发(BDD).随着敏捷软件开发的推行,软件质量控制的重担也逐渐从测试工程师转向了研发工程师.测试驱动也随之悄然而生,成为了敏捷开发中重要的 ...

  4. C# 的各种排序

    http://www.cnblogs.com/jiajiayuan/category/302446.html

  5. Winform绑定数据源的几种方式?

    第一种:DataSet ds=new DataSet (); this.dataGridView1.DataSource=ds.Table[0]; 第二种:DataTable dt=new DataT ...

  6. 在项目中导入MRC的文件时解决办法

    1.由于在项目中要使用到第三方框架和其他的类的时候,而它用的是MRC的时候,其最简便的方法:完成从MRC到ARC的转换. 1.点击工程文件,进入到工程的设置里面. 2.看见Build Phases,就 ...

  7. HTML5视频Video 音频Audio

    视频协议 视频格式 Flash HTML5 HTTP flv HTTP f4v HTTP mp4 HTTP m3u8 HTTP webm HTTP ogg RTMP flv RTMP f4v RTMP ...

  8. html页面元素事件丢失

    前段时间做网站包括最近用mvc做oa都发现这个奇怪现象,就是页面加载完毕后页面元素事件(比如按钮点击.复选框change)一切正常,但是当执行查询或者其他操作后页面事件丢失.具体原因暂没有时间分析,现 ...

  9. UVA1103

    题意:输入以16进制的矩阵,先转换成2进制,之后输出形成的图案. 思路:先处理掉无关图案的0,之后一个图案一个图案的遍历,识别图案的方法就是有多少个圈圈.找到一个就全部标记为-1.并且记录圆圈的数目. ...

  10. c++句柄设计

    句柄,也称为智能指针. 我计算了一下我的时间,以后每14天得读完一本书,才不愧对我买的这么多书.然而我还要抽出时间来谢谢博文.最近读的是c++沉思录,开篇就用了3章来讲述句柄.好了,废话少说,接下来谈 ...