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

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

[复制链接]
STMCU小助手 发布时间:2021-11-10 18:02
STM32G070的flash读写问题
+ W8 }! c  Z2 L3 r! s, m: Y2 L7 J1 B# |STM32G070xx的flash分布如下图,打算将Page 63用于保存用户数据。4 O, b  S& m4 M3 d" {" h

/ B+ ^! E# n8 S' h5 G! K
2019102511214233.png
. m: O) T% }! g0 P, ~; z5 L5 R4 y* n
( Q& v" X& O' Z" x' v
问题
; Y) g, G1 u5 Q; n( [8 a开始一直出现flash写入失败,从返回码来看是FLASH_FLAG_PGSERR,一直找不到原因,代码如下:
6 T2 V5 b: U% |, Y: H. f- T
+ D. c$ ?; u2 U* C6 `
  1. #define ADDR_USER_DATA  0x0801F800; C' S5 m0 n  q( Y% e
  2. : k3 H( d) ?$ _* O% |9 A4 |
  3. HAL_FLASH_Unlock();" l! Y  F: N; d% m# Z
  4. FLASH_PageErase(63);
    8 p( x- j# e( B; |  H% \
  5. ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, ADDR_USER_DATA, (uint64_t)data);+ C! ~$ }4 }$ g3 m- t9 m0 u
  6. HAL_FLASH_Lock();
    + I# W; _+ I6 `

  7. % L2 @* ?9 b, \0 y. Q$ a2 e9 c5 v" q
  8. if (ret != HAL_OK)& B7 f  ^  u8 |
  9. {, C/ F9 V' @7 V1 Q7 q7 A+ a# G
  10.     printf("\r\nuser data save failed, ret = %u, flash err = 0x%x", ret, HAL_FLASH_GetError());
    * m& L6 C0 l3 q
  11. }
复制代码
" p* f: N! ^6 k  ~  ]/ S3 e: L
2019102511181630.png
. ~& g# R; h( ^

% x. V" O+ \" r0 L  n! }4 S( h7 ~后来终于在community.st找到了答案:
7 Y3 r3 U0 a' S+ P+ t# a% P7 }
. {2 U# Z1 \" @
20191025112810625.png
% c, l8 \, G. {' [0 E3 w# H

* L0 o: z' T0 ?* a& c4 XSTM32G070 flash驱动代码! X1 t$ E) [6 S; i0 C0 O0 l
好了,话不多说,直接上最终的代码,亲测有效:
8 B; O2 T! s1 i* l5 V5 \+ Y/ b/ N" g+ @9 s  `/ l7 F0 `
  1. HAL_StatusTypeDef flash_write(uint32_t address, uint64_t data)
    0 |2 Q( }- C+ ?7 H* Q
  2. {
    " N2 ]) p4 ]& h* v+ X
  3.     HAL_StatusTypeDef ret = HAL_OK;; b/ T& d, w6 V  A
  4. 5 n; Y6 g$ P2 e; w6 m# c
  5.     HAL_FLASH_Unlock();# z& o( h, ?" R$ B
  6.     ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, address , data);
    & t$ V, M4 `" `
  7.     HAL_FLASH_Lock();: Y* d/ O! v1 d

  8. : b: \2 h$ h$ u4 M, s: N
  9.     return ret;
    + p, W  n$ ~, f% Q) F* J
  10. }
    5 n- [9 J. G$ X5 t7 w% a
  11. 8 V4 ?& l* L' J* F8 x; U( f/ ?$ r
  12. void flash_page_erase(uint32_t page)
    2 r" A/ F: L6 M
  13. {1 s/ o$ N8 x/ u2 P
  14.     HAL_StatusTypeDef test = HAL_FLASH_Unlock();3 f+ U2 b) D8 e" C

  15. - D4 H5 ]+ Z1 N9 \: D( j9 m8 R
  16.     test = FLASH_WaitForLastOperation(1000); //1s timeout
    % n( f3 K7 R( T, x: y4 V, Y3 m, F; _
  17.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);3 \' I& r2 M, O6 g8 K; q+ @: t! E
  18.     FLASH_PageErase(page);
    ; l3 u4 i! }* ]9 J, D
  19.     test = FLASH_WaitForLastOperation(1000);
    ' @' Q% i( Z9 e0 Z1 G' }# s  t2 ]2 K
  20.     CLEAR_BIT(FLASH->CR, FLASH_CR_PER);! F  V  c/ r5 _7 w6 _1 U% U
  21.   T( I) L, C+ i+ g; T) f, n
  22.     HAL_FLASH_Lock();3 a5 Y9 e: S7 d, s+ ]. [
  23. }
    # M" X3 w/ o. c  Z, }) o& F
  24. & B1 r+ e* Y0 m, G2 n% G% r
  25.     /* 调用上述两个函数即可实现flash的擦除和写入 */
    * J1 q. T8 L' v  F3 G4 _$ m, y
  26.     flash_page_erase(63);2 [9 A1 S+ l# t2 Z) N
  27.     ret = flash_write(ADDR_USER_DATA, (uint32_t)u_data);
    . H  E9 f. Q0 l% |( h
  28. . `2 ^/ V4 ^/ Z2 i
  29.     /* 读取的话就简单了,直接使用地址即可 */2 P; ^' M# X. x& O9 C' Q
  30.     uint32_t u_data1 = 0;& _7 L6 W( f' P1 |
  31.     u_data1 = *((uint32_t*)ADDR_USER_DATA);
复制代码
( \& U% K$ w" C* }, ]; ~
注意点8 C9 Z* S% u* p9 X
flash_write每次写入的是一个uint64_t类型的数据,其最终调用的函数为:( Q, T0 P* T8 x- J+ \. x. k

  1. * J; ^6 J& V3 r, b2 y
  2. static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)/ W- p( I4 }; Z7 s; u* d0 P. f# G/ N
  3. {
    2 t7 K) m5 R" M- E
  4.   /* Set PG bit */+ @* a% ?! Y0 `8 ~. h/ e6 f( S
  5.   SET_BIT(FLASH->CR, FLASH_CR_PG);
    , ]/ d0 c9 u) m1 k! e9 S/ s
  6. 0 I$ v& S; v9 M3 I0 ^7 M
  7.   /* Program first word */
    # \" y3 L- w4 `* h
  8.   *(uint32_t *)Address = (uint32_t)Data;
    2 O/ u% c4 e: C/ G
  9. , N0 U( _' Z  V6 h0 O+ b1 Y& W
  10.   /* Barrier to ensure programming is performed in 2 steps, in right order
    - u9 X- x) ~6 i, ]) R$ A
  11.     (independently of compiler optimization behavior) */3 N: P, F) y$ y1 N- ]
  12.   __ISB();  z1 D1 a* q/ x5 \9 ]7 I7 J7 Z
  13. 7 f, y7 p5 B6 q$ k$ S+ s, ?- t3 q
  14.   /* Program second word */
    + P4 D5 ~! q+ {" X+ u; Q
  15.   *(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U);
    5 N8 `* z3 m; Z+ b( _! i; c
  16. }
复制代码

' r  m7 g4 l# k. g: _该函数每调用一次,其实是写入了2个word,所以在使用时需要注意Address的递增。
% ]. [0 ~" g5 `$ J8 b0 N) ^  j. i! q$ @

4 q% k) D& Y7 R2 S# }
20210405170242660.png
20210405170242660.png
赞 收藏 评论0 发布时间:2021-11-10 18:02

举报

0个回答

所属标签

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