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

STM32学习笔记 | 片内FLASH读写失败问题分析

[复制链接]
STMCU小助手 发布时间:2021-3-9 13:04
STM32学习笔记 | 片内FLASH读写失败问题分析

& A; D" v4 a% j7 s( {8 Y+ |0 i- Y
FLASH,指Flash Memory,是一种非易失性存储器(闪存),掉电能正常保存数据。
STM32的存储器通常包含内部SRAM、内部FLASH,部分系列还包含EEPROM。其中FLASH通常用于存储代码或数据,可被读写访问。

2 v; V1 a3 H: ~% ]8 H
STM32 FLASH 基础内容

6 l& J0 O- q1 W2 S0 c& d" ~
STM32的FLASH组织结构,可能因不同系列、型号略有不同。比如大家熟悉的STM32F1中小容量一页大小只有1K,而F1大容量一页有2K。
还比如有些系列以扇区为最小单元,有的扇区最小16K,有的128K不等。
本文主要结合F4系列来描述关于FLASH的相关内容。

' N4 a& k  f3 g! f
1.Flash 结构

1 U' e' S: A' P% ~! ]
通常Flash包含几大块,这里以F40x为例:
※       主存储器:用来存放用户代码或数据。
※       系统存储器:用来存放出厂程序,一般是启动程序代码。
※       OTP 区域:一小段一次性可编程区域,供用户存放特定的数据。
※       选项字节:存放与芯片资源或属性相关的配置信息。

8 [! J; k/ |1 U% [
1.1.jpg

& P' @8 q$ X9 h8 z5 H4 p! H
2.Flash 常规操作

* g$ }2 P5 |/ |  C/ v- ?) R( C
Flash 读、写(编程)、擦除:
※       128 位宽数据读取
※       字节、半字、字和双字数据写入
※       扇区擦除与全部擦除
(提示:不同系列可能存在差异,比如还有字节读取,页擦除等)
Flash 读、写保护:通过配置选项字节实现。

. c& P! ?9 c( Y; F9 E, _9 W
3.Flash 容量
1 ]- A/ L3 U7 V/ z
STM32的Flash容量出厂已经决定,可根据型号得知容量大小。
! x. V7 _3 K8 E. Y2 F4 e
1.2.jpg
  j$ A+ I# @( t/ p* D1 W
4.存储器端格式

+ O. x- H$ E) E+ [3 w
目前STM32存储器组织结构默认为小端格式:数据的低字节保存在内存的低地址。
更多内容请查阅芯片对应的参考手册。
4 q' z- c8 Q4 |: `; R
FLASH 选项字节
/ X; z5 E2 r5 \, I) q' w7 f4 d' p' ~
STM32内部Flash具有读写保护功能,想要对Flash进行读写操作,首先要去除读写保护,读写保护通过配置选项字节完成。
配置选项字节,常见两种方式:1.软件编码;2.编程工具;

% P* a  l/ |; C. a
1.软件编码
0 e  C- ~8 S6 z2 a
比如STM32F4系列标准外设库库提供函数:
2 c1 `# ~6 v; N" a% R. h) P) g7 m* i
  1. <font face="微软雅黑">void         FLASH_OB_Unlock(void);: X4 q7 n6 h( u) L& q0 z( `
  2. void         FLASH_OB_Lock(void);
    , [5 l0 A# |9 f1 b
  3. void         FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState);
    5 U6 n  ^9 s3 F/ D; A0 F$ Y4 B
  4. void         FLASH_OB_WRP1Config(uint32_t OB_WRP, FunctionalState NewState);
    5 {5 @8 Z$ D* H5 N, U* ?
  5. void         FLASH_OB_PCROPSelectionConfig(uint8_t OB_PcROP);
    , q6 l4 }6 b+ Y! H7 ^) F- D
  6. void         FLASH_OB_PCROPConfig(uint32_t OB_PCROP, FunctionalState NewState);5 }9 s$ N$ y4 w$ P
  7. void         FLASH_OB_PCROP1Config(uint32_t OB_PCROP, FunctionalState NewState);9 c# T& h& i# r4 L4 o+ I
  8. void         FLASH_OB_RDPConfig(uint8_t OB_RDP);
    5 W0 M" B, T& h  ^! y/ U1 \- O
  9. void         FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY);
    ( a' Q5 |9 o. s1 f+ W
  10. void         FLASH_OB_BORConfig(uint8_t OB_BOR);
    4 x# i" H. B2 ]0 U* B: r
  11. void         FLASH_OB_BootConfig(uint8_t OB_BOOT);) D* j: A# [- ~* ?$ {7 A; c; U' ]
  12. FLASH_Status FLASH_OB_Launch(void);
    : n6 R( ?3 g9 `; F; ^
  13. uint8_t      FLASH_OB_GetUser(void);
    / `7 }5 `7 i* j& |! V5 P
  14. uint16_t     FLASH_OB_GetWRP(void);  u1 o) m5 ?# c
  15. uint16_t     FLASH_OB_GetWRP1(void);! E7 s$ I4 k' {
  16. uint16_t     FLASH_OB_GetPCROP(void);: u. M" Y$ W9 ?3 e% x* i+ V7 R* S
  17. uint16_t     FLASH_OB_GetPCROP1(void);
      W$ l5 Q% A6 S
  18. FlagStatus   FLASH_OB_GetRDP(void);
    4 ]/ H" u  p1 ~# J  `$ o- A) i
  19. uint8_t      FLASH_OB_GetBOR(void);</font>
复制代码

