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

【经验分享】STM32F1系列HAL库读写内部FLASH

[复制链接]
STMCU小助手 发布时间:2022-4-11 10:16
测试环境:/ E5 {7 o6 L9 ^3 [: A9 _' H
STM32F103RB
- q7 N' _" |, M* R; \" b; _: c* _20KBytes RAM
6 b, L. i6 |0 e9 N" p. V1 `128KBytes FLASH
# z" j& Z, t; C0 x. [注:本章节代码只适合STM32F1系列!
# t1 ^$ s3 h& ~0 m, r5 f( ?
9 I4 U: R* p) C& s2 j 20201024152250174.png
! K- R; L, K1 e
0 K  I& K- G  G0 S  |头文件
! r6 v% I8 k4 q* J- Z, z' K5 E
% ~4 q# u. M7 ^( z
  1. /**
    ! L8 k. P6 \$ S+ p4 L; Y5 [. c- K" o
  2. * @brief Create by AnKun on 2019/10/10
    : ]& b" w* W7 y, K3 B
  3. */
    " ?1 o2 k  |( O9 L3 D

  4. # v' k7 p* P( z3 b4 j% N* Y# U) y9 g
  5. #ifndef __FLASH_H9 G1 e4 d: d% Z8 Z8 j; d3 O
  6. #define __FLASH_H' s$ B+ S2 D. @2 \) ^4 Y/ M

  7. / H1 J. J4 R* \/ _  M! S) W
  8. #include "main.h"
    " X! g, Z: Z( _% k& r

  9. 6 j. P/ B2 l7 M; V6 Z
  10. 移植修改区 ///
    : ]% [' ^0 b' E) N9 _( q0 `
  11. 7 A# ]4 U* q7 D3 o9 X" Z2 c
  12. /* FLASH大小:128K */$ o1 F9 Z1 ^3 ?$ \; `- U! f- A2 ]7 n
  13. #define STM32FLASH_SIZE  0x00020000UL
    ! z: i& l' Y* s6 j+ l& _; s( l. O: q
  14. : k% h: {7 y. a! t1 G  @9 R
  15. /* FLASH起始地址 *// Z( w+ E3 \2 H; R2 t8 ~" z
  16. #define STM32FLASH_BASE  FLASH_BASE
    8 S. l$ j+ G6 G$ u0 N$ v* v3 b

  17. , |' Z6 L, q9 v. ?$ A
  18. /* FLASH结束地址 */
    7 c9 b! t/ l, b- }9 H
  19. #define STM32FLASH_END   (STM32FLASH_BASE | STM32FLASH_SIZE)
    # [- E9 V: ]5 O. p6 c$ X
  20. % d. Y1 ?$ v3 Q) ?3 `  W3 @
  21. /* FLASH页大小:1K */
    * o( f8 U$ D0 ?! y& S" w+ L5 L
  22. #define STM32FLASH_PAGE_SIZE FLASH_PAGE_SIZE6 S+ Y- {: @, l, M
  23. . I, k! L6 Z0 w
  24. /* FLASH总页数 */
    , ]9 s% @; R7 a. G! e( G  }* B$ U
  25. #define STM32FLASH_PAGE_NUM  (STM32FLASH_SIZE / STM32FLASH_PAGE_SIZE)! ^' F  ]7 j, J( e/ q3 A3 a

  26. % k9 \( C- P, ?& I& x
  27. /// 导出函数声明
    ! ]! D( A; s' x) o5 y
  28. void FLASH_Init(void);/ H0 a5 U& k2 ~) v6 _" E
  29. uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size);
    9 v, v' f0 z' M3 Y( s! f& z  S1 u
  30. uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
    3 H" `1 ?; s; H; ^- R5 j, u* A
  31. int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages);3 S& L% z2 V2 N# t, f# D: ~
  32. uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
    9 g8 s8 M  v% A3 n: K

  33. 3 r( i# a( B) q9 k
  34. #endif // !__FLASH_H
    7 r% P' m' [5 D; ?

  35. : N2 A- o1 O+ a& ~8 }
  36. end of file
    4 `  I2 I( d0 U2 ^% t. B" v
复制代码

. y* R2 w* t; `/ v源文件

2 m$ _' ]2 h2 V1 B
+ A3 g- p, _# C1 {5 {8 t0 u% U
  1. /**
    * Q$ f8 F# E/ ]4 ~
  2. * @file  flash.c
    # D  C& a8 f( V- k
  3. *8 F  v2 Z5 ?) S8 [  C
  4. * @brief Create by AnKun on 2019/10/10
    , k6 G$ o3 @* g3 b/ w9 Z* ]! _+ e
  5. *
    " P' ?: f$ e/ |; R7 B
  6. */
    . ?4 ]* E) B: u3 }- {

  7. ( c& x2 Q) M& W0 w; m! ?. F5 P
  8. #include "flash.h"2 l2 }5 c' ^# Q: C# H* m- p1 c  ?
  9. #include <string.h>
    3 E1 q5 A6 B1 u5 P9 h$ s1 s: w
  10. 8 F6 R* q; S3 C& I: b9 r) i1 n. N0 ]
  11. static uint16_t FlashBuffer[STM32FLASH_PAGE_SIZE >> 1];
    - R1 C" ~  f" Y" V4 X. ?+ q

  12. - k: }5 B$ m# c
  13. /// 初始化FLASH
    ) \; g8 Z8 y% f0 L. p/ }8 X
  14. void FLASH_Init(void)/ X$ n. H& u% e4 b: w/ Q5 u1 ?( M
  15. {: Y+ {  }& D: |, J- D  x
  16.     HAL_FLASH_Unlock();* i" R) {, k5 n
  17.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);/ p9 G6 [4 |/ s) M0 k3 G5 S+ {) c
  18.     HAL_FLASH_Lock();
    4 C' [, f% r/ |) M$ j# S5 c. `
  19. }
    9 a. C5 E! `- X. R

  20. % K8 [. T* W' h  i! c$ U
  21. /**
    5 i8 x; n; f( A0 I4 i3 j& M
  22. * 读FLASH
    8 C0 g, P# t8 p. i* r9 ]1 ?4 e5 R7 m
  23. * @param  Address 地址
    3 n* X/ R& _" S2 j. q; O: ]
  24. * @param  Buffer  存放读取的数据
    ; _2 [6 h/ P& j& B1 H& ~: [0 Y
  25. * @param  Size    要读取的数据大小,单位字节+ o9 ~  C1 s% B
  26. * @return         读出成功的字节数. o$ w; X  T: H! x
  27. */, O7 U* N2 O' v# |
  28. uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size)0 z2 X+ h, G# t6 t6 j, f; ]
  29. {
    1 i  F  b2 r' N0 h
  30.     uint32_t nread = Size;( m* p3 `1 x6 ~( ]
  31.     uint8_t* d = (uint8_t *)Buffer;4 {4 y7 Y: V7 y( E% S* m1 m- _
  32.     const uint8_t* s = (const uint8_t *)Address;
    " S( t: v1 p; I0 |1 D9 j2 C0 Y
  33. " l6 N; D! g3 L! m/ x' Y' ]" J" H7 D
  34.     if (!Buffer || Address < STM32FLASH_BASE || Address >= STM32FLASH_END)$ {3 ]. ]' U. C% E: Z
  35.         return 0;
    ! a, E7 W$ O8 L% i8 @$ f

  36. % T1 j1 A3 E$ }. f
  37.     while (nread >= sizeof(uint32_t) && (((uint32_t)s) <= (STM32FLASH_END - 4)))
    4 H, ^5 x- a& w+ L: Z2 `) o2 q! i
  38.     {! ]  F4 j. i" [, g- @1 x
  39.         *(uint32_t *)d = *(uint32_t *)s;
    4 z- z, q, d4 }  `' ~! O. N
  40.         d += sizeof(uint32_t);
    6 A! E, @7 [4 d
  41.         s += sizeof(uint32_t);! S( v3 h' G$ z+ d/ |. f
  42.         nread -= sizeof(uint32_t);4 |; f3 F+ m/ P- a( y
  43.     }% A1 t$ k. o9 i
  44. % |/ T' _' a7 i3 b
  45.     while (nread && (((uint32_t)s) < STM32FLASH_END))
    + t9 O& E; X8 @- B* k( @% f/ u
  46.     {9 ?* q' a, X0 w" V+ N8 v
  47.         *d++ = *s++;3 R) w! I4 V+ G
  48.         nread--;' y* M0 J$ |# C* H5 j3 `
  49.     }6 X+ T% [3 Y& S' V) L. w

  50. & {7 N+ c4 ]0 C6 {
  51.     return Size - nread;6 e! q& D2 q9 k3 m/ I; {
  52. }2 @3 ]) o9 U* p6 {9 n

  53. 9 g2 ^$ [5 ]  {' I( F# Z$ L% z; f
  54. /**6 |3 s2 R, V4 b# G# K
  55. * 写FLASH
    " c" u" y* n0 A+ l
  56. * @param  Address    写入起始地址,!!!要求2字节对齐!!!
    9 K) t. P) {& r* F: G- H
  57. * @param  Buffer     待写入的数据,!!!要求2字节对齐!!!
    7 c/ x8 R; u4 U- u
  58. * @param  NumToWrite 要写入的数据量,单位:半字,!!!要求2字节对齐!!!
    9 P" r3 }$ H8 v6 E
  59. * @return            实际写入的数据量,单位:字节
    . R+ c  g2 W3 u; V
  60. */
      o% [4 G7 q  Y4 A* X4 R& W" ~
  61. uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)) g3 s' K% e: T9 d8 s
  62. {
    ( a# }2 W1 c/ }, j3 Y& }, V9 L
  63.     uint32_t i = 0;
    2 o+ b" M. I$ k; V' T
  64.     uint32_t pagepos = 0;         // 页位置0 V  p4 s' S' H& u
  65.     uint32_t pageoff = 0;         // 页内偏移地址
    ' q+ q& k" R4 v, D3 c7 t8 m
  66.     uint32_t pagefre = 0;         // 页内空余空间
    5 z  k  C( z  R; h/ A1 M
  67.     uint32_t offset = 0;          // Address在FLASH中的偏移
    0 o+ o' O, _7 V
  68.     uint32_t nwrite = NumToWrite; // 记录剩余要写入的数据量# A+ |8 T3 n/ Q/ e2 i
  69.     const uint16_t *pBuffer = (const uint16_t *)Buffer;5 K' U! u! J# ^; i' S0 u/ |

  70. 8 n+ j% s" p. @+ @: }) H8 n  i/ ~
  71.     /* 非法地址 */
    9 F9 H, `0 L7 n5 f: e- }" t
  72.     if (Address < STM32FLASH_BASE || Address > (STM32FLASH_END - 2) || NumToWrite == 0 || pBuffer == NULL)
    7 h* Q) ?% I1 w$ V
  73.         return 0;
    / ~2 u- o5 O- t( m( k& d: x
  74. ) k! N# U3 q9 z
  75.     /* 解锁FLASH */
    5 f3 y; Y% v2 X
  76.     HAL_FLASH_Unlock();
    " m3 a# T' y) i$ c* R2 A

  77. # }. _" v+ K# w5 z- U) A
  78.     /* 计算偏移地址 */
    0 |5 E3 H* |; u; Z& S
  79.     offset = Address - STM32FLASH_BASE;
    7 v) J, q: \0 c: x/ @3 F1 e) e5 w4 X5 y

  80. / P( u0 M5 p4 u: m
  81.     /* 计算当前页位置 */9 B: n' I; L1 p6 ~% k# A
  82.     pagepos = offset / STM32FLASH_PAGE_SIZE;1 F. l4 j2 X! h3 }2 {

  83. ; i: w4 {2 a+ a* Z3 Q4 l
  84.     /* 计算要写数据的起始地址在当前页内的偏移地址 */4 G: {" G1 o4 }! E; h5 [
  85.     pageoff = ((offset % STM32FLASH_PAGE_SIZE) >> 1);
    * _' j# E4 P5 r6 S! F. n% X) `7 a' m0 a
  86. 6 v1 n1 C* e& C# Q, \" D: J
  87.     /* 计算当前页内空余空间 */2 K* i; X8 T* Z
  88.     pagefre = ((STM32FLASH_PAGE_SIZE >> 1) - pageoff);
    8 E5 H$ N; t) O% R

  89. - ]% ]$ @$ S7 N$ h
  90.     /* 要写入的数据量低于当前页空余量 */1 Y; u6 Y+ N1 Y$ q/ \% Q
  91.     if (nwrite <= pagefre)3 g3 u" i& B- T; t4 `
  92.         pagefre = nwrite;& C1 F8 G5 i, e) B0 _

  93. 2 e% V5 P+ F3 E( y9 U5 \. m: w
  94.     while (nwrite != 0)9 `5 i# [% `5 N
  95.     {
    ! d' T8 I9 \3 ^; o1 Q4 t) x
  96.         /* 检查是否超页 */
    ( ?8 P* j! [# x% B% l! o
  97.         if (pagepos >= STM32FLASH_PAGE_NUM)% {+ v, c! O6 L  h& @
  98.             break;
    * X5 f" E' ?+ a2 N
  99. , D2 i: z, l2 x# b
  100.         /* 读取一页 */) ?$ k9 c+ F; ?" X0 ^5 j# I  {
  101.         FLASH_Read(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE);3 n- Q6 \/ a: q7 K6 {# z/ i1 [

  102. ; X. p% d6 ^/ y* n, p+ c
  103.         /* 检查是否需要擦除 */9 A  C- u1 |7 _) E$ }
  104.         for (i = 0; i < pagefre; i++)
    : ?3 m  V. s% D
  105.         {4 g: F3 F# k8 W+ I& s1 N' ~" v
  106.             if (*(FlashBuffer + pageoff + i) != 0xFFFF) /* FLASH擦出后默认内容全为0xFF */6 K! {3 l2 h$ V  Z3 X# C3 d( S, p# h
  107.                 break;2 l2 y7 F6 I4 p9 b9 r
  108.         }
    0 ], r3 x- N8 ?3 w# g0 e9 ~: h2 [
  109. ( P2 ?. w- u4 E: ~
  110.         if (i < pagefre)- @$ N1 G( S" c7 q/ g
  111.         {1 d' |0 f9 {6 n( h
  112.             uint32_t count = 0;7 j" U% q: S* W" f. |7 I& D
  113.             uint32_t index = 0;9 `4 o" c& |' z# f
  114.             uint32_t PageError = 0;+ r/ y' [! |6 Z% w& a9 i
  115.             FLASH_EraseInitTypeDef pEraseInit;6 @0 p8 {2 I. h: H4 W! A: b  L7 S' n7 O

  116. + ^$ w$ G, o+ F# c4 d% @1 s
  117.             /* 擦除一页 */
      ^* t) U8 q" J3 x3 J$ s
  118.             pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
    # N) g. z# [* E
  119.             pEraseInit.PageAddress = STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE;
    , ]8 {- D, b, c' D5 z2 N$ l
  120.             pEraseInit.Banks = FLASH_BANK_1;$ c, @  v2 y) t2 x) S& T! j9 u
  121.             pEraseInit.NbPages = 1;/ }( Z1 C7 F- U3 R2 y
  122.             if (HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)% h1 E. F5 Q4 m8 M) ?. A& e
  123.                 break;
    $ r1 n, |* q  R! y& u) H  D; H
  124. 9 ]5 \5 G& b! \) a
  125.             /* 复制到缓存 */7 V7 R) u8 b( N( h2 J+ ?' O/ Z6 W
  126.             for (index = 0; index < pagefre; index++)& H! G- q; x$ |2 _
  127.             {
    ( C4 R. s* `$ i
  128.                 *(FlashBuffer + pageoff + index) = *(pBuffer + index);
    . A. }. N& O$ t' Q$ D" s) B8 A3 c
  129.             }
    + L* L) j6 H# F9 D, ?

  130. & T* V) Z1 ^* s5 w
  131.             /* 写回FLASH *// B$ l2 B" t8 x" ?( A/ z
  132.             count = FLASH_WriteNotCheck(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE >> 1);
    * f8 P, x* @5 ^: M) q1 a0 H
  133.             if (count != (STM32FLASH_PAGE_SIZE >> 1)). e2 b' X4 ], w1 [
  134.             {7 [6 P6 e5 z" x6 @: l1 r8 r1 G; d" v
  135.                 nwrite -= count;
    / N8 H' q2 G. s# j7 N+ {$ c7 Y
  136.                 break;: v4 o# ]9 p3 ?) |
  137.             }$ J, |4 f6 M; ?6 W0 u% C
  138.         }- T, D3 \+ R4 p. J' H, M4 {
  139.         else
    " n1 T/ _& R9 b
  140.         {/ i# Z/ f' |5 g& C) K) D
  141.             /* 无需擦除,直接写 */* K+ |: x+ S  t7 y
  142.             uint32_t count = FLASH_WriteNotCheck(Address, pBuffer, pagefre);/ M5 L" ?- H8 C: K! {
  143.             if (count != pagefre)$ w2 ?$ K  |  Z; r8 T. C8 w% Z
  144.             {1 s7 _& }# M! q( n) w
  145.                 nwrite -= count;
    , H) S  T- Y5 E& T* Y  F
  146.                 break;
    5 z) N# z7 T' f" L1 H
  147.             }
    # _7 U( H# I' w" M/ x
  148.         }
    1 |8 k" }/ `, U/ ^

  149. + s- P+ n1 s: E) d* O. i8 z9 R
  150.         pBuffer += pagefre;         /* 读取地址递增         */
    ! c5 b0 [7 {& r) i5 G* o
  151.         Address += (pagefre << 1);  /* 写入地址递增         */: G* @) I8 e* f0 E
  152.         nwrite -= pagefre;          /* 更新剩余未写入数据量 */
    9 b0 `9 F/ Q5 D2 D3 Q6 \$ H
  153. . [6 t4 ?% x7 l* B
  154.         pagepos++;     /* 下一页           */
    8 V' N3 S! ]% k1 n
  155.         pageoff = 0;   /* 页内偏移地址置零  */
    7 m5 x& m$ y9 z$ E7 q+ c
  156. 6 z8 l% H- M' e( S6 H# T1 s- [+ ^, t
  157.         /* 根据剩余量计算下次写入数据量 */4 G- I4 k1 H4 n% T4 i" `
  158.         pagefre = nwrite >= (STM32FLASH_PAGE_SIZE >> 1) ? (STM32FLASH_PAGE_SIZE >> 1) : nwrite;
    : G" u$ v' U( Z7 L: E' p
  159.     }
    , V) E3 a$ ~$ ?  R

  160.   _& H& O5 p. h% Q, L0 ^# j
  161.     /* 加锁FLASH */: d% M$ Z% i9 c
  162.     HAL_FLASH_Lock();* D& h% |0 V6 w; K4 I( N

  163. 3 n4 G1 d- B4 P7 O" M
  164.     return ((NumToWrite - nwrite) << 1);
    2 V+ v3 @$ P, W: R- q9 \
  165. }! j: w4 B: A5 {7 Y6 n* H$ x

  166. + R2 ~  ?7 g) N6 Q0 D, u. N1 k: ?
  167. uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
    9 _! k7 B; M, V, G
  168. {  D" \$ z! h3 `8 {, G. o
  169.     uint32_t nwrite = NumToWrite;
    5 \8 x' y1 u4 P- n3 L2 e+ a
  170.     uint32_t addrmax = STM32FLASH_END - 2;
    0 s. K3 D7 H, x/ y% q8 ^
  171. # S9 l' g% S: [8 r! z1 @! [  ~
  172.     while (nwrite)
    & \% W" K" s/ [. O) I3 H7 X3 ^7 V
  173.     {
    9 K2 H* E  {% E4 y# T3 Y
  174.         if (Address > addrmax). ?5 O/ F" q, J
  175.             break;
    . W( P  ~" s7 d. V
  176. 8 n, V1 M3 _. Y) W/ o( Z( {4 q
  177.         HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, *Buffer);
    & W1 G( m8 V: }$ H
  178.         if ((*(__IO uint16_t*) Address) != *Buffer)- g$ q; s9 a6 v* F1 R
  179.             break;- t$ j: }/ z* I  k' Z& f

  180. ( w  e8 o6 @; B3 f
  181.         nwrite--;
    " G9 c# U7 `' r# {/ w
  182.         Buffer++;  U% g- R1 z: \- u
  183.         Address += 2;
    , l8 u! N: I9 ?, e! n9 r
  184.     }
    ; ^, w. z' C' B( u4 L
  185.     return (NumToWrite - nwrite);' W7 e# @: r+ M7 U1 @" h/ P. H: E
  186. }& I) W# T  \9 @) M4 I2 s( g" ~! E
  187. 2 g8 I5 P: s, t, W9 _
  188. int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages)
    / P- Z  \7 m/ x5 A/ g( i' T
  189. {# K* `* x4 l$ |: v  C4 f, ^) {
  190.         uint32_t PageError = 0;
    ; ^+ y: a5 ]! r6 V$ o8 `
  191.         FLASH_EraseInitTypeDef pEraseInit;' w" @  L5 s7 I% V1 z9 [2 Y$ k
  192.         pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
    % @% i' [1 \: z
  193.         pEraseInit.PageAddress = PageAddress;
    4 ~- T. A2 e! @
  194.         pEraseInit.Banks = FLASH_BANK_1;
    7 X0 Q. T* ~9 T: ]/ q
  195.         pEraseInit.NbPages = 1;
    $ G9 V7 K: E& P" B) y  T
  196.         if(HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)
    ' n& z* N" z' d# ?. B8 X' b
  197.         {
    0 L9 q% N0 L4 S% J7 \: _3 g
  198.                 return -1;
    5 O, _4 b6 {* Q+ d
  199.         }
    2 N! z5 ^, q/ f0 f
  200.         return 0;7 |/ _% X$ `! U2 |
  201. }
    ! i2 p8 F- S. j3 D/ W

  202. ! V4 p' w9 P2 X' j) N
  203. end of file
复制代码
5 t& Y5 |* u/ g/ C
- f0 f* j$ p5 E; A7 x% Q
4 }) ~- n. i) o0 @$ b, X

+ l: O& m6 `7 B4 j) {; Q  |8 y) ?1 u7 k% V& ^+ j

( J; A6 \# H& A8 \* \
. @, m$ I6 J5 W2 P) g
收藏 评论0 发布时间:2022-4-11 10:16

举报

0个回答

所属标签

相似分享

官网相关资源

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