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

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

[复制链接]
STMCU小助手 发布时间:2022-4-11 10:16
测试环境:- V: r, S$ n6 L9 ~2 A3 A
STM32F103RB
- w8 y3 `) i1 I- X" |20KBytes RAM
4 j( l' I6 Z6 ]9 E6 H9 @8 Y8 s128KBytes FLASH7 Y# }5 X, [2 i9 _9 F0 d0 j
注:本章节代码只适合STM32F1系列!
% I; V" x4 N( [, H
6 w6 G- [2 z3 S 20201024152250174.png
. O6 i' G  n) |4 ]  K8 J7 H/ G- k, n/ M
头文件$ B; G  M+ _# ]8 s+ w& x2 L, f  ~

1 d$ V9 w5 X# A5 \, ?
  1. /**0 S8 r4 |: i% N5 f- O- V
  2. * @brief Create by AnKun on 2019/10/10
    + I3 }7 i2 _; B% m1 d* n
  3. */9 ?# T! o' F5 s6 O$ F- Y' n: X

  4. 6 L( K( {/ N( K3 @. o
  5. #ifndef __FLASH_H
    - V3 g) R7 o" D4 t) f# o
  6. #define __FLASH_H
    1 \# n2 y3 c# J7 ~( t
  7. 9 d) O& u" q2 ~& a
  8. #include "main.h"& i  s) z6 b, x
  9. " R& m0 [/ \" v
  10. 移植修改区 ///8 f! V$ a* g2 ]0 w: s

  11. * f7 o( y# n) n1 {0 K8 e# y+ k+ T
  12. /* FLASH大小:128K */
    : _$ Z1 r) h1 x+ d
  13. #define STM32FLASH_SIZE  0x00020000UL! N. r6 j9 N( c+ H4 ?6 p- C; ^5 r

  14. ) ^6 d" {& F- Y
  15. /* FLASH起始地址 */5 p7 z4 l8 ~0 q8 v' z9 M
  16. #define STM32FLASH_BASE  FLASH_BASE3 ?  ?% ]/ w( V, u
  17. 1 ?! b) [8 d! D. d
  18. /* FLASH结束地址 */. [* g' |+ a! ~# v( V
  19. #define STM32FLASH_END   (STM32FLASH_BASE | STM32FLASH_SIZE)
    ; N, x* W  m! N, P6 w5 Z! z7 {! s/ M; Z
  20. % C" s6 d3 E# a
  21. /* FLASH页大小:1K */
    & x7 }  s) x1 V( @4 V% f6 ~: F( e
  22. #define STM32FLASH_PAGE_SIZE FLASH_PAGE_SIZE0 d* n6 ~, m! `$ r! |% i

  23. ) c" y1 Z/ F! _  I0 W
  24. /* FLASH总页数 */
      I& W* S1 X! n7 y, P2 d/ Q
  25. #define STM32FLASH_PAGE_NUM  (STM32FLASH_SIZE / STM32FLASH_PAGE_SIZE)
    ( C3 G/ ~) U& Z! M

  26. " k# x$ v4 B4 ]  z8 x% r' j% A
  27. /// 导出函数声明
    9 Y' E* K+ p) i/ a, t8 t
  28. void FLASH_Init(void);
    , O8 q! p+ Y# b* P+ q6 A+ s
  29. uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size);; q! a% m" J/ A) L- p: e
  30. uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
    6 U& t3 B% z4 H' g3 \
  31. int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages);
    9 b6 I; H. ^" ^0 i5 U# ?8 A
  32. uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
    * R' T! C' l0 x  J0 Z# F
  33. 2 ]) ?$ L5 _8 ]
  34. #endif // !__FLASH_H
    & J% C& T) b" X0 q$ q* @) [

  35. $ ]+ B3 Q- J; w& Y. ?
  36. end of file : J# Y2 d. ~& B% ?+ e
复制代码

) M7 U4 Q1 o/ Q* _0 n# n源文件
9 g6 d# W$ t1 j; e2 v$ I7 N: D: {

