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

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

[复制链接]
STMCU小助手 发布时间:2021-11-10 18:02
STM32G070的flash读写问题
6 u9 }5 a1 {3 r/ P8 p# HSTM32G070xx的flash分布如下图,打算将Page 63用于保存用户数据。
1 [2 [: _6 |" z% t. J: z7 v, N* S! b3 f
2019102511214233.png

2 L5 d+ C3 {- z6 k2 P& V0 M; X, |; c# b9 D6 S; Z( Y# J
问题
# V# y/ w6 `! c- v开始一直出现flash写入失败,从返回码来看是FLASH_FLAG_PGSERR,一直找不到原因,代码如下:6 m0 x" J  @' D

- x& Z' _/ q5 w: V: m
  1. #define ADDR_USER_DATA  0x0801F800
    , b& T( ~6 T4 u7 M6 K) `# J
  2. / c0 r' B' D. f* u2 R: D; Z
  3. HAL_FLASH_Unlock();
    1 z2 @9 y  y4 t3 l+ y( d  q, c; S
  4. FLASH_PageErase(63);+ n7 v' V# T6 F$ u7 [% U
  5. ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, ADDR_USER_DATA, (uint64_t)data);  a+ j9 l( ?- \. e. ]: F  R: {7 Q
  6. HAL_FLASH_Lock();
    . Q' c' F) F7 o; l6 z+ O* ]- V) w
  7. , Q* O! |% R4 w
  8. if (ret != HAL_OK)0 l8 E. P3 C! {! _, Q  y0 s
  9. {
    ) J" l* ?/ h) l$ X& a
  10.     printf("\r\nuser data save failed, ret = %u, flash err = 0x%x", ret, HAL_FLASH_GetError());
    , w' i  K$ S* U7 `# `, W
  11. }
复制代码
: I3 L, p  A8 o' \" y$ M( \1 a
2019102511181630.png
/ l+ a% D% u* Z. N7 H  @$ d# G
9 Z$ G1 c5 x4 k9 A" h$ i
后来终于在community.st找到了答案:
$ X$ \4 c% L" G8 ?# M* a6 H5 V& U% T. D
20191025112810625.png
2 n- N/ a+ r& ?3 _

( H5 j$ y( C5 B: Z1 z3 G2 wSTM32G070 flash驱动代码3 ]9 y' d4 q( F! p
好了,话不多说,直接上最终的代码,亲测有效:1 ]$ `7 X3 d9 m5 z

7 V4 T- g8 W: X2 b: X
  1. HAL_StatusTypeDef flash_write(uint32_t address, uint64_t data)
    + r9 y: N# x, ]. n' J: G
  2. {$ M. o0 d4 G/ A
  3.     HAL_StatusTypeDef ret = HAL_OK;
    0 N( K0 C8 p: s* U3 L, B
  4. 6 h# u! E, v1 Y2 a! D/ B5 E1 E2 ^
  5.     HAL_FLASH_Unlock();. ]: s7 ^$ y7 R( P# p9 k
  6.     ret = HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, address , data);
    - d: x& ~% D: E5 c) s4 Q- u
  7.     HAL_FLASH_Lock();
    $ t$ K' g1 b9 I7 G- ^( Y

  8. # ]$ C* \4 Z7 _6 D- H! r$ L1 X$ @
  9.     return ret;
    $ ~2 H+ ~0 ^, s! p! M
  10. }
    : B$ s) o% x5 K, C: j' h
  11. & |- K$ d& ~/ Y3 p& `& c
  12. void flash_page_erase(uint32_t page)2 j' b5 Q5 B$ x9 i6 a4 C
  13. {1 @  b2 x' L" A
  14.     HAL_StatusTypeDef test = HAL_FLASH_Unlock();: P, B( t" N! a5 i2 B/ z

  15. & T( p% B$ e2 O: w3 u- _
  16.     test = FLASH_WaitForLastOperation(1000); //1s timeout
    , p$ |* o" a5 w, L& A4 [
  17.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
    8 h, Z1 }% n; h( W# k0 Y7 A
  18.     FLASH_PageErase(page);
    0 Y2 }  |2 L% B5 d( @$ w0 y7 k  `
  19.     test = FLASH_WaitForLastOperation(1000);8 e) v' Y4 S, K1 Y
  20.     CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
    % [% R8 S. @6 }4 B
  21. - N+ {& @/ @* O! l
  22.     HAL_FLASH_Lock();
    9 T$ ]  U1 S' u
  23. }! a3 P3 m$ m# X. F& O
  24. ) `" Q  x7 X% f7 P2 k. v
  25.     /* 调用上述两个函数即可实现flash的擦除和写入 */% X  }. r" m" A$ a
  26.     flash_page_erase(63);7 a0 U0 L  T* V! M2 \  ^: q
  27.     ret = flash_write(ADDR_USER_DATA, (uint32_t)u_data);3 U6 `* [7 }' p* I- [

  28. 5 h) z2 M9 H1 U. e7 I
  29.     /* 读取的话就简单了,直接使用地址即可 */
    " u$ H  \( C, ]  @
  30.     uint32_t u_data1 = 0;4 k: L5 e0 x$ r0 e
  31.     u_data1 = *((uint32_t*)ADDR_USER_DATA);
复制代码
- F4 |$ V$ f% \- J0 i% L  c! C
注意点
, R' d% L7 U  L2 i8 c3 U# Cflash_write每次写入的是一个uint64_t类型的数据,其最终调用的函数为:
7 s$ m) R1 y5 }3 I& v2 }* H! v
  1. & C! E6 f3 m7 U) c, ?4 Q0 B$ {
  2. static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
    # f  d5 g  k$ s$ b
  3. {6 |! {. o( P8 |( C  @8 C% y1 L
  4.   /* Set PG bit */
    4 Q3 j4 Y' z$ b4 n2 E2 o) k! u( z
  5.   SET_BIT(FLASH->CR, FLASH_CR_PG);/ q) A% j9 q+ A' W! i7 D8 \' c
  6. 3 u: h; O% S' F- T" g
  7.   /* Program first word */$ B$ C* [4 S. G3 Z4 D9 q* I
  8.   *(uint32_t *)Address = (uint32_t)Data;
    # Y6 P5 ]; u$ J" m# J! c
  9. - {9 `( V( T" g) V( Z
  10.   /* Barrier to ensure programming is performed in 2 steps, in right order
    $ Q% j5 k5 V0 N. A& y0 `/ j
  11.     (independently of compiler optimization behavior) */
    ! w, S. p4 T3 t+ _
  12.   __ISB();
    ! D5 N2 U5 e! ~. i4 v
  13. 5 z3 @: }1 P6 |% \: Z# y7 H
  14.   /* Program second word */
    ) c4 g8 l$ t& c/ v0 }* N
  15.   *(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U);# B) P) t) V& t; x4 _- X0 d  m
  16. }
复制代码

. L3 q5 P- M# x" u8 y该函数每调用一次,其实是写入了2个word,所以在使用时需要注意Address的递增。0 t* ]5 l, R0 C6 Y: W% g

. |( J; X) a) A& Y; R6 E3 I6 ^* t% f0 i) G. Y/ i5 y) E+ E$ U
20210405170242660.png
20210405170242660.png
收藏 评论0 发布时间:2021-11-10 18:02

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版