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

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

[复制链接]
STMCU小助手 发布时间:2021-11-10 18:02
STM32G070的flash读写问题% @! k/ Y  B: ?
STM32G070xx的flash分布如下图,打算将Page 63用于保存用户数据。
/ r( m3 R7 g/ V8 W& K. L* f
9 W- Y8 m% l3 `* d
2019102511214233.png
( U* ^- p  c! j+ T  S

7 @1 F/ \( [  t问题1 y- f- k# e! O& K
开始一直出现flash写入失败,从返回码来看是FLASH_FLAG_PGSERR,一直找不到原因,代码如下:
8 }, c' t0 u6 z$ r  g
! V# k  w  e& a7 I3 I$ T4 C) E1 D
  1. #define ADDR_USER_DATA  0x0801F800& [6 W8 d! m! T6 g4 z7 S4 r

  2. ' ?$ Q1 m% J7 x+ }4 U
  3. HAL_FLASH_Unlock();
    , ?* {% W6 d3 c9 l
  4. FLASH_PageErase(63);
    ' w' m/ Y4 ^& E5 J0 u. u( E5 t3 r
  5. ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, ADDR_USER_DATA, (uint64_t)data);
    $ b' G- ?% y9 C
  6. HAL_FLASH_Lock();$ q0 G& e: s1 r: v3 A' u$ [

  7. . K; E+ c% n( b/ [9 G
  8. if (ret != HAL_OK)
    . V6 O3 w% d& I- E* W- ?1 ^
  9. {5 l) y' O% L3 c4 k# @& z+ Q
  10.     printf("\r\nuser data save failed, ret = %u, flash err = 0x%x", ret, HAL_FLASH_GetError());
    # b! }7 Z. ~" M
  11. }
复制代码

. M7 l& U* o5 I$ e7 g2 `  j# j0 d2 }
2019102511181630.png

. \5 T# Q5 j& \) V' N, q  i8 ^
: R9 D' j) s% z' j  {后来终于在community.st找到了答案:3 L7 V1 ^* [" T; G  c. o

$ l# N+ q) v; c+ m& ?5 J, O1 w8 Q
20191025112810625.png

' o5 R# a# T& v: S& L& H1 U' M
5 R: k- G( X8 K: ^% h2 X3 p( h, d2 n3 p, GSTM32G070 flash驱动代码
1 Y2 J% i$ z- v! q' m, `好了,话不多说,直接上最终的代码,亲测有效:
/ K$ j4 c2 g$ N7 d3 d6 O+ _
& K4 @: A* j& Y7 w$ C
  1. HAL_StatusTypeDef flash_write(uint32_t address, uint64_t data)
    ; q* A& Y3 n6 a8 @/ _: O
  2. {, h# g: {7 b8 l1 x0 y2 K* I
  3.     HAL_StatusTypeDef ret = HAL_OK;
    2 p  b. }: |( H6 g: G. T

  4. 1 V& Y( L. z  ?
  5.     HAL_FLASH_Unlock();' }( {; n) _" J) g% G! I
  6.     ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, address , data);
    & c9 g( O  h% I" _' W3 N
  7.     HAL_FLASH_Lock();
    & `, }7 K. b) v1 Y, r

  8. " D* m* ~0 D7 a5 @
  9.     return ret;( U: R6 Y+ A! t1 P6 V, O) M' ?8 j
  10. }
    , q8 ]& O0 V2 y+ M# }+ W& M* h
  11. 6 H! [; {+ q$ }6 J0 l; r4 B
  12. void flash_page_erase(uint32_t page)8 X# j0 a1 B1 d* r& o3 J
  13. {* m# Z# I( f/ E( X
  14.     HAL_StatusTypeDef test = HAL_FLASH_Unlock();
    8 _# w/ b0 P; H
  15. 4 U, @: `& B  H
  16.     test = FLASH_WaitForLastOperation(1000); //1s timeout
    + z- V* |3 M& g  B; z
  17.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);5 J) c6 B. i' j# S: d; F
  18.     FLASH_PageErase(page);- L+ [) ~2 W7 }) \- ^9 x4 j* v9 U
  19.     test = FLASH_WaitForLastOperation(1000);
    : j3 G1 e5 d5 v; g) _' Q! l
  20.     CLEAR_BIT(FLASH->CR, FLASH_CR_PER);( L: v9 I0 @* n5 d: F
  21. , _3 F' n1 D) ]1 a
  22.     HAL_FLASH_Lock();
    9 B+ V8 P1 B5 E6 K
  23. }, W+ e& T) p& g$ B! k

  24. ; I0 ?" S, t8 h$ }6 t1 \( h
  25.     /* 调用上述两个函数即可实现flash的擦除和写入 */7 {0 |1 X  R9 P
  26.     flash_page_erase(63);
    4 ~! Y$ A$ A3 Y7 s1 D$ w
  27.     ret = flash_write(ADDR_USER_DATA, (uint32_t)u_data);, @1 l' ?$ v4 ~  S

  28. * m& w  ^  r3 N4 G" ?
  29.     /* 读取的话就简单了,直接使用地址即可 */4 Z# Q# e" t% J' M$ W
  30.     uint32_t u_data1 = 0;
    ( p: w; `( p, E4 Y4 Z+ ^3 s6 u. t
  31.     u_data1 = *((uint32_t*)ADDR_USER_DATA);
复制代码
. o$ n5 C1 r4 n2 H8 Q. t
注意点
) D. f! j# ]# N$ l: Y3 ~$ ^' h7 y2 A' t# vflash_write每次写入的是一个uint64_t类型的数据,其最终调用的函数为:$ g5 A, c1 U% w7 B* [) r( p

  1. 8 b% X  P& A/ {8 `) q5 C; E, I  P1 f
  2. static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)8 l+ c. R& V$ p$ G
  3. {, U9 L4 w! S  `( a! G, I
  4.   /* Set PG bit */9 w/ z# `- R" t! W2 [
  5.   SET_BIT(FLASH->CR, FLASH_CR_PG);& K2 h/ t2 `3 j. p/ j6 |
  6. ) D# n6 D* E0 e  b9 [" t
  7.   /* Program first word */4 G9 L! ~" X# i- g4 A) t& |) ^0 c* Z6 {
  8.   *(uint32_t *)Address = (uint32_t)Data;0 ^% @4 \6 J# K
  9. 0 j! ]4 r! Q# @. G/ s0 ~8 Y3 W; e
  10.   /* Barrier to ensure programming is performed in 2 steps, in right order' }. u5 S1 q; S5 g$ J/ B
  11.     (independently of compiler optimization behavior) */
    : h- y; M) f# }9 V/ R4 ~- ^' e6 }
  12.   __ISB();6 V* s- d9 u  Z- _$ ?7 r: A

  13. 6 Z& P/ u- M6 i
  14.   /* Program second word */
    % S% u3 ], }: |3 _# f
  15.   *(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U);) d  T! A. T" V8 s3 Q& o/ z; _: n
  16. }
复制代码

: m  [% U, w6 u& c1 L' K& l该函数每调用一次,其实是写入了2个word,所以在使用时需要注意Address的递增。% p: O7 w' _4 H( g# o
/ d7 \* K& l: N; B  w6 W
/ r9 K( [/ y0 \/ c+ L' b
20210405170242660.png
20210405170242660.png
赞 收藏 评论0 发布时间:2021-11-10 18:02

举报

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