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

【经验分享】STM32G070进行flash读写操作

[复制链接]
STMCU小助手 发布时间:2021-11-10 18:02
STM32G070的flash读写问题1 a9 n! L9 P$ U, L
STM32G070xx的flash分布如下图,打算将Page 63用于保存用户数据。# ~; d. E3 W5 {' U! X

' {0 g9 Y$ _" _* p1 y! @7 K, q) @
2019102511214233.png

3 R2 m) {, Q: s5 _2 K0 B( F2 B$ @8 _+ M
问题
/ u$ \. S& I0 ]/ n3 T; i- B& e3 C开始一直出现flash写入失败,从返回码来看是FLASH_FLAG_PGSERR,一直找不到原因,代码如下:
+ I1 ^+ k5 `" S0 K. d; c" F2 v0 V0 e
  1. #define ADDR_USER_DATA  0x0801F800: s; A" S% s: c
  2. % Q6 a. I1 K: w: @( t' X1 ]
  3. HAL_FLASH_Unlock();8 P0 I$ I. m: M' P& R8 u
  4. FLASH_PageErase(63);( w- R- w9 h# x( z
  5. ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, ADDR_USER_DATA, (uint64_t)data);9 ]' E5 U2 k2 H4 p
  6. HAL_FLASH_Lock();
    * C9 ]7 L1 ?7 s$ j3 Y6 E
  7.   q" |3 |) u* m2 l) u4 c% e: ?
  8. if (ret != HAL_OK)
    & C- o" [) p7 a0 d/ Z! i3 z
  9. {
    2 q1 y# G* E" v' Y/ l/ q
  10.     printf("\r\nuser data save failed, ret = %u, flash err = 0x%x", ret, HAL_FLASH_GetError());
    3 r& N2 H9 Q3 E0 o) a! e! S
  11. }
复制代码

# z7 x+ L+ Q, }- T9 P# D9 E/ k
2019102511181630.png
( ]8 c% D7 h) a

' e6 b; {( r8 c后来终于在community.st找到了答案:
6 [' J0 C% X- ]0 x+ `' U
/ ^* I$ ]/ ~6 A$ Y) ]2 S  J7 N& C
20191025112810625.png

, o9 @  }3 h( u, h% q0 j
/ u5 A% I5 {3 S0 J2 H' n$ l% P+ s$ [STM32G070 flash驱动代码
; u. f9 U) R4 X- _" \好了,话不多说,直接上最终的代码,亲测有效:9 {4 v: i! ]; ~. j4 v( r

* r% V4 e: q; f( i4 z+ p! Y
  1. HAL_StatusTypeDef flash_write(uint32_t address, uint64_t data)
    ) a) a% B' b0 R' p6 V' Y
  2. {: ?4 O5 R9 Z# v! \, O8 O
  3.     HAL_StatusTypeDef ret = HAL_OK;
    - n6 D) ~* V6 ~5 z5 F& l0 C( O1 Z- c
  4. # y! [: c. d8 E4 ?# r! g& ]1 n
  5.     HAL_FLASH_Unlock();
    ( v) {6 {4 K* R0 v) }7 M# |9 F2 n
  6.     ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, address , data);1 _5 ^" z6 z3 z
  7.     HAL_FLASH_Lock();
    % H, y, N/ f; Q, ]0 Z
  8. 5 a) ^8 ]9 V; D- a7 o
  9.     return ret;
    : j( m* B6 ]- s7 C
  10. }& M) B' O7 l  b  @2 q1 y3 s
  11. $ V2 l2 C" H, n, X/ U4 z  e  U
  12. void flash_page_erase(uint32_t page)# h+ B5 L5 o) [" t
  13. {" B" c. ^& ~( c
  14.     HAL_StatusTypeDef test = HAL_FLASH_Unlock();
    * E: B( c0 I9 [( q7 S3 |

  15. * e; t& @  L0 p; G
  16.     test = FLASH_WaitForLastOperation(1000); //1s timeout
    3 l  T& M8 t% Q- l6 ?6 h% q; S
  17.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
    9 }- Z% z4 J8 c3 F  ?0 U; Q1 i
  18.     FLASH_PageErase(page);: k3 `8 D* Y1 `* E5 \9 [. {5 D+ I
  19.     test = FLASH_WaitForLastOperation(1000);8 W4 _1 S+ A, ~/ |
  20.     CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
    ( q0 F' s/ Q$ G8 G1 k
  21. 0 Z, }  P' u6 \. P: I
  22.     HAL_FLASH_Lock();
    1 f0 v1 a5 G9 _  p* M: l# V1 I8 X! d0 p
  23. }7 L' ^, O- S0 d* ~/ ~
  24. ( H4 W$ q' U* f/ {- P+ {
  25.     /* 调用上述两个函数即可实现flash的擦除和写入 */
    & X' h3 {! f8 Z2 H  [- a
  26.     flash_page_erase(63);! ]8 s: n( O1 I. F7 L% c
  27.     ret = flash_write(ADDR_USER_DATA, (uint32_t)u_data);
    + c: y  S! w8 p2 ]) @9 k" z
  28. ) c. \& t! o' D4 y- W9 ]
  29.     /* 读取的话就简单了,直接使用地址即可 */
    2 \) B7 R2 \; E) M3 R7 p
  30.     uint32_t u_data1 = 0;
      v; o% `& Q: d  ]3 q  D% H
  31.     u_data1 = *((uint32_t*)ADDR_USER_DATA);
复制代码
3 A: s5 Q6 [2 D2 {
注意点
6 Q' K- K/ q4 d1 X3 g! xflash_write每次写入的是一个uint64_t类型的数据,其最终调用的函数为:( }6 Z+ J7 G8 B1 ?1 O
  1.   h( B* V5 B4 t( |& V$ n: f5 D& P9 K
  2. static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
    $ w& X% \' E* d
  3. {
    9 G4 O2 k% S' h' A0 `4 B0 E
  4.   /* Set PG bit */; Y7 c* H4 ~/ O7 g
  5.   SET_BIT(FLASH->CR, FLASH_CR_PG);  d2 X& T3 o  W% N# p$ J0 n+ R7 q

  6. $ e! F/ {8 ]% g6 l  f
  7.   /* Program first word */& H6 k# o/ ~8 r( {/ v
  8.   *(uint32_t *)Address = (uint32_t)Data;
    9 ~6 c& {+ Z$ B6 y

  9. 4 q; ~1 ^+ n$ i: F+ m+ X
  10.   /* Barrier to ensure programming is performed in 2 steps, in right order' o* _$ h3 k7 B! U
  11.     (independently of compiler optimization behavior) */; W$ M" q' g% ^7 ^/ l! o# B' ~- Y
  12.   __ISB();* ^; B8 O# g- \+ t' q. K  ^. i' K

  13. - [# U. m. `2 w' U7 }
  14.   /* Program second word */* s# h( D3 Y/ Y" k3 c4 T4 h
  15.   *(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U);
    , `6 g: Z! o8 v" y6 h
  16. }
复制代码
0 I+ s0 @' p4 d: n% V
该函数每调用一次,其实是写入了2个word,所以在使用时需要注意Address的递增。* z# ]: W+ A; T3 r8 }

7 a% Q# q( w; S5 i) }, a3 x- Z* |7 p9 A# k& S9 G, `) m, ~1 p" n' t
20210405170242660.png
20210405170242660.png
收藏 评论0 发布时间:2021-11-10 18:02

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版