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

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

[复制链接]
STMCU小助手 发布时间:2021-11-10 18:02
STM32G070的flash读写问题
# U3 p! D( ^$ }$ v: S2 \STM32G070xx的flash分布如下图,打算将Page 63用于保存用户数据。# T- c1 y, a; ~" b1 G, U

/ B% i" j5 _& C
2019102511214233.png

+ E- A4 ?3 [$ w# h# y# j
" n* l- l; m4 O: r. M( X问题. b: M# D7 [: e/ K* `
开始一直出现flash写入失败,从返回码来看是FLASH_FLAG_PGSERR,一直找不到原因,代码如下:
3 T$ \0 X) u. f0 ]5 e# V. q: j: @1 k+ N5 _/ y; T4 j
  1. #define ADDR_USER_DATA  0x0801F800* O3 Z9 ]# v5 B: q1 ]$ u
  2. 3 I3 }2 _3 p2 i; K# p* \
  3. HAL_FLASH_Unlock();
    + z4 c/ D3 P! X4 f4 P1 C. C
  4. FLASH_PageErase(63);4 u' K, j9 R4 T8 Y) o
  5. ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, ADDR_USER_DATA, (uint64_t)data);
    3 n4 J4 B- a/ x. [% @0 `9 P
  6. HAL_FLASH_Lock();2 Z3 j% S( z; n' G+ T0 j1 B2 A

  7. ( Z& M/ H) B4 z3 N$ z" T: M8 G
  8. if (ret != HAL_OK)) P) v7 g8 t% r+ l& a: x
  9. {
    / C' T* l5 o- _) L' c
  10.     printf("\r\nuser data save failed, ret = %u, flash err = 0x%x", ret, HAL_FLASH_GetError());
    . R- k# A7 a; [3 }+ {4 v2 C
  11. }
复制代码

! ?+ d' m& k8 n/ a! E; f) W' _
2019102511181630.png

) k3 i# r6 r0 m' F
  z0 b6 U9 K& f后来终于在community.st找到了答案:9 K' k+ @0 n* N/ w7 u; X

, R% A" J7 j4 O0 s7 o
20191025112810625.png
% z: _+ L7 X3 T4 ]8 z

( W# M2 A( p/ S( k! B0 ZSTM32G070 flash驱动代码
, Q2 L. f+ D6 i好了,话不多说,直接上最终的代码,亲测有效:8 b2 H( |9 B5 h9 N# q* x7 C5 |$ U
) y& Z/ d. G" O
  1. HAL_StatusTypeDef flash_write(uint32_t address, uint64_t data)
    1 [0 S- c2 n0 W. N
  2. {
    " i  c+ R- y+ q7 y
  3.     HAL_StatusTypeDef ret = HAL_OK;0 [; g/ w- [. g+ p+ x9 B8 P1 T

  4. 4 }& B% ?3 W: z
  5.     HAL_FLASH_Unlock();+ {+ O0 q. g# m& F% Y
  6.     ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, address , data);
    , k+ `1 y5 q9 k1 t
  7.     HAL_FLASH_Lock();
    * h1 A% r2 g4 Y7 L8 @; J+ `3 ?

  8. ( Y8 _+ u4 S2 }. m( ~
  9.     return ret;% ]; ], L! D' l6 N
  10. }" u+ B! a) j( e/ z" w

  11. * M; e5 i$ x) c3 \) s" W
  12. void flash_page_erase(uint32_t page)
    3 d, M% s* r5 A+ A
  13. {
    ' l4 _' d+ N$ o
  14.     HAL_StatusTypeDef test = HAL_FLASH_Unlock();
    ' t$ R7 C' P0 v# J
  15. 8 K, J$ v: B- V, J. A* X2 _
  16.     test = FLASH_WaitForLastOperation(1000); //1s timeout
    ! [) m' M! x7 [5 M" I
  17.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);  M+ R  f3 y! O+ R
  18.     FLASH_PageErase(page);
    0 ]3 \0 d3 F1 t' N9 g* q/ c" f
  19.     test = FLASH_WaitForLastOperation(1000);! K( A; N2 T7 U9 ~! c8 i/ e
  20.     CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
    ) a* U# Y7 s0 g0 f6 Z* i" U( X5 w

  21. 3 D! c" k$ R, R( K, v7 D
  22.     HAL_FLASH_Lock();3 D, Z" h2 J' k# \, G1 y
  23. }
    8 U4 @5 ]* m. [9 V% L* A; J* t
  24. & s  ]" _/ Q* q! J
  25.     /* 调用上述两个函数即可实现flash的擦除和写入 */( K! F! l" c5 V, i% c
  26.     flash_page_erase(63);
    - w7 T. @. A* y1 `2 P% J
  27.     ret = flash_write(ADDR_USER_DATA, (uint32_t)u_data);
    ; x7 R; h; B) i9 j# v2 P- [2 N

  28. ' z* L0 Y7 X: c- w: v. M9 B$ l
  29.     /* 读取的话就简单了,直接使用地址即可 */9 S( N+ I9 t, v% Z* E5 d) u' x
  30.     uint32_t u_data1 = 0;4 i* T  @& X. [  U3 h1 K6 g! _
  31.     u_data1 = *((uint32_t*)ADDR_USER_DATA);
复制代码
# v3 Q% a  e9 ?' i
注意点
! |+ \5 |7 p5 ]* eflash_write每次写入的是一个uint64_t类型的数据,其最终调用的函数为:
. s, W. [, s$ R! W1 R5 I# {
  1. ! O0 F7 ^( ]: w/ w+ m+ D, E& G" q, _
  2. static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
    ; H: ]3 }# l8 x/ _6 l
  3. {
    % l( B- X7 @& H; Y7 |/ c+ ^4 ~7 p
  4.   /* Set PG bit */
    % p1 K' {7 s; I9 H6 s9 }& d  ~
  5.   SET_BIT(FLASH->CR, FLASH_CR_PG);4 d: t2 J. p# q  d  n+ l
  6. 1 l1 U) \: D8 @( ]
  7.   /* Program first word */# s4 }- z: O! v
  8.   *(uint32_t *)Address = (uint32_t)Data;  q8 B' b+ t9 Y. _

  9. 2 ]* E2 C( H. Y8 N
  10.   /* Barrier to ensure programming is performed in 2 steps, in right order; u0 k3 P- }5 B, O7 k
  11.     (independently of compiler optimization behavior) */
    6 f" T* o9 d+ H6 O6 D$ x
  12.   __ISB();! c! u: K* i7 Z$ w8 ^! E  H

  13. # C1 {% V. r0 r6 L7 h" M
  14.   /* Program second word */
    2 N  G; i' B) c6 G2 y- X
  15.   *(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U);" ~6 P  Z  f  c% }* P5 K5 a! @8 h5 d; A
  16. }
复制代码
2 g9 u$ x0 `1 I$ }
该函数每调用一次,其实是写入了2个word,所以在使用时需要注意Address的递增。
5 F. b' S) \$ w* y$ L" x( N" n( I% H6 C( Y# S1 I$ c
  [4 }! ?- j& w
20210405170242660.png
20210405170242660.png
收藏 评论0 发布时间:2021-11-10 18:02

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版