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

STM32 Flash详解

[复制链接]
STMCU-管管 发布时间:2020-9-9 10:13
01概述
这里的flash是指STM32F207内部集成的Flash

- k$ Y8 U( {0 x2 M: S
Flash存储器有以下特点
) S9 o1 l9 Q. U0 N- C
  • 最大1M字节的能力
  • 128位,也就是16字节宽度的数据读取
  • 字节,半字,字和双字写入
  • 扇区擦除和批量擦除
    ' z8 v6 o5 {' W4 q

+ h: @/ U! V+ c: }, D1 Y$ `
存储器的构成

( P5 {& A% q) Q$ r4 R* ~# U6 s
主要存储区块包含4个16K字节扇区,1个64K字节扇区和7个128K字节扇区。
- U1 w6 b  o; k2 U' W& z0 K
系统存储器是用于在系统boot模式启动设备的。这一块是预留给ST的。包括bootloader程序,boot程序用于通过以下接口对Flash进行编程。USART1、USART3、CAN2、USB OTG FS设备模式(DFU:设备固件升级)。boot程序由ST制造期间编写,用于保护防止错误写入和擦除操作。
; p, S" a6 ?0 C8 Z2 V. {
512OTP(一次性编程)字节用于用户数据。OTP区域包含16个附加的字节,用于锁定响应的OTP数据。

* ]. b* p* W! a) D# X; r8 M
选项字节,读写保护,BOR水平,软件/硬件看门狗和复位当设置处于待机和停机状态。
+ B( A1 ?) `( l$ G7 Z) V$ W; f% A

) x+ D8 r/ E  I; H, y# e
低功耗模式(参考参考手册的PWR部分)
1.png

2 b: @9 t2 w" h' x
对比参考手册的boot部分
2.png

8 C! \) y9 F, h, |
当BOOT0为0是运行主存储区
/ o" h. q" z1 T7 }2 C
当BOOT0为1,BOOT1为0时运行系统存储区

