你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 Flash详解

[复制链接]
STMCU-管管 发布时间:2020-9-9 10:13
01概述
这里的flash是指STM32F207内部集成的Flash
) z5 b% Q, {: P+ Y( L) z
Flash存储器有以下特点
# A* |) l0 Y( o
  • 最大1M字节的能力
  • 128位,也就是16字节宽度的数据读取
  • 字节,半字,字和双字写入
  • 扇区擦除和批量擦除, @& `* K  C1 b5 L6 G; w
2 ?" X5 M( i! L. A) u  z# }9 o
存储器的构成

# M6 t( @% c& A) r
主要存储区块包含4个16K字节扇区,1个64K字节扇区和7个128K字节扇区。
: \. k5 f! I) W$ r# H- A0 R
系统存储器是用于在系统boot模式启动设备的。这一块是预留给ST的。包括bootloader程序,boot程序用于通过以下接口对Flash进行编程。USART1、USART3、CAN2、USB OTG FS设备模式(DFU:设备固件升级)。boot程序由ST制造期间编写,用于保护防止错误写入和擦除操作。

7 ~: H9 v: l; I) a  ]! ?" a
512OTP(一次性编程)字节用于用户数据。OTP区域包含16个附加的字节,用于锁定响应的OTP数据。
2 ^* e4 e& C) }& p7 p# T# j
选项字节,读写保护,BOR水平,软件/硬件看门狗和复位当设置处于待机和停机状态。

: I, z6 A: H5 W0 W6 k! r
* c7 O& o1 u1 l2 b/ z" D$ U5 y
低功耗模式(参考参考手册的PWR部分)
1.png
/ v9 S& j+ T* C' W
对比参考手册的boot部分
2.png

5 Q: e. A- X! C# P% R: o
当BOOT0为0是运行主存储区
2 |! O! T2 u4 w2 B7 `, G5 G" Y
当BOOT0为1,BOOT1为0时运行系统存储区

4 ?$ n: c# [/ ?+ o
系统存储区运行的是ST出厂的bootloader代码,跳过过了用户的代码。如果在应用层代码锁定了JTAG管脚(将JTAG管脚用于普通GPIO),我们可以通过修改boot管脚状态,进入系统存储中,再进行debug。

; `6 z6 Z* A2 N( g7 z& O3 f0 W  H$ Q
02Flash操作
+ Y$ C: g! f3 x7 |+ a, m( @0 \+ i6 d  Q
2.1、读取
内置的Flash是处于CortexM3的数据总线上的,所以可以在通用地址空间之间寻址,任何32位数据的读操作都能访问Flash上的数据。
  1. data32 = *(__IO uint32_t*)Address;
复制代码

( l; l+ O% k$ P$ P8 h9 g. o: e9 z
将Address强制转化为32位整型指针,然后取该指针所指向的地址的值,就得到了Address地址上的32位数据。) R/ n' v2 o- y0 C. A2 k

$ [) ~% N% L( s  x
2.2、擦除
Flash 擦除操作可针对扇区或整个Flash(批量擦除)执行。执行批量擦除时,不会影响OTP扇区或配置扇区。
2 A! p/ \4 \1 w7 n
扇区擦除步骤
  • 1、检查FLASH_SR 寄存器中的BSY 位,以确认当前未执行任何Flash 操作
  • 2、在FLASH_CR 寄存器中将SER 位置1 并选择要擦除的扇区(SNB)(主存储器块中的12个扇区之一)
  • 3、将FLASH_CR 寄存器中的STRT 位置1
  • 4、等待BSY 位清零
      E( ^$ H& y6 c/ G" o- ]
  Y& M% r& M4 [. w# u9 l
: \0 y) l* t7 L" C& ?
批量擦除步骤
( O: o& y" j( [  f0 L, i
  • 1、检查FLASH_SR 寄存器中的BSY 位,以确认当前未执行任何Flash 操作
  • 2、将FLASH_CR 寄存器中的MER 位置1
  • 3、将FLASH_CR 寄存器中的STRT 位置1
  • 4、等待BSY 位清零3 K" [- k$ }4 v; F! _
$ f7 g* X% L, [; _( F8 S1 v
" n  }3 _( @6 M$ X7 }
ST提供相应的库函数接口
  1. - ?& v8 @9 A" x' c
  2. FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_tVoltageRange). ?. E$ q- k4 i, _
  3. FLASH_Status FLASH_EraseAllSectors(uint8_tVoltageRange)
复制代码

8 @3 p3 E- z* {# T9 P7 W8 {8 D" b

5 n/ O/ A; ?: i( e  j; E* W. F) ]
注意到,有个特殊的参数VoltageRange,这是因为
7 f% R9 h! W& _6 u8 H$ O
3.png

' m5 y' q" T" M* v. z
这里就不再翻译了,就是在不同电压下数据访问的位数不同,我们是3.3V,所以是32位数据,这也就是在读数据是为什么要读取32位的原因。

' P- Z' Q, _/ L2 v4 T
2.3、写入
写入之前必须擦除,这里和NorFlash操作是相同的

( m' f; O. V2 l5 z" E9 G
复位后,Flash控制器寄存器(FLASH_CR)不允许写入的,去保护Flash闪存因为电气原因出现的以外操作,以下是解锁的步骤
+ j  S6 t) j# E! h
  • 1、在Flash 密钥寄存器(FLASH_KEYR) 中写入KEY1 = 0x45670123
  • 2、在Flash 密钥寄存器(FLASH_KEYR) 中写入KEY2 = 0xCDEF89AB/ G) b/ `8 v, L, j1 `( ^- V7 r/ e

0 E: F0 K# w5 ]& S0 h8 F
将FLASH_CR 寄存器中的LOCK 位置为1 后,可通过软件再次锁定FLASH_CR 寄存器
! Z, x: D5 k: ^0 m6 r4 D
ST提供了库函数
/ q5 x0 x- I( I# C+ P" `. k  d

  1. ( }/ K8 A0 R4 A) g) v! V
  2. FLASH_Unlock();//解锁
    7 b" p4 e( S* L6 h& t
  3. FLASH_Lock();//重新上锁