1 E( q% Z; B* e% L% c; c
软件编码通过调用这些函数接口就可以配置选项字节。
/ S0 [3 X) Y; X& ^# M2 D" o8 f
2.编程工具

5 B7 y, k! \" v  O
比如STM32CubeProg编程工具:
, @) I' \; b8 P' Q! q8 V
1.3.png
( w+ W) s/ g3 j
配置STM32选项字节,还可通过ST-LINKUtility、STVP等类似工具进行配置。
提示:不同型号的STM32选项字节可能略有差异。

6 z3 X" |5 n- A# E
FLASH 读写擦除操作
1 C7 x+ T+ R* B! s
STM32内部Flash和其他外部Flash类似,支持读、写、擦除等常规操作。对内部Flash操作之前通常需要解锁、去保护等操作。
比如:

% ]1 V- m* ?3 p2 H& l6 Z4 d
  1. <font face="微软雅黑">FLASH_OB_Lock();2 t! K7 J' p9 Q% w$ _9 f5 c
  2. FLASH_OB_WRPConfig(OB_WRP_Sector_All, ENABLE);
    * \0 x- `% I. H& r: N; W- z/ a
  3. FLASH_OB_PCROPConfig(OB_PCROP_Sector_All, ENABLE);</font>
复制代码
% m. G9 g! Y. X5 N- T- n+ {
1.读数据
' Q+ ^; w2 V) P0 k( I: U
读取内部Flash数据通常有两种方式:
※       通过程序(编码)读取
※       通过外部(编程)工具读取

( M8 u' v: Y( d7 C8 Z9 q
程序(编码)读取:
  1. <font face="微软雅黑">uint32_t uwData32 = 0;uint32_t uwAddress = 0x08001000;uwData32 = *(__IO uint32_t*)uwAddress;</font>
复制代码
外部编程工具读取:
读取前提:没有读保护,设置好读取地址,长度、数据宽度等。

1 Z' X3 [5 T5 u6 f" |( G5 w
1.4.png
6 t% p% d$ A: I% |  R
2.写数据
# k- B1 k. C: ?$ v7 o7 a1 y
往STM32内部Flash写数据和读数据类似,但写数据地址不能有数据,也就是写之前要擦除数据。
所以,相对读数据,通常写之前需要一些额外操作,比如:
  1. FLASH_Unlock();3 W  S2 W+ V& K+ N
  2. FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | 1 r+ B/ Z% e$ ^7 M, x" R2 V1 _- h
  3.                 FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
复制代码

) I- S/ |1 S% g8 I
通过工具写数据,就是我们量产时说的下载数据,正式一点说法叫编程。
) I& ]) y5 x! ?1 K& `+ z8 \" W
3.擦除数据
- r; F% f1 R0 x+ \8 _
擦除数据通常分擦除页、扇区、整块,擦除时间也因型号不同、速度不同有差异。
提示:该部分内容建议参考官方提供的Demo(标准外设库和HAL都有基本例程)
( ~( H- r/ F2 [$ ~/ Y  o6 L& V+ R
FLASH 常见问题
& R. k& G8 }$ K; T5 ^! j: y6 A6 ~' o) B
STM32内部Flash主要用途是存储程序代码和数据。操作内部Flash要慎重,一旦操作不当就有可能会破坏整个程序。
; Z* r- n# @) m2 q' A  R) q
问题一:编程(写数据)地址非对齐
写数据时,我们要指定写入的地址,如果写入地址为非对齐,则会出现编程对齐错误。
比如:遵循32位(4字节)地址对齐,你的地址只能是4的倍数。0x08001000正确,0x08001001错误。
提示:不同型号对齐宽度可能不同,有的32位、有的128位等。
解决办法:通过“取余”判断地址。
+ K+ a( ?# n8 W& _& }, M- t
问题二:编程地址数据未擦除
写数据之前需要擦除对应地址数据才能正常写入,否则会出现失败。
我们擦除数据通常是页,或扇区,写入某个地址数据,就可能影响其他地址的数据,如果直接覆盖就会出现问题。
解决办法:通常的做法是读出整页(或扇区)数据并缓存,再擦除整页,再写入。
- E2 s. F7 ?% h9 ~2 I7 C
问题三:擦除时读取数据
STM32内部Flash在进行写或擦除操作时,总线处于阻塞状态,此时读取Flash数据就会出现失败。【双BANK模式除外】
解决办法:通过标志判断写/擦除操作是否完成。

/ D7 S( J! r+ o1 g( X6 e# P4 x
问题四:电压不稳定写入失败
处于外界干扰较大的环境,供电就有暂降的可能,而对STM32内部Flash进行操作时,如果低于特定电压就会出现编程失败。
操作Flash的最低电压既与工作频率有关,也与STM32型号有关(具体需要看数据手册)。
解决办法:通过完善硬件电路保证电压稳定。电源电压不够或不稳导致隐患往往不易觉察!!
& f+ P- d9 B' s7 ^
复盘一下
▼FLASH 基础内容:结构、常规操作、容量、大小端格式;
▼FLASH 选项字节:通过软件编码和编程工具配置;
▼FLASH 读写擦除操作:常规程序读写操作、工具的读写操作;
▼FLASH 常见问题:编程地址非对齐、数据未擦除、擦除同时读取数据、电压不稳定写入失败。
% |. \/ p; t4 \# i( l
文章出处: STM32
8 @0 I2 \' r% ^  j5 s) h, r
赞 收藏 评论0 发布时间:2021-3-9 13:04

举报

0个回答

所属标签

相似技术帖

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