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

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

[复制链接]
STMCU小助手 发布时间:2022-4-11 10:16
测试环境:  p, @% C/ i( f* U  ^
STM32F103RB
9 e6 e$ ?% P3 R0 l, ~& A20KBytes RAM
; ~8 f& m) Q: T  i1 p128KBytes FLASH
$ Q7 u! [( J* a% _  r. h注:本章节代码只适合STM32F1系列!# l2 r7 N  H" w
7 `5 T+ {; p7 v: S# X
20201024152250174.png
2 [" J; y; z3 n6 @/ ?0 q' p
6 _7 P4 M, @; \7 f" f头文件# k1 M$ A* _8 X& i

& f4 g7 U3 A4 g+ @' z" R
  1. /**' S1 l* J. }/ a& Y1 D
  2. * @brief Create by AnKun on 2019/10/10) u* W0 g2 l# x/ x9 S) ]" F
  3. */2 N- j1 T6 o7 A1 B0 Q% G
  4. ; u  t- U$ j8 o
  5. #ifndef __FLASH_H
    ( r$ Z3 R7 W# u; s$ ?) z/ F5 I
  6. #define __FLASH_H
    2 X! e- ^$ g6 r' `! m  |
  7. 9 a6 A' `- N9 s- N  ^( _. w3 U
  8. #include "main.h"
    " j# e0 ?$ g6 s# K" g
  9. $ s! Y$ @6 A  ^, k5 B1 J3 o1 z8 t0 d
  10. 移植修改区 ///
    " v2 {% V) c0 ?* m7 F" F! F

  11. " g7 p' Z0 q7 Y- }$ `1 `2 B& `
  12. /* FLASH大小:128K */6 r' q- U0 i6 l: x0 L: R
  13. #define STM32FLASH_SIZE  0x00020000UL
      b8 u6 B( ]& y2 a8 \
  14. 8 r. l9 j. S4 v5 m+ |
  15. /* FLASH起始地址 */& L0 [. w$ f  K
  16. #define STM32FLASH_BASE  FLASH_BASE
    ! Y; ^* R* e5 J2 `$ B2 ~
  17. : G' d0 A/ p# C9 o) l( N8 R5 W
  18. /* FLASH结束地址 */
    0 [( d& H7 w3 F% X, r# e' g
  19. #define STM32FLASH_END   (STM32FLASH_BASE | STM32FLASH_SIZE)
    ! y8 @: s" ?* i, G8 d6 W, b: V
  20. 7 C( K/ a0 i( [- E) p! R
  21. /* FLASH页大小:1K */
    . N- m2 H$ C/ q3 A
  22. #define STM32FLASH_PAGE_SIZE FLASH_PAGE_SIZE' j; z0 m; z2 t3 z1 B
  23. 3 \4 p% }% Q  [, u3 U& w
  24. /* FLASH总页数 */
    ' r, _6 B3 ^1 @6 w; _( c4 D% X3 ]6 M
  25. #define STM32FLASH_PAGE_NUM  (STM32FLASH_SIZE / STM32FLASH_PAGE_SIZE)5 `' `( k3 h0 B

  26. $ s9 J  R" ^- y: S* V9 ~
  27. /// 导出函数声明
    7 X3 s% s) W  k1 {) g' P2 r7 x6 c
  28. void FLASH_Init(void);
    8 b0 R  d2 \4 A
  29. uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size);; P  s) c% @: F# q
  30. uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);+ Q# Y4 y1 n6 O/ A8 P
  31. int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages);# r+ Q( y1 \1 D1 M3 j# }4 F
  32. uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
    - Q7 }& B  a/ `, e
  33. % X' }7 z+ V) y5 d* \- c
  34. #endif // !__FLASH_H4 H9 Y5 L3 O6 j8 k2 k

  35. 2 q' |: ^. X5 K* B
  36. end of file . l% Y3 G* y) c
复制代码

( _% x' F% Q" s8 Q; G3 w5 e源文件

6 U5 r1 E  G' J5 P3 N; g  \% L& M5 p+ r' {
  1. /**% ?5 x3 a' g% {- _  Z1 t
  2. * @file  flash.c
    4 x' K* M* D5 B) J* B
  3. */ g% d' x1 n3 l1 i4 o, p
  4. * @brief Create by AnKun on 2019/10/10
    5 U. B( O0 R/ D8 F1 W
  5. *7 b) |( A+ }+ O" l$ n8 N
  6. */2 u3 G3 `0 \7 A$ k8 d
  7. 1 Y4 N6 a) w" ]6 v$ r
  8. #include "flash.h"# T; t! N( V6 l$ }+ y1 Z
  9. #include <string.h># s5 S. ~1 W7 W
  10. . F4 B" p1 O4 G- v+ y3 \7 D
  11. static uint16_t FlashBuffer[STM32FLASH_PAGE_SIZE >> 1];
      x3 D9 z1 c* L4 D' i/ G8 r' ?/ Q0 p
  12. % s, Z: g: g: `. \* ]0 F3 |  l
  13. /// 初始化FLASH
    6 j* G. G  n' h( g1 M4 M
  14. void FLASH_Init(void)9 ]$ P; }- K! _
  15. {- ^& W+ l5 ~6 b. A5 J
  16.     HAL_FLASH_Unlock();
    1 B1 z' q3 g/ m5 e' o; j
  17.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);: C1 q0 ?: j7 c5 j2 K
  18.     HAL_FLASH_Lock();2 P: M8 F$ T+ o1 \+ J) Y
  19. }
    * m* F- r* d! o" s9 d6 ^

  20. " C( V$ c4 J/ j1 s4 N. c
  21. /**  h& ^. D+ d2 U; K) Z6 h$ F& g
  22. * 读FLASH* C  x( `% X; x# G3 _
  23. * @param  Address 地址
    6 i/ Z* f9 V. {; M) m/ ^& P
  24. * @param  Buffer  存放读取的数据
    & ~! M) v5 P/ Z3 T6 K& B, ^* A
  25. * @param  Size    要读取的数据大小,单位字节
    2 R3 ~; k! K! o
  26. * @return         读出成功的字节数$ e) B4 Q% x3 T, a2 B$ h; H) S6 ]
  27. */
    ) d3 x- a* W: V! ]/ K: i8 D/ _
  28. uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size)
    , M' n/ Z! i. s' e' m
  29. {
    7 v, d% l+ ?1 t3 `
  30.     uint32_t nread = Size;
    + L! m, U+ C$ f  D. K' O; C
  31.     uint8_t* d = (uint8_t *)Buffer;9 `( I1 l  O0 \- o2 c9 x& P3 s
  32.     const uint8_t* s = (const uint8_t *)Address;9 [+ K0 m$ a$ s# v
  33. % \' s  ?+ L3 x# c
  34.     if (!Buffer || Address < STM32FLASH_BASE || Address >= STM32FLASH_END)
    6 o) I# _( C' ]0 G$ U7 ?1 ]
  35.         return 0;4 m: g! W3 \( F" t6 O

  36. , ]+ p8 I0 W/ ^* w) ]! n" {
  37.     while (nread >= sizeof(uint32_t) && (((uint32_t)s) <= (STM32FLASH_END - 4))). X- b5 L5 N3 w. e+ I" \0 F
  38.     {% m) k3 P& E( F/ b  n4 C
  39.         *(uint32_t *)d = *(uint32_t *)s;% `  m: [. B" `. q" _
  40.         d += sizeof(uint32_t);
    4 i4 p- R( v4 A4 }, g( N
  41.         s += sizeof(uint32_t);2 U5 m$ V3 n/ j) ~0 W% X
  42.         nread -= sizeof(uint32_t);- p* F6 C0 Z$ A
  43.     }
    + L3 [8 I7 o5 D7 i
  44. 9 u. f, K: U1 p( E" |; `6 _# q
  45.     while (nread && (((uint32_t)s) < STM32FLASH_END))
    / g6 A% h/ ~8 b  [! H' C& @
  46.     {
    9 B. i* B$ L- R& I  x
  47.         *d++ = *s++;
    - L4 b$ s: b& ~" ~  G, ^' ]% j
  48.         nread--;& v, ]$ _0 S" |- r7 b+ ~; D9 g
  49.     }
    ! i( U5 A( _3 U, ^: X) h
  50. ; J8 I$ j, T4 N& u
  51.     return Size - nread;
    + R4 L* \8 D: N: l9 K5 Q, F
  52. }8 }) ^. v: D. ^1 W9 k4 X" N9 p) g

  53. $ B+ y7 n# C* Q, K
  54. /**5 d% e# H$ ^' e8 `
  55. * 写FLASH
    2 L9 m; j$ C7 e
  56. * @param  Address    写入起始地址,!!!要求2字节对齐!!!
    1 W( v0 ]8 P/ O, G8 p- e$ a& D( O3 q
  57. * @param  Buffer     待写入的数据,!!!要求2字节对齐!!!
    8 o8 P( _/ ~* {) T
  58. * @param  NumToWrite 要写入的数据量,单位:半字,!!!要求2字节对齐!!!; P9 f0 B4 @0 l) D0 B
  59. * @return            实际写入的数据量,单位:字节
    & _) u) o- ?3 y- C3 U
  60. */
    / Y1 ]  I4 S4 m
  61. uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite): W) n5 P) m- K  k! Y( ?. T8 Y% ?6 k
  62. {
      l* ^; o; m, U  T5 {
  63.     uint32_t i = 0;; ^* {8 o5 b1 {" W1 N; u# b. ?/ u0 f" T" M# c
  64.     uint32_t pagepos = 0;         // 页位置1 a# r7 O) Y' J: c8 Z8 {
  65.     uint32_t pageoff = 0;         // 页内偏移地址
    + L( h( q, b4 G( `* M, }
  66.     uint32_t pagefre = 0;         // 页内空余空间
    8 ]( {% `0 t" d
  67.     uint32_t offset = 0;          // Address在FLASH中的偏移" r. v3 A3 F; S' |6 m; d6 N+ t: N
  68.     uint32_t nwrite = NumToWrite; // 记录剩余要写入的数据量0 R; \+ `; g  _* Q
  69.     const uint16_t *pBuffer = (const uint16_t *)Buffer;) o. L( C$ ]6 d  U" Y; p* x' k

  70. 8 C6 r* ?$ d4 {# B
  71.     /* 非法地址 */
    7 Q* t6 |7 k" t/ P% b, x  E. |
  72.     if (Address < STM32FLASH_BASE || Address > (STM32FLASH_END - 2) || NumToWrite == 0 || pBuffer == NULL)
    5 Q3 N/ _* z0 Y- {) Q
  73.         return 0;
    2 n2 e' O' z' J) Y4 b. G$ y

  74. 7 `! R2 H* l5 W" d, }1 ?
  75.     /* 解锁FLASH */
    6 D) ]' u, M, O* }3 o( x# |2 H
  76.     HAL_FLASH_Unlock();3 g# t- r) }! `4 b1 m2 Z% }! ~$ I

  77. % T; h. B* d0 r( j$ a
  78.     /* 计算偏移地址 */" g) n' y0 f& K# R
  79.     offset = Address - STM32FLASH_BASE;
    ; `# ]; t' c  @+ ?$ j
  80.   H- X& G9 N' M
  81.     /* 计算当前页位置 */# Q; Z# u9 h) h6 ~
  82.     pagepos = offset / STM32FLASH_PAGE_SIZE;
    / j! y; W$ C6 l/ h" b4 i" C
  83. 7 \+ j3 y" ~8 X6 c: ?( x5 v
  84.     /* 计算要写数据的起始地址在当前页内的偏移地址 */
    # M/ y9 {4 x# ]. A. x% g
  85.     pageoff = ((offset % STM32FLASH_PAGE_SIZE) >> 1);
    7 I; H) r) T, |7 W% f; B
  86. 0 E/ g- P, |2 D  ]+ O. j2 B$ _
  87.     /* 计算当前页内空余空间 */
    / K0 O' Q3 [; |3 D. H. o# {
  88.     pagefre = ((STM32FLASH_PAGE_SIZE >> 1) - pageoff);
    . ^# E7 w+ w+ n9 t! [' K
  89. 9 j" G' q/ ]) L( G$ m' |- @! Q: `
  90.     /* 要写入的数据量低于当前页空余量 */% i& V. \1 z8 v3 q' l9 X' O
  91.     if (nwrite <= pagefre)& h2 O: n9 E) s# Z7 X, A4 o4 R1 X
  92.         pagefre = nwrite;3 }# D& A1 p4 `7 P$ l
  93. % v3 M) E- O* x/ J1 C
  94.     while (nwrite != 0)6 S7 l: i0 Z5 V0 H% Z1 B7 R
  95.     {
    $ L6 ]* o& _4 z6 f, j) U
  96.         /* 检查是否超页 */, e. n. Q1 R1 q% o+ ~3 f! y+ R; c
  97.         if (pagepos >= STM32FLASH_PAGE_NUM)
    9 r& ^) S8 E; |. R* c! I4 e
  98.             break;
    3 j/ F9 y- H" z- Z
  99. * v# E0 ~: z# s+ |- ]9 G& U4 i; D
  100.         /* 读取一页 */, {: M) I7 W2 Y/ R6 r
  101.         FLASH_Read(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE);
    6 D7 ^1 V- E  R

  102. ( T7 g6 i; y. z6 {: v/ g1 S
  103.         /* 检查是否需要擦除 */
      `  U: ^. K/ T2 Y3 o1 A
  104.         for (i = 0; i < pagefre; i++)
      @3 N9 w& U1 w" ~
  105.         {
    % l8 r6 O6 A9 I* }' @: a" Y5 m/ b/ e
  106.             if (*(FlashBuffer + pageoff + i) != 0xFFFF) /* FLASH擦出后默认内容全为0xFF */! f* b) t# m% r" B5 P/ u
  107.                 break;
    & T9 [3 A' [' D8 p1 X# ?. S
  108.         }$ V) C" N  o/ T
  109. ! z1 ?/ @. S, n: F8 h7 i
  110.         if (i < pagefre)/ q( Z& |2 a+ V: y
  111.         {
    8 T% O# O, h8 d* m
  112.             uint32_t count = 0;
    + ?5 e5 c# ^; `  g: y0 ^, ]
  113.             uint32_t index = 0;/ f! z( n' I/ h; y0 A; r) f0 W# V
  114.             uint32_t PageError = 0;
    & g" J3 R( l, L9 X6 `
  115.             FLASH_EraseInitTypeDef pEraseInit;
    ( l; A4 f- ], ~9 Z
  116. * l- D0 G4 o# ~# d6 ~2 s
  117.             /* 擦除一页 */1 V  |- s+ x8 t- c" e: F2 F
  118.             pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
    : c% g  c/ G7 y$ Q+ n& C
  119.             pEraseInit.PageAddress = STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE;
    : b0 w9 [* A: x/ T) e) k# _- q$ W$ \
  120.             pEraseInit.Banks = FLASH_BANK_1;2 B5 h/ H% p, |3 |2 v
  121.             pEraseInit.NbPages = 1;7 Q3 r2 M. ~* p
  122.             if (HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)
    ' S! q+ K7 H$ ]1 g: u
  123.                 break;
    . L2 G# U' s; j
  124. 1 g, \# N! @  \7 L
  125.             /* 复制到缓存 */% T5 a3 |" Q) W0 R, v6 ~
  126.             for (index = 0; index < pagefre; index++)
    7 G" H0 k# d. g8 R& L+ j1 D& l
  127.             {
      ]/ Z' P: d7 @% w5 |4 q* }# Y
  128.                 *(FlashBuffer + pageoff + index) = *(pBuffer + index);
    & `7 a# e  _& |8 h1 Z0 w
  129.             }
    ; i2 l. \; c, ]9 e$ r7 G4 F

  130. 8 \) o. l5 U1 }  t8 x) I
  131.             /* 写回FLASH */3 E/ v3 ^3 |1 J' e1 C7 `9 i2 E
  132.             count = FLASH_WriteNotCheck(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE >> 1);$ C0 ]6 r& m5 X; U/ _7 G5 i, W
  133.             if (count != (STM32FLASH_PAGE_SIZE >> 1))9 f$ {% I# b6 p. |6 G
  134.             {$ U0 I: J# u/ S6 s; U! P
  135.                 nwrite -= count;# U$ c! l) g) @, H/ P- x" v" x
  136.                 break;
    " i8 S" d, ?- u5 X
  137.             }
    . M3 K& m8 Q0 `0 c
  138.         }
    * g6 J; K. p, G7 A
  139.         else' l* p" V- |; \$ l( t, c
  140.         {
    # W  M2 m% c8 P4 J  J+ v7 K, d
  141.             /* 无需擦除,直接写 */. a% y% c4 F" k
  142.             uint32_t count = FLASH_WriteNotCheck(Address, pBuffer, pagefre);
    & I7 f& K6 M( U# R( q
  143.             if (count != pagefre)- O3 K) j) B: _- K
  144.             {
    / Q" r7 h# {5 ~% j
  145.                 nwrite -= count;# x  c0 G, J- ^& W7 Q0 n6 a
  146.                 break;6 ?4 \8 U" T$ D  Y6 B+ R
  147.             }4 K! e9 J" _7 t, k
  148.         }
    ' y: h# A- p' ^* k% s0 S* [9 |" j
  149. ; o  }% }4 o1 e
  150.         pBuffer += pagefre;         /* 读取地址递增         */! N. X( ]2 i& f  o
  151.         Address += (pagefre << 1);  /* 写入地址递增         */" D+ S* B& ~7 X, F8 |" W/ P5 D
  152.         nwrite -= pagefre;          /* 更新剩余未写入数据量 */
    . {6 r1 m8 n7 E+ b; K/ {
  153. & G) Z# k# L& Y' u9 N8 e* N
  154.         pagepos++;     /* 下一页           */! u+ W# t& [8 M- H9 D7 {% D0 g
  155.         pageoff = 0;   /* 页内偏移地址置零  */
      q/ G0 G! @! `* D

  156. " C' U5 t. A2 B! \6 f% O7 V& l
  157.         /* 根据剩余量计算下次写入数据量 */0 O( z# y6 E5 ]! C' l3 i/ g8 k
  158.         pagefre = nwrite >= (STM32FLASH_PAGE_SIZE >> 1) ? (STM32FLASH_PAGE_SIZE >> 1) : nwrite;
    % {2 Z0 ?/ E' |, V% c! O
  159.     }9 V. N% ]3 W+ l, o2 Q+ R
  160. 4 n" S& T& k. a
  161.     /* 加锁FLASH */
    1 y7 w  A& f  g, P% l2 m4 ?( G1 {
  162.     HAL_FLASH_Lock();
    8 i$ A, Q4 {5 @- K

  163. 9 Q: u2 v" F2 P  u( [
  164.     return ((NumToWrite - nwrite) << 1);+ I$ Z7 w0 v6 ~
  165. }
    ! ^" E- \: B. a& Z5 I; _2 s! x' k8 v2 ]

  166.   Y" f/ ^/ h, d
  167. uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)3 Y% z4 c: Y7 G5 u5 Y7 n& e0 k0 j6 r
  168. {1 j) F0 m. `0 K. z& v
  169.     uint32_t nwrite = NumToWrite;/ O- f! L/ P! D5 g) D
  170.     uint32_t addrmax = STM32FLASH_END - 2;
    - i) L* ?: d# S% w" c
  171. 5 Y" R7 f; N3 o7 ]* t" a5 p# X
  172.     while (nwrite); l2 \8 K8 c2 y
  173.     {
    ' m5 @+ V+ v" l" F9 G0 O9 V
  174.         if (Address > addrmax)* d8 v; E5 h4 Y+ k5 w- N
  175.             break;
    , N4 @  N. t' ?" l$ D

  176. - m& Z  i+ D+ ^; Q2 w5 r
  177.         HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, *Buffer);
    " T- i: @$ M! @4 m- c  K6 n+ D4 O2 h
  178.         if ((*(__IO uint16_t*) Address) != *Buffer)
    & k4 v  q7 U4 @1 B5 m/ H/ P2 a
  179.             break;  i' B& q! y% k  q
  180. . a0 @. {! A5 ]
  181.         nwrite--;# E4 ~& s; b7 Y# {) r( ~
  182.         Buffer++;5 p7 e, S9 d" o7 P8 t1 ~
  183.         Address += 2;
    ) C/ J, E! A/ V" d" K& q. H5 q( r
  184.     }( R+ X1 i  X( E* Y6 x" E
  185.     return (NumToWrite - nwrite);( q1 A9 t+ c% E& F$ [! l6 L
  186. }
    3 k; z) T2 d% y) C: B( b& Z
  187. % @5 l" |. T! X" ^2 C+ q) x6 z
  188. int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages)
    , y! T6 N+ t& |
  189. {
    7 ]* o  A* b0 Q& Y5 Y! n$ G
  190.         uint32_t PageError = 0;
    , {" O: \( o; ~
  191.         FLASH_EraseInitTypeDef pEraseInit;2 \. m  m3 M$ @% R  _
  192.         pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;: B8 n! g: ]8 l: A5 [# S8 z
  193.         pEraseInit.PageAddress = PageAddress;
    " [  Z" S" _' @5 X$ h
  194.         pEraseInit.Banks = FLASH_BANK_1;
    , p% L' J3 T7 J/ Q
  195.         pEraseInit.NbPages = 1;
    ( |5 G# U, P5 N3 V
  196.         if(HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)/ P$ Q9 q8 j+ G5 e2 I7 Q; w. t! C8 R! L
  197.         {( c6 T! x' a# I" m
  198.                 return -1;
    ) \; t1 m: ?( b# d5 d0 |! b
  199.         }
    # b# ~' @$ l/ f
  200.         return 0;
    7 f/ [: |7 M  r# F7 l
  201. }
    ( j/ `$ P# {2 x8 V; `$ \+ G
  202. ' f7 A/ y8 `+ ]
  203. end of file
复制代码

( w0 h! X2 \& s- b4 |3 P3 T0 i% M5 u6 I& z$ q+ U

# o% F/ [) k4 l3 W" W
" }; p( d% k) w" U5 t2 P+ h8 Q+ j2 {* s/ v6 v
% ^" L- f8 Q3 H  Z, q- j

: ]$ H+ B, }. ]& w
收藏 评论0 发布时间:2022-4-11 10:16

举报

0个回答

所属标签

相似分享

官网相关资源

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