复制代码

+ ?6 s; x" F( D/ l7 Y+ I

9 H: L  N. p- F  }8 Z$ K7 X
备注:
7 Z  X  Q- [' _# Z4 T% f
当FLASH_SR 寄存器中的BSY 位置为1 后,将不能在写模式下访问FLASH_CR 寄存器。BSY 位置为1 后,对该寄存器的任何写操作尝试都会导致AHB 总线阻塞,直到BSY位清零
$ {5 H" y9 R# v
这要求我们在写入前必须判断下FLASH_SR寄存器中的BSY位。
' [& H( |2 }/ S7 o) a
ST提供了对用的库函数
  1. " O& s$ C% S$ l+ P& U. O% g1 M# T% Q# w' |
  2. FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR| FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
复制代码

# j7 [- Q9 M; g
写入步骤
$ |8 ]- E* ~: a
  • 1、检查FLASH_SR 中的BSY 位,以确认当前未执行任何主要Flash 操作
  • 2、将FLASH_CR 寄存器中的PG 位置1。
  • 3、通过不同的位宽对指定地址写入
  • 4、等待BSY 位清零* G! a+ S1 B* O9 l( t: c

7 L% X6 E: k  N, I! E/ U4 F0 ~
对于写入接口,ST提供相应的库函数,提供了8位,16位,32位的操作,因为我们是3.3V电压,所以使用32位写入接口
  1. FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)
    8 s3 W# Q- G+ B2 C) n
复制代码
) [$ {# a' w( B" P  q! k) p
2.4、中断
如果对于写入要求较高,可以使能中断,对于写入完成,写入错误都会有响应的中断响应。我也没有详细研究,参看Flash编程手册的15.5章节
" X+ Z( a% E0 w+ t0 Y
03Flash保护
6 l. I1 N0 a' Q4 J. f# {" l0 n  y
3.1概述
Flash具有读写保护机制,主要是用过选项地址实现的。还有一次性编程保护
+ i0 o( n  x9 S% U) @! J1 [( [
4.png
这讲述了选项字节的构成
: w' \0 M% @4 }$ u: r: m
5.png
用户修改选项字节
6 M+ P, t# T% O% V2 |
To run any operation on this sector, the option lock bit (OPTLOCK) inthe Flash option control register (FLASH_OPTCR) must be cleared. Tobe allowed to clear this bit, you have to perform the followingsequence:
' l) |' W7 p/ o
1. Write OPTKEY1 = 0x0819 2A3B in the Flash option key register(FLASH_OPTKEYR)
2. Write OPTKEY2 = 0x4C5D 6E7F in the Flash option key register(FLASH_OPTKEYR)
The user option bytes can be protected against unwanted erase/programoperations by setting the OPTLOCK bit by software.

  p  D' u' O0 [1 a4 X; a
这个上面讲述的解锁Flash相同,就是要写入不能的数值
/ f; Q* L4 R: v
ST提供相应的库函数

9 ^: K" L6 {; n6 B6 Z! E' l+ f' D+ v
  1. 5 g' m: R6 s; R: o5 {% X3 `2 e
  2. void FLASH_OB_Unlock(void)% j9 y1 t" p6 _& N; v
  3. void FLASH_OB_Lock(void)
复制代码

; v9 U4 C4 g1 N3 ^2 n

+ v& r9 n) O, O" V3 [! u4 m
修改用户字节的步骤
: D' X& u+ D/ I" ]  ^
  • 1、检查FLASH_SR 寄存器中的BSY 位,以确认当前未执行任何Flash 操作
  • 2、在FLASH_OPTCR 寄存器中写入所需的选项值
  • 3、将FLASH_OPTCR 寄存器中的选项启动位(OPTSTRT) 置1
  • 4、等待BSY 位清零
    % E  i& y% e, A3 e/ F, K2 z  I* z4 @

2 G: z4 F* Z8 a) C
% f7 s9 q$ ]: W# Z6 n
3.2 读保护
从上面概述中得知,Flash读保护共分三个等级
1 等级0:没有保护) B; A2 O" I: \+ h0 m% B# f
将0xAA 写入读保护选项字节(RDP) 时,读保护级别即设为0。此时,在所有自举配置(Flash用户自举、调试或从RAM 自举)中,均可执行与Flash 或备份SRAM 相关的所有读/写操作(如果未设置写保护)。

7 g; x/ z' S. f8 t, H
2 等级1:闪存读保护# Z& u: ^, n5 ?% F4 f0 ^
这是擦除选项字节后的默认读保护级别。将任意值(分别用于设置级别0 和级别2 的0xAA和0xCC 除外)写入RDP 选项字节时,即激活读保护级别1。设置读保护级别1 后:

5 Y* U9 B, }' x4 L, c: X
-在连接调试功能或从RAM 进行自举时,将不执行任何Flash 访问(读取、擦除和编程)。Flash 读请求将导致总线错误。而在使用Flash 用户自举功能或在系统存储器自举模式下操作时,则可执行所有操作

2 c2 O+ B8 \' U3 ]: W
-激活级别1 后,如果将保护选项字节(RDP) 编程为级别0,则将对Flash 和备份SRAM执行批量擦除。因此,在取消读保护之前,用户代码区域会清零。批量擦除操作仅擦除用户代码区域。包括写保护在内的其它选项字节将保持与批量擦除操作前相同。OTP 区域不受批量擦除操作的影响,同样保持不变。
8 |( o2 Q  ~% L( y; L" h3 T4 ?& W
只有在已激活级别1 并请求级别0 时,才会执行批量擦除。当提高保护级别(0->1,1->2, 0->2) 时,不会执行批量擦除。.
3 等级2:禁止调试/芯片读保护
; H0 u% O- j; d# _- y
注意:

" o1 G$ c9 w# B6 \0 B  B
在注意中写道,如果使能了等级2的读保护,永久禁止JTAG端口(相当于JTAG熔丝)ST也无法进行分析,说白了就是没办法再debug了,目前我没有使用到这个水平的读保护
读保护库函数
  1. void FLASH_OB_RDPConfig(uint8_t OB_RDP)
复制代码
5 u2 b( F1 J  `# G
查询读保护状态库函数
  1. FlagStatus FLASH_OB_GetRDP(void)
复制代码

& z$ o( w4 ]7 e
3.3 写保护
Flash 中的用户扇区(0到11)具备写保护功能,可防止因程序计数器(PC) 跑飞而发生意外的写操作。当扇区i 中的非写保护位(nWRPi, 0 ≤ i ≤ 11) 为低电平时,无法对扇区i 执行擦除或编程操作。因此,如果某个扇区处于写保护状态,则无法执行批量擦除。
: g) V, v& M1 F) v2 g- z
3 T# p5 w; e, K" |

" [2 w) X  G/ V5 p, H; t8 n如果尝试对Flash 中处于写保护状态的区域执行擦除/编程操作(由写保护位保护的扇区、锁定的OTP 区域或永远不能执行写操作的Flash 区域,例如ICP),则FLASH_SR 寄存器中的写保护错误标志位(WRPERR) 将置1。
# L: A: z. m6 X) o7 Z
9 X& Z) I& K4 T
9 ]) a* m* m# C2 R$ X6 @
写保护库函数

  1. 7 z& x- g2 }* U+ T1 `* u6 Y& w
  2. void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState)
复制代码
3 i2 e6 ?7 C0 E9 Q& |$ p  l
- Z! B# x9 a" i( ]$ a6 h
查询写保护状态库函数
, `$ V* ?' H/ h% I' X, d1 w/ K
  1. uint16_t FLASH_OB_GetWRP(void)
复制代码
04一次性可编程字节+ d4 p/ y& o5 T& M4 x; m  k1 G
没有使用过,使用了芯片就废了吧,没有做过这个等级等保护,可以参看Flash编程手册的2.7章节

+ a+ q& Z( {& @2 S4 T
05 代码
  V- G! h& @. D; v+ X7 @7 Q9 _
关于读写保护代码如何调用的问题,在stm32f2xx_flash.c文件中有调用说明.
- I( n& W- a' S) B$ J

/ ^# L8 W5 K. ^  K! |: y3 ^1 C
收藏 评论0 发布时间:2020-9-9 10:13

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版