8 I- W0 @) p0 ]/ M6 I
  1. /**" R- _* \1 c( P6 t) a
  2. * @file  flash.c
    4 X" l; |" x0 _3 n
  3. *- s& j1 p1 b8 u5 s, i
  4. * @brief Create by AnKun on 2019/10/10% F& B( H. {' |: z( _
  5. *, h' j7 B" B8 q; Q- V" f
  6. */7 e: O7 Z& ?( {/ }
  7. ; V0 m9 |% E+ O& b* p
  8. #include "flash.h"/ f$ f& ?) J: V/ J) c) v$ z
  9. #include <string.h>  l! y% {- X2 y/ }3 v; d* ^
  10. / i- P9 X+ Q* ~- l" O3 N
  11. static uint16_t FlashBuffer[STM32FLASH_PAGE_SIZE >> 1];
    2 R6 F$ B8 d0 R) _  t8 W) s
  12. 9 p( n- _  d3 _( ]
  13. /// 初始化FLASH3 k, P- L& `8 u* ?/ l
  14. void FLASH_Init(void)
    0 H5 j( N( O; S9 S+ t% G" z! A; m
  15. {% _! r% W! g9 Y% B5 l* X
  16.     HAL_FLASH_Unlock();
    % M0 _! [/ S1 u/ p3 v
  17.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
    4 M# p0 [5 u; J& ^" b% w1 K7 G8 r
  18.     HAL_FLASH_Lock();
    + G& R6 g2 y( r0 W2 s  s
  19. }
    9 h4 `8 n4 w7 ^2 o' Q
  20. 8 [  X- p, O% o
  21. /**3 N2 S3 v( {$ P/ g( e
  22. * 读FLASH# n/ u. `# L0 [7 H1 w
  23. * @param  Address 地址' |- y/ ?+ T, U) e* x( _) D
  24. * @param  Buffer  存放读取的数据3 k0 p! C1 y/ T' g/ I+ s
  25. * @param  Size    要读取的数据大小,单位字节
    6 o9 V, |' K. p6 w, J
  26. * @return         读出成功的字节数4 x- D) P0 a, K2 Y; o
  27. */
    / c2 n% Q' k1 S# x$ k4 N: g; w7 t
  28. uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size)
    / @$ f5 d' a0 E7 W) G1 B, `
  29. {7 u: E; n3 q0 O* R! V
  30.     uint32_t nread = Size;. q/ A* D% I  [
  31.     uint8_t* d = (uint8_t *)Buffer;
    7 k1 e3 n: R' k, Q1 X7 R& o
  32.     const uint8_t* s = (const uint8_t *)Address;
    * `% ~# Q4 Q# M! L$ O5 P) w1 `

  33. ! v$ [7 X2 O* `$ _1 f
  34.     if (!Buffer || Address < STM32FLASH_BASE || Address >= STM32FLASH_END)- |$ t5 \, t) g. w1 X: D% J
  35.         return 0;2 i" P. D  z$ h9 d

  36. ! u6 s! B' @/ F0 U, B$ o
  37.     while (nread >= sizeof(uint32_t) && (((uint32_t)s) <= (STM32FLASH_END - 4))); S0 {  x/ ^! t" J
  38.     {
    ! {# p4 w; p" g- ]' l9 `) t
  39.         *(uint32_t *)d = *(uint32_t *)s;' \7 X. F- w" z; B1 W
  40.         d += sizeof(uint32_t);- o# y3 M, m/ e- G1 ~
  41.         s += sizeof(uint32_t);
    7 u) P5 S/ n$ `+ K4 d8 ~  y: e
  42.         nread -= sizeof(uint32_t);
    - f3 d! I2 x5 n( t- l( m
  43.     }- x6 r+ V* I9 B/ E2 Q8 e$ t: q  b

  44. 1 S2 j% I/ C+ l3 S
  45.     while (nread && (((uint32_t)s) < STM32FLASH_END))
    0 O1 ?( q" l- |/ _# r( Q4 E
  46.     {
    1 \+ y; R; f$ B# _0 `% i$ M
  47.         *d++ = *s++;/ T. f) a  V3 C
  48.         nread--;
    - Y! ?$ p+ s! P, E7 Z( h/ k) y' x$ [$ F
  49.     }- k* Y$ T! K  A$ {. X/ e& `6 l" H7 I
  50. 7 u( c4 r) v8 S/ V# b
  51.     return Size - nread;
    2 j' P4 o% r  T$ R4 V" i
  52. }
    3 a3 B( j, a7 o. U* M
  53. 7 g8 ^* N+ y( D: ^
  54. /**
    & F' }: P9 z, Y
  55. * 写FLASH! o$ y$ S4 R% G3 X
  56. * @param  Address    写入起始地址,!!!要求2字节对齐!!!+ ]% t- V0 ^- e  q; p" t
  57. * @param  Buffer     待写入的数据,!!!要求2字节对齐!!!
    0 o0 J3 l. f! G" w* I
  58. * @param  NumToWrite 要写入的数据量,单位:半字,!!!要求2字节对齐!!!
    * L! x# {9 s% n, ^! s/ m
  59. * @return            实际写入的数据量,单位:字节
      i  s0 z  ]' q6 K7 |1 b
  60. */
    ' F0 a/ q: V5 ~& d7 f  A
  61. uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)' ~- J7 W4 f" m: \& ]
  62. {
    / @3 K/ a+ ?. n6 S0 }5 I
  63.     uint32_t i = 0;) q0 O! M+ p- u: X8 C
  64.     uint32_t pagepos = 0;         // 页位置
    4 }/ r. i/ e, m4 M1 s
  65.     uint32_t pageoff = 0;         // 页内偏移地址
    ) K- P) |1 U6 j0 L
  66.     uint32_t pagefre = 0;         // 页内空余空间
    9 ~$ v1 E, O% X: L
  67.     uint32_t offset = 0;          // Address在FLASH中的偏移6 z# j$ F1 l4 A1 B' H8 r6 G
  68.     uint32_t nwrite = NumToWrite; // 记录剩余要写入的数据量
    * \' c' r* F& ]5 @( P2 l
  69.     const uint16_t *pBuffer = (const uint16_t *)Buffer;. Y1 G/ _* q' I$ }
  70. % {# n3 g( L# D4 j/ ?
  71.     /* 非法地址 */- u) `- v$ u3 O. C
  72.     if (Address < STM32FLASH_BASE || Address > (STM32FLASH_END - 2) || NumToWrite == 0 || pBuffer == NULL)
    " N+ I1 U0 m% p' x9 b$ v( I6 j
  73.         return 0;& [( K" ~- g+ g# [+ R# [/ J+ }
  74. : _1 Q+ o) p9 c9 u% |
  75.     /* 解锁FLASH */
    , L& u( N* a% G- ~
  76.     HAL_FLASH_Unlock();
    . m; m9 w4 \$ t4 P2 W

  77. . d6 I' ^( d" ?
  78.     /* 计算偏移地址 */: a8 v, H, i7 E) t, r* H
  79.     offset = Address - STM32FLASH_BASE;
    8 m, W1 A1 B; N/ n: O  X

  80.   J  {' w8 Z3 j/ {: R$ {) |' |  U
  81.     /* 计算当前页位置 */9 |; }6 c: s) d5 H3 m
  82.     pagepos = offset / STM32FLASH_PAGE_SIZE;/ ~4 ]( b& v2 R' h$ ]
  83. 2 H# @% N( [& t; i
  84.     /* 计算要写数据的起始地址在当前页内的偏移地址 */
    # b) m! Q; Z* f2 B* q' M
  85.     pageoff = ((offset % STM32FLASH_PAGE_SIZE) >> 1);; N/ U- A: _9 D1 ~- h) K! L0 N
  86. 8 r$ f; s9 {; _8 X: r
  87.     /* 计算当前页内空余空间 */; O4 y+ J3 d" S: @3 E* w* q, _! i+ t) K
  88.     pagefre = ((STM32FLASH_PAGE_SIZE >> 1) - pageoff);) @( Z8 u# g& a' _9 Y

  89. 1 T# F$ n  F! G1 L& N
  90.     /* 要写入的数据量低于当前页空余量 */. n9 Y" g' r9 R) y: z) z
  91.     if (nwrite <= pagefre)
    : A) P8 l9 l6 N
  92.         pagefre = nwrite;; P7 g# N5 \- @' C
  93. - ~( F( C% H$ {  S" ]) E
  94.     while (nwrite != 0)6 q4 ~& S0 \) a- u% Z
  95.     {& L+ `; U% f- Q( F. Y
  96.         /* 检查是否超页 */
    # c# U+ T" ~- H: x
  97.         if (pagepos >= STM32FLASH_PAGE_NUM)
    ( n, y( P9 A4 g- X! {; V) ]
  98.             break;
    - P  W5 ?$ |7 U9 P' b& o# _- [
  99. / k& H. V" H# h8 A
  100.         /* 读取一页 */5 K, r) b$ o& X& j4 x' s
  101.         FLASH_Read(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE);" H. d* S- @' Z7 [& }# \

  102. " n" \7 i/ _3 A+ ^
  103.         /* 检查是否需要擦除 */
    8 W$ ^9 Z1 F, }! g: F* O) r
  104.         for (i = 0; i < pagefre; i++)
    - C4 {& c3 f* w8 {* ?  p: \) f
  105.         {
    $ _2 p/ h9 B& C
  106.             if (*(FlashBuffer + pageoff + i) != 0xFFFF) /* FLASH擦出后默认内容全为0xFF */
    % n6 f. H$ Y* R. k
  107.                 break;
    9 ]' x+ m4 A7 d. |
  108.         }9 b. j: x$ h  {1 ?9 Q% P
  109. * r7 P5 V1 R/ p3 y
  110.         if (i < pagefre)
    : H: T1 ~  U1 q( |
  111.         {% L+ I% g4 |, l( e2 n" ]+ u, m6 i. J
  112.             uint32_t count = 0;
      N9 n: j8 _) T0 k* T% K: [& y8 d
  113.             uint32_t index = 0;$ m: s+ y9 C0 T. q, L9 @% |
  114.             uint32_t PageError = 0;
    ; l1 b/ A* D8 w6 Z
  115.             FLASH_EraseInitTypeDef pEraseInit;+ |" m5 D" ^% }8 i' G
  116. % T; R) ?: R# T6 L
  117.             /* 擦除一页 */
    * P  M6 R; U& ?4 t# z
  118.             pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;/ z& d5 L3 B/ \3 w! y5 A" Q
  119.             pEraseInit.PageAddress = STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE;
    + Q5 `) m; y/ {
  120.             pEraseInit.Banks = FLASH_BANK_1;& v* @* k$ v, k, q- ]2 D
  121.             pEraseInit.NbPages = 1;
    - m) A0 {' g. {1 W# _! k' \7 L
  122.             if (HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)
    5 w8 n  o, E7 n2 Z1 I. i
  123.                 break;9 X! f. {# c- ?9 e9 L
  124. : k. z2 D( T* d
  125.             /* 复制到缓存 */
    ; ^9 e; y7 Q) [# C
  126.             for (index = 0; index < pagefre; index++). u% E) _. n6 T$ D* T
  127.             {7 I/ |  |) {3 h- a
  128.                 *(FlashBuffer + pageoff + index) = *(pBuffer + index);) I6 {* D* y5 }+ Q- @+ ^- e4 {
  129.             }
    * s+ P6 l, }/ z$ w7 q; p; F9 c
  130. 1 L* X# M0 ^. o  d' a- m# Z
  131.             /* 写回FLASH */
    7 ?; H: v: u2 _2 ^6 Q/ K' R+ F4 {) X
  132.             count = FLASH_WriteNotCheck(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE >> 1);
    7 ^/ T. u/ M* ^  m2 L1 e
  133.             if (count != (STM32FLASH_PAGE_SIZE >> 1))
    . ~! q& E! C' [
  134.             {3 I  M4 E! Y5 E. h: y
  135.                 nwrite -= count;  x0 [7 H( A' G: @4 g5 o
  136.                 break;, v% ^1 \% v5 K/ B) k
  137.             }) V9 ^3 _$ C* I9 Q8 M
  138.         }
    8 Y, q. s- u) f9 `' r& h7 x' K
  139.         else
    ( N# p1 |6 |0 }3 H; e- l; E! [- j% f
  140.         {0 ^3 T6 c9 s+ a3 ~! Q% K
  141.             /* 无需擦除,直接写 */# {9 q: n* ]9 W8 z& M8 t! Q" A
  142.             uint32_t count = FLASH_WriteNotCheck(Address, pBuffer, pagefre);( b+ g6 k+ O2 Z7 w
  143.             if (count != pagefre), c  ]9 |/ k( L
  144.             {
      V2 H/ U7 `0 B) g4 Z! O: q
  145.                 nwrite -= count;  o$ x/ f) l! ]1 ]
  146.                 break;6 V' s0 n& [6 A7 ~4 m6 S
  147.             }8 N2 L( X2 Y8 F+ V7 X) C
  148.         }- @+ S# |: `. K$ ]1 R1 d& U
  149. 0 U+ O$ k2 C" k% g' m
  150.         pBuffer += pagefre;         /* 读取地址递增         */
    & A( d% o/ s- \  H
  151.         Address += (pagefre << 1);  /* 写入地址递增         */
    : f% J! h+ ^9 d+ @4 F. ~+ F* ^
  152.         nwrite -= pagefre;          /* 更新剩余未写入数据量 */
    , q, U* P( ?* d- o; L, a# E
  153. % o7 m+ I9 R% C1 [
  154.         pagepos++;     /* 下一页           */, I' @) o; d" P' E" x5 j. o0 l
  155.         pageoff = 0;   /* 页内偏移地址置零  */
    : Z+ [8 ~" q, ]

  156. & |( O+ ?. V9 O% }' r/ Q& ?0 ?
  157.         /* 根据剩余量计算下次写入数据量 */
    5 M, S. g* l. m7 v
  158.         pagefre = nwrite >= (STM32FLASH_PAGE_SIZE >> 1) ? (STM32FLASH_PAGE_SIZE >> 1) : nwrite;5 Q3 b; s- `" B6 E0 k$ s
  159.     }
    - s, ?7 ^/ p' X

  160. # j- _* k( u* E" @6 T' u6 r) c
  161.     /* 加锁FLASH */8 `% X! Q- x  d( Z2 S7 x
  162.     HAL_FLASH_Lock();( n7 ], Y: M2 ^

  163. % ^) M0 v5 _- o
  164.     return ((NumToWrite - nwrite) << 1);
    $ z' h& K' T/ _$ O4 u* e+ _
  165. }1 S3 w, Q8 D7 j& z1 E

  166. ) R: |6 A9 Y8 R- L
  167. uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
    & l  `! `6 }& p
  168. {* Q  X2 f- l+ k1 O
  169.     uint32_t nwrite = NumToWrite;3 n3 [0 k$ Y, {8 \; ~
  170.     uint32_t addrmax = STM32FLASH_END - 2;' Y  w( J5 o' D4 w5 L: x
  171. 2 F: X. q6 D+ u+ j
  172.     while (nwrite)
    + G4 {& |( D' V: J: T! {. |! f
  173.     {
    ! i' S) `% ?+ s6 ]5 E' `: N
  174.         if (Address > addrmax)
    . H- N3 n* D; i- k1 H
  175.             break;
    $ ?% o" v% y6 D$ V; H5 Y* R/ M0 v. M

  176. 2 D! H7 F2 C: J. _
  177.         HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, *Buffer);
    + X4 Y: v: L7 C% ]# I1 U8 a1 Q
  178.         if ((*(__IO uint16_t*) Address) != *Buffer)1 z2 K" E: ~+ h$ W4 l
  179.             break;
    4 X$ B5 |* B. k( F% Q& n
  180. * ?* g7 c+ a, L( g
  181.         nwrite--;
    ; i0 N* U  L8 V& P
  182.         Buffer++;6 [+ q% K8 T  w' H4 s
  183.         Address += 2;1 p9 M7 i1 E" P8 p2 q
  184.     }4 I! O0 c& ^* I# j& a6 M1 B/ M9 I
  185.     return (NumToWrite - nwrite);! z/ k2 r# h; E8 t" h6 U1 @, t* O: W
  186. }* E; B4 ?5 z( g) @
  187. 8 W, J" E; ]# U* H
  188. int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages)1 X  Y. m6 X3 ]% G5 b
  189. {) B+ u. Q! \7 [2 ?- `
  190.         uint32_t PageError = 0;% ?* k2 ]6 _( n7 c  ^1 t1 `) `) G' D2 L
  191.         FLASH_EraseInitTypeDef pEraseInit;
    5 @- L  y+ I  k: B5 W4 Z& q; K- t
  192.         pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;8 w& K& ]: H; n' N! w4 ~( G3 D
  193.         pEraseInit.PageAddress = PageAddress;
    8 [& _) d9 Z5 s. t1 U0 M7 r& a
  194.         pEraseInit.Banks = FLASH_BANK_1;
    - @! c8 T# b* N$ x0 T
  195.         pEraseInit.NbPages = 1;
    ( C9 h( T* E5 H9 |& y
  196.         if(HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)7 r  T4 J* i. W( p( I
  197.         {: `7 F* Y" I" O6 `+ [  m
  198.                 return -1;$ _' T% `1 L5 R# T1 u% p0 }
  199.         }, |2 i: u1 Y7 s2 ?6 G6 C
  200.         return 0;
    5 l, R+ x1 O9 c2 d+ D
  201. }
    : x; c' @2 F+ y) e$ u7 I" D! L

  202. # U: E. j! a+ h
  203. end of file
复制代码
2 s4 T% c0 H; c' ]& X1 a

/ L& S3 e' v2 c+ V6 `: k9 N# s4 |1 m$ K1 ?% F$ M' p
) w6 ?5 w' n) Y- ~
1 e5 @7 P7 [0 Q
2 P1 l7 ^: R' L% W, A- P1 Y4 X
: G. V% ]) V1 l/ e
收藏 评论0 发布时间:2022-4-11 10:16

举报

0个回答

所属标签

相似分享

官网相关资源

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