( E- g! X* w" h7 K+ b
系统存储区运行的是ST出厂的bootloader代码,跳过过了用户的代码。如果在应用层代码锁定了JTAG管脚(将JTAG管脚用于普通GPIO),我们可以通过修改boot管脚状态,进入系统存储中,再进行debug。
* c# T' T6 p# [& S: o
02Flash操作
' g- F$ h' V' Q: T7 o$ t
2.1、读取
内置的Flash是处于CortexM3的数据总线上的,所以可以在通用地址空间之间寻址,任何32位数据的读操作都能访问Flash上的数据。
  1. data32 = *(__IO uint32_t*)Address;
复制代码

0 u: L4 Y! \  Q. f5 o
将Address强制转化为32位整型指针,然后取该指针所指向的地址的值,就得到了Address地址上的32位数据。( _1 o' e% }3 ~7 |

! t/ G1 M+ o8 w3 {% b
2.2、擦除
Flash 擦除操作可针对扇区或整个Flash(批量擦除)执行。执行批量擦除时,不会影响OTP扇区或配置扇区。
! i+ B; e/ l* Q* X: }
扇区擦除步骤
  • 1、检查FLASH_SR 寄存器中的BSY 位,以确认当前未执行任何Flash 操作
  • 2、在FLASH_CR 寄存器中将SER 位置1 并选择要擦除的扇区(SNB)(主存储器块中的12个扇区之一)
  • 3、将FLASH_CR 寄存器中的STRT 位置1
  • 4、等待BSY 位清零: r. e5 C2 G5 @

- X+ ?/ K  ~! K( z* C
' g* S, I$ j9 T) p
批量擦除步骤

( ~' O  H1 V, ?* U9 a4 t
  • 1、检查FLASH_SR 寄存器中的BSY 位,以确认当前未执行任何Flash 操作
  • 2、将FLASH_CR 寄存器中的MER 位置1
  • 3、将FLASH_CR 寄存器中的STRT 位置1
  • 4、等待BSY 位清零
    + l: D9 e  f, W7 L, A( j2 `) `8 ^; ]
8 p! N% s; g- _& n% ~

0 M4 t- o# n  @  M
ST提供相应的库函数接口
  1. # M# D3 `. X6 x" {6 N8 ]0 u
  2. FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_tVoltageRange)$ J0 f: n5 _* @( p0 l4 i
  3. FLASH_Status FLASH_EraseAllSectors(uint8_tVoltageRange)
复制代码
( ~/ o' o1 s* T$ C; y
: v9 ^+ y& \  \- t
注意到,有个特殊的参数VoltageRange,这是因为

) h) _$ Y: u! [- o/ o
3.png
2 `3 c" p) m: j6 k0 ~$ C
这里就不再翻译了,就是在不同电压下数据访问的位数不同,我们是3.3V,所以是32位数据,这也就是在读数据是为什么要读取32位的原因。

% ?3 O% R9 X3 L' w0 p& w2 f
2.3、写入
写入之前必须擦除,这里和NorFlash操作是相同的

' u6 I  |; z& s- p) k9 x
复位后,Flash控制器寄存器(FLASH_CR)不允许写入的,去保护Flash闪存因为电气原因出现的以外操作,以下是解锁的步骤

, C. b' Q* P, @% `4 v' f8 r
  • 1、在Flash 密钥寄存器(FLASH_KEYR) 中写入KEY1 = 0x45670123
  • 2、在Flash 密钥寄存器(FLASH_KEYR) 中写入KEY2 = 0xCDEF89AB
      b2 I- v4 U/ {: }9 r$ h
1 n1 g/ _3 j! x0 T
将FLASH_CR 寄存器中的LOCK 位置为1 后,可通过软件再次锁定FLASH_CR 寄存器
  e/ D8 P  y4 z" U1 v# B) S- K
ST提供了库函数

' G- S# u3 f7 r( f
  1. & ?. x" R5 u  h) `' T1 n( ?
  2. FLASH_Unlock();//解锁
    ! C1 r* H% A4 U, E( Q. q" Y+ u
  3. FLASH_Lock();//重新上锁
复制代码
3 s% |% Q! h- [+ U" q

6 v. m5 s/ i% i: v7 I
备注:
8 H% s5 R/ r. }5 x8 a
当FLASH_SR 寄存器中的BSY 位置为1 后,将不能在写模式下访问FLASH_CR 寄存器。BSY 位置为1 后,对该寄存器的任何写操作尝试都会导致AHB 总线阻塞,直到BSY位清零
$ R4 z  K$ Q; j4 ?
这要求我们在写入前必须判断下FLASH_SR寄存器中的BSY位。
, W1 _* ^, q1 N4 g
ST提供了对用的库函数

  1. : \( r4 o1 d2 ]7 s3 J5 d. X* a
  2. FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR| FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
复制代码

/ R7 k; \+ G) ]5 d3 K% _
写入步骤
2 ~% \4 F+ |2 U' n
  • 1、检查FLASH_SR 中的BSY 位,以确认当前未执行任何主要Flash 操作
  • 2、将FLASH_CR 寄存器中的PG 位置1。
  • 3、通过不同的位宽对指定地址写入
  • 4、等待BSY 位清零: b' ?  M4 X) C6 o0 H% \- c+ G
$ d- h- Z2 H1 ?* t& h' Z
对于写入接口,ST提供相应的库函数,提供了8位,16位,32位的操作,因为我们是3.3V电压,所以使用32位写入接口
  1. FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)9 D* A9 ^; T/ r- ^- @, P
复制代码
5 {2 F3 ^. P7 O
2.4、中断
如果对于写入要求较高,可以使能中断,对于写入完成,写入错误都会有响应的中断响应。我也没有详细研究,参看Flash编程手册的15.5章节

8 C( z6 \; D/ W03Flash保护

& K/ ?  N2 R" _% m6 i; [
3.1概述
Flash具有读写保护机制,主要是用过选项地址实现的。还有一次性编程保护

0 ^8 r2 f+ Y1 \# j2 Q! y7 S
4.png
这讲述了选项字节的构成

. s0 Y9 }9 h$ I3 S8 A1 P
5.png
用户修改选项字节

6 M' ]- {7 c4 F; G) I- o2 {
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:
" I( M4 Z& J+ n. \
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.
& d6 \) A8 N4 t1 r
这个上面讲述的解锁Flash相同,就是要写入不能的数值
" T" k% z1 Q) {$ D
ST提供相应的库函数

) u& s$ [  g5 g, \$ Z8 c6 ?
  1. ; ]6 S1 D- p2 X$ G; n
  2. void FLASH_OB_Unlock(void)
    ; d* q9 C5 X3 Q- v; s; U6 E
  3. void FLASH_OB_Lock(void)
复制代码
) B. c( P7 M8 s$ P; P4 A
! _1 I+ |* R6 {5 L) E" ^+ V+ K
修改用户字节的步骤

" \9 j* ^: K! {5 b
  • 1、检查FLASH_SR 寄存器中的BSY 位,以确认当前未执行任何Flash 操作
  • 2、在FLASH_OPTCR 寄存器中写入所需的选项值
  • 3、将FLASH_OPTCR 寄存器中的选项启动位(OPTSTRT) 置1
  • 4、等待BSY 位清零- [* ?; o% Q% L( P/ m# V! s% W

) f% Z- e8 K  C" j- J

% A( v  m5 @( a: J* P8 o  T6 U
3.2 读保护
从上面概述中得知,Flash读保护共分三个等级
1 等级0:没有保护
3 @7 w, P6 \) N6 H% k- i
将0xAA 写入读保护选项字节(RDP) 时,读保护级别即设为0。此时,在所有自举配置(Flash用户自举、调试或从RAM 自举)中,均可执行与Flash 或备份SRAM 相关的所有读/写操作(如果未设置写保护)。

# C" M9 J0 K. @( |" Q! V8 ^! Z
2 等级1:闪存读保护9 E7 n* |- c* W9 X/ _3 U
这是擦除选项字节后的默认读保护级别。将任意值(分别用于设置级别0 和级别2 的0xAA和0xCC 除外)写入RDP 选项字节时,即激活读保护级别1。设置读保护级别1 后:
- d3 n9 J5 N3 ?' [
-在连接调试功能或从RAM 进行自举时,将不执行任何Flash 访问(读取、擦除和编程)。Flash 读请求将导致总线错误。而在使用Flash 用户自举功能或在系统存储器自举模式下操作时,则可执行所有操作

$ J; Y$ c; J- a0 y$ J. f$ l; l% Q
-激活级别1 后,如果将保护选项字节(RDP) 编程为级别0,则将对Flash 和备份SRAM执行批量擦除。因此,在取消读保护之前,用户代码区域会清零。批量擦除操作仅擦除用户代码区域。包括写保护在内的其它选项字节将保持与批量擦除操作前相同。OTP 区域不受批量擦除操作的影响,同样保持不变。

) [1 u) B0 Z# H" }: C
只有在已激活级别1 并请求级别0 时,才会执行批量擦除。当提高保护级别(0->1,1->2, 0->2) 时,不会执行批量擦除。.
3 等级2:禁止调试/芯片读保护2 @8 i8 M, {+ w9 A7 _  H  a
注意:

2 ?+ _! U; Y+ Z) v
在注意中写道,如果使能了等级2的读保护,永久禁止JTAG端口(相当于JTAG熔丝)ST也无法进行分析,说白了就是没办法再debug了,目前我没有使用到这个水平的读保护
读保护库函数
  1. void FLASH_OB_RDPConfig(uint8_t OB_RDP)
复制代码

. ~$ t( g/ ~  [4 K  e6 |
查询读保护状态库函数
  1. FlagStatus FLASH_OB_GetRDP(void)
复制代码

* ~; I  O6 G  \* C2 V
3.3 写保护
Flash 中的用户扇区(0到11)具备写保护功能,可防止因程序计数器(PC) 跑飞而发生意外的写操作。当扇区i 中的非写保护位(nWRPi, 0 ≤ i ≤ 11) 为低电平时,无法对扇区i 执行擦除或编程操作。因此,如果某个扇区处于写保护状态,则无法执行批量擦除。; [0 n0 @- U# T& w

; B0 T5 n4 h, ?* V0 f+ l
" K" G' i& j/ P# V+ H
如果尝试对Flash 中处于写保护状态的区域执行擦除/编程操作(由写保护位保护的扇区、锁定的OTP 区域或永远不能执行写操作的Flash 区域,例如ICP),则FLASH_SR 寄存器中的写保护错误标志位(WRPERR) 将置1。
( @5 H% }$ h4 k# r/ c1 r" u7 l$ a, O. @- L3 q. p3 O1 A

1 E4 W- g7 g* a) ~! v& [
写保护库函数

  1. . x1 x7 N& L6 ^9 M! g7 {0 X
  2. void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState)
复制代码
' s9 U7 M" d0 j

. i7 e( T' R3 v' V
查询写保护状态库函数

5 w+ L" N6 a+ K$ C* \
  1. uint16_t FLASH_OB_GetWRP(void)
复制代码
04一次性可编程字节3 Y+ y4 A: W  s- E5 h7 ?
没有使用过,使用了芯片就废了吧,没有做过这个等级等保护,可以参看Flash编程手册的2.7章节

, N/ a, n+ O9 `0 s$ \& ~) Q/ r/ F7 z
05 代码
  s2 i; v, \! G6 t7 d
关于读写保护代码如何调用的问题,在stm32f2xx_flash.c文件中有调用说明.

9 l: c$ H3 a4 T* O% o/ E5 k
6 O) v7 @# T& o5 q' `/ J
赞 收藏 评论0 发布时间:2020-9-9 10:13

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版