不知道为为什么,STM32 LL库并没有FLASH的库函数,于是决定写一个6 M5 Q; O/ n: ]/ w# D) u1 A
+ E4 G- c" B$ {6 k( R" L" M
LL库的特色,就是一个函数,只占用一个指令周期,比如,设置GPIO输出的状态,就是LL_GPIO_SetOutputPin();" [+ R/ \$ q; z9 Y- Z% r3 j
- __STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
$ X6 H' U, _ x' C - {- o/ F; E* l4 \8 ^1 @3 S, {
- WRITE_REG(GPIOx->BSRR, PinMask);
7 l( A; `. Q6 y+ O+ R - }
复制代码 于是我根据这种风格,已经常用的操作写了一个.h和.c文件
& ?8 [5 k3 L% _: W. d4 K
- D1 x( j' F( u4 p) L) v0 f头文件代码3 k, p# ^+ }2 C' E! ~* R/ k
- #ifndef __STM32F0xx_LL_FLASH_EX_H) P* Q% J4 E" ?: j& o
- #define __STM32F0xx_LL_FLASH_EX_H" a" i. m# ~) v7 S) y3 u/ }
- $ u' B! Z1 a0 F( e1 c: m
- #include "stm32f0xx.h"6 H3 P# P; h/ ]' E3 e
- 8 p# G/ S( ^ z( h1 }
- # g+ O6 s% U# |! N
- #define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */
6 H" f9 x1 z! |5 @( @& p - #define FLASH_FLAG_PGERR FLASH_SR_PGERR /*!< FLASH Programming error flag */
3 }1 u* ]. m1 R, |. S7 e& l. U - #define FLASH_FLAG_WRPERR FLASH_SR_WRPERR /*!< FLASH Write protected error flag */( I* M6 T: ~ k
- #define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Operation flag */8 T! g2 d$ t+ ]1 M1 j6 F
- ' s: I% O8 d8 ]
- #define FLASH_TYPEERASE_PAGES FLASH_CR_PER /*!< FLASH_CR_PER */+ s+ z( v7 K! K$ c- k$ U" w
- #define FLASH_TYPEERASE_MASSERASE FLASH_CR_MER /*!< MASSERASE */4 p- L4 ?$ v! `. N; n
- 6 Z2 G5 o0 s5 P5 u
& L, A4 k8 t: S. e2 c- #if defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F031x6) || defined(STM32F038xx) \) V3 _! W) `2 l$ Z0 P$ g
- || defined(STM32F051x8) || defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F058xx) || defined(STM32F070x6)
, t. H" M" t# b0 P - #define FLASH_PAGE_SIZE 0x400U
9 A& v) J" J1 f' c - #endif /* STM32F030x6 || STM32F030x8 || STM32F031x6 || STM32F051x8 || STM32F042x6 || STM32F048xx || STM32F058xx || STM32F070x6 */
& U ]$ _7 p$ \1 Q L- O9 [7 P0 u - . c9 c8 j; B5 g8 D( ~) E* P" O" d
- #if defined(STM32F071xB) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F070xB) \ u( F: U- x1 R0 J5 c
- || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC)0 p5 {& f0 v. r: s
- #define FLASH_PAGE_SIZE 0x800U
6 P5 Q1 v7 w+ M - #endif /* STM32F071xB || STM32F072xB || STM32F078xx || STM32F091xC || STM32F098xx || STM32F030xC */ F' d0 U# _- v
& I& ~' }; S& A1 o! y, B- typedef enum {4 B N, s. G; Q! V6 s( a% G6 \
- ProgaraType_DATA64,) F& O+ n' O8 K+ ?
- ProgaraType_DATA32,4 d+ {; D0 |/ @
- ProgaraType_DATA16/ H( r0 a" X; T# o7 Z! O4 ?
- }ProgaramDataType;# @2 j2 D& k" d& D! T8 ]
. Y+ K8 L. \9 ]! V( l0 p. e1 |* a- typedef enum {\9 t8 {) n9 g3 l L
- FLASH_Lock=1U,Flash_Unlock=!FLASH_Lock\
0 c' r! g3 q: T) y - }FlashStates;
: y. S# l% w+ I& m' {8 w
5 ~" f0 j3 y( K) S- /* Set the OBL_Launch bit to launch the option byte loading */
% z9 ^- V7 m$ B7 M - __STATIC_INLINE void LL_FLASH_SET_OBL_Launch(FLASH_TypeDef *FLASHx)* N+ o7 u4 r e: Y2 y
- {' y+ h- S1 R0 Z" j2 Q2 m9 e7 v
- SET_BIT(FLASHx->CR, FLASH_CR_OBL_LAUNCH);
3 M9 h) s. x6 E* G8 p" L - }+ n# n% n* C9 E3 q2 z; w
- __STATIC_INLINE void LL_FLASH_Lock(FLASH_TypeDef *FLASHx): B/ v) U6 m) j+ X* _
- {; o$ L* \6 r; K" Q- G7 ?
- SET_BIT(FLASHx->CR, FLASH_CR_LOCK);
- E9 F8 j: y m p. r$ d5 O - }
$ b2 x L' \% H - 5 G* u8 [+ T" p1 d
5 r, B- c F, Q0 X/ B- /* @brief Set flash erase type.4 p K, W2 M" e; o) O
- * @param FLASH_TYPEERASE specifies the FLASH flags to clear.
; P! c+ g5 c, T$ i3 l0 N - * This parameter can be any combination of the following values:
+ F) ^. x6 E$ P4 b4 O- T" U - * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase" y/ s2 v1 f" L$ Z& C" h; Q
- * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag # w1 _; T; T0 M( Q$ h' ^
- * @retval none*/
9 Y; Q$ X/ u' z1 |3 A) F7 E- b$ J
$ `% i: \- j1 d7 @: _: N- __STATIC_INLINE void LL_FLASH_SetTypeErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)
- F* F: Z$ h/ B% T - {% Y% S+ Y0 ?* _
- SET_BIT(FLASHx->CR, FLASH_TYPEERASE);
6 f- ~- d$ w; _) B' C' p - }* h. C4 J6 s) U+ Y! Y- ^' r
- /* @brief Set flash erase ADDR. n- G( k2 l, r e$ t
- * This parameter can be any combination of the following values:
" m4 H0 y% d [" I/ y! U - * @arg @ref EraseADDR uint32_t value2 E( V$ v/ f7 z D* H! i
- * @retval none*/- X9 v; P3 L' {3 d; L9 F8 r& `
- 0 t3 J3 G3 o' s) n+ k
- __STATIC_INLINE void LL_FLASH_SetEraseADDR(FLASH_TypeDef *FLASHx,uint32_t EraseADDR)
( B$ n5 p M( i - {1 }, o; y4 G0 n! h W+ l- V
- WRITE_REG(FLASHx->AR, EraseADDR);8 e: s r1 M3 p& \; ~' L
- }
- D- N6 q% o5 g6 V7 Q - /* @brief Set flash erase ADDR.8 G& T6 }8 E: e5 x8 C
- * This parameter can be any combination of the following values:
d8 P8 b8 l' M' \: o - * @arg @ref EraseADDR uint32_t value" P* S9 L2 S( I) y% ]5 k
- * @retval none*/! S' J" o9 b0 ]0 C! G l0 w" n
- " b) @3 K( k6 C- m2 d! a. V
- __STATIC_INLINE void LL_FLASH_StartErase(FLASH_TypeDef *FLASHx)
$ a7 j9 y. J J! n% I - {8 l+ E2 s( j4 s, X1 A
- SET_BIT(FLASHx->CR, FLASH_CR_STRT);* p* `( x% L; |. ?9 ^/ M$ x% m$ Y
- }1 @0 p3 W* k* }6 c6 n
7 m- k1 X- t; ~# e+ V* ~6 ]- /* @brief Clear the specified FLASH flag.+ K W4 j0 q5 }) d5 L
- * @param __FLAG__ specifies the FLASH flags to clear.
1 C1 G8 R# Q. T. N+ w: c6 `/ c - * This parameter can be any combination of the following values:. U& C$ A( Q2 D" q) m" x
- * @arg @ref FLASH_FLAG_EOP FLASH End of Operation flag 4 m/ o+ v& s/ T }
- * @arg @ref FLASH_FLAG_WRPERR FLASH Write protected error flag . G* }7 ]% W+ Q, I% W7 q: J! D, q
- * @arg @ref FLASH_FLAG_PGERR FLASH Programming error flag* M# O( _! R/ I! o' X. J) |! c3 x
- * @retval none*/6 Q- V) c2 r. r3 V) ~
- % |! g6 s5 p& b# j' H
- __STATIC_INLINE void LL_FLASH_ClearFlag(FLASH_TypeDef *FLASHx,uint32_t STATE_FLAG)
' [" T0 u0 |. I- Y" i! g - {6 A0 R( E% @7 M+ P* k3 V
- WRITE_REG(FLASHx->SR, STATE_FLAG);
4 ]5 f: a U% g3 R z - }
6 `; j0 G( ~" S8 s# Q
6 u: [& ]" b( t- M7 U- /*get bit flash bsy*/ d g" u+ W1 h" ~
- __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_BSY(FLASH_TypeDef *FLASHx)
, ~5 ~6 b9 b8 R" R1 u" W9 z - {3 g) T2 ^6 P4 t2 _& ?+ G- z6 U7 h
- return (READ_BIT(FLASHx->SR, FLASH_SR_BSY) == (FLASH_SR_BSY));
* D6 K' @ U5 b/ d( M - }7 G, W, e; U! y8 s
- /*get end of operation bilt*/
) l/ V9 H( _+ R [ - __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_EOP(FLASH_TypeDef *FLASHx)/ g# g* M0 o2 g
- {9 ^ w# C# k" `0 I3 s2 [2 y( @
- return (READ_BIT(FLASHx->SR, FLASH_SR_EOP) == (FLASH_SR_EOP));2 w. w" ?6 U- W" D4 Y) ]
- }& p- `. k; M7 l" X( w! ]) \& C
- /*clear end of operation bilt*/& B2 A* O8 b; @1 z4 H
- __STATIC_INLINE void LL_FLASH_ClearFlag_EOP(FLASH_TypeDef *FLASHx)
) F' y1 _6 B# X( f4 N - {8 a- d% w" x# ?
- SET_BIT(FLASHx->SR, FLASH_SR_EOP);//EOP bit Set clear& P( U3 Z$ I: O' Q( X
- }; n9 c, b8 q) `' o
- /* @brief Set flash erase type.
+ p$ {' N8 `8 j% ?$ B - * @param FLASH_TYPEERASE specifies the FLASH flags to clear.
4 ?5 V+ x8 q8 O/ A/ N - * This parameter can be any combination of the following values:
) l# |& J( i( x5 p. u7 b" O - * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase2 W, q V9 ~- L. V* P
- * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag
3 y1 j5 z" _$ m! @6 K) P - * @retval none*/3 {, z$ z7 L. Q
- __STATIC_INLINE void LL_FLASH_DisenableErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)9 B' M8 w q% W( v+ |& {" B
- {
5 Z: I+ \7 \7 I2 S. L - CLEAR_BIT(FLASHx->CR, FLASH_TYPEERASE);
5 F7 n K5 g1 ~* n" s; A% I$ x- p3 P - }
2 ^' f+ F0 X: q
2 V) ?0 }% Y2 X4 P5 l- /*EnableProgram*/
) t! Y$ P2 [+ v; h4 Z - __STATIC_INLINE void LL_FLASH_EnableProgram(FLASH_TypeDef *FLASHx)
. h' X- O; L. Q, d# P - {4 Q/ C0 I4 ^: _4 i0 E2 H
- SET_BIT(FLASHx->CR,FLASH_CR_PG);
+ ], S: H: q0 v; @, S' L( e! g% F; R - }5 U/ `9 k8 j8 A% C) V
- /*DisenableProgram*/6 e! }" \& R0 q. D7 Q+ v
- __STATIC_INLINE void LL_FLASH_DisenableProgram(FLASH_TypeDef *FLASHx)
+ \( r0 M+ B/ _9 Q, b- V. Z - {1 O7 k2 b7 q8 W% ^- p) ?
- CLEAR_BIT(FLASHx->CR,FLASH_CR_PG);
+ d" f/ c3 Q0 ?% G - }9 Y. n- V+ \$ |/ A/ ?9 P4 S
- /*read flash's states of lock or unlock*/
6 X- V0 n' k8 J5 `3 ` - __STATIC_INLINE FlashStates LL_FLASH_LockState(FLASH_TypeDef *FLASHx)
9 ~+ ~4 e F' G( M) ]7 N8 S9 U% j - {) ]0 F; ^/ s! k2 k+ G! f0 |
- return (FlashStates)(READ_BIT(FLASHx->CR,FLASH_CR_LOCK));& i4 f' Z8 T. k. Y
- }
' h, h6 Z, V# j- N. Z - /*set key for flash*/* A0 o( J' n5 k" ?1 ]3 Q
- __STATIC_INLINE void LL_FLASh_SetKey(FLASH_TypeDef *FLASHx,uint32_t key)5 a; g0 u& t! h* `6 c9 O
- {7 s, R" N, R' N8 P! F7 G
- WRITE_REG(FLASH->KEYR,key);! h6 Y. o( A* e" d4 }* H
- }6 [4 q- C: ~$ r+ @( a
- . Y7 z& o/ y* v3 _. U2 }
- 4 Q7 A8 R. s( b
- LL_StatusTypeDef LL_Flash_Unlock(void);& h( L9 t8 H& U/ H+ i" f0 w2 t
- LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t NbPages);
$ b! P% M, d. _2 t - LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data);: k! L% P) _. s
- #endif
复制代码 , l) O- Q1 J/ d; L3 ]5 [
C文件代码" ?7 e$ Z4 V, ]. B: x
- #include "stm32f0xx_ll_flash_ex.h"
2 w8 `) J1 u# c- s3 G6 A0 ?: Z6 c' h
) h% Q+ I2 C& K/ w4 j- ) ]! {' Z% t% E# m( C. d3 D
- void static LL_FLASH_Program_TwoBtye(uint32_t flash_addr,uint16_t data)
0 m1 W3 F* b& u* W, c7 n - {
+ U6 G3 s* Q! J - LL_FLASH_EnableProgram(FLASH);5 N$ f2 f+ P$ L7 @0 c+ P9 R
- *(__IO uint16_t*)(flash_addr) = data;
! k- d3 [# D$ D - }
8 h, J8 x8 c$ u) h+ H L- C
* y$ s1 {5 d% g7 T; W* n8 C- LL_StatusTypeDef LL_Flash_Unlock(void)
) |8 u3 i% [. M - {
; t- ]2 Y. ~" F; K - while (LL_FLASH_IsActiveFlag_BSY(FLASH))
$ g) B% p4 g( j' o3 r5 p - {" C' a0 N t3 m5 k9 H
- } 0 r5 z. W, ~' K! ]. {& ? v, \
- if (LL_FLASH_LockState(FLASH)) ( m$ Z. J9 e. a0 Q
- { . Q# o, s6 {' t- L1 J* R
- LL_FLASh_SetKey(FLASH,FLASH_KEY1);9 }$ {$ R! r5 q* p7 P
- LL_FLASh_SetKey(FLASH,FLASH_KEY2);! \3 V% Q+ X/ {6 [% a6 |
- }# N9 G; b- V- |
- return LL_OK;
) v9 |, ~) c, x4 g5 s% V - }
7 F" V& j9 q2 O$ g - 8 w6 d6 O5 }* W# u# \* o& z
- LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t Nb)
, m. _- n/ m9 E8 `0 A - {: ]+ j5 b, @% S; F' R3 E
- uint32_t End_addr = 10* FLASH_PAGE_SIZE +page_addr;
# k W& H' N. D - uint32_t Start_addr = page_addr;/ N) ?$ K8 U: Y. b
- for(;Start_addr < End_addr;(Start_addr += FLASH_PAGE_SIZE))
$ h) K! s. _1 t% P2 w6 `* a# B - {
: M. D s9 i5 w6 B/ r" b - LL_FLASH_SetTypeErase(FLASH,FLASH_TYPEERASE_PAGES);
% V+ e, v, Y# R) V' c$ j - LL_FLASH_SetEraseADDR(FLASH,Start_addr);! D1 K- W- I( Y% s/ }% t
- LL_FLASH_StartErase(FLASH);
8 a. ?% \2 Z4 E" ^& D( n; I* B - while (LL_FLASH_IsActiveFlag_BSY(FLASH))
8 ^ l7 o% V2 w5 V! |: ? - {
1 L3 l0 L' e. l0 ?6 {/ O; \ - } . v& p& ?* F% O
- if (LL_FLASH_IsActiveFlag_EOP(FLASH))
$ Y$ w/ V x9 h, |; r: i - {
# |5 ^) E' c6 D0 P( x" i2 ?9 t" J - LL_FLASH_ClearFlag_EOP(FLASH);; ) A. {# l7 `6 s$ Q' A3 X
- } - D! H6 z0 ?1 ]& l6 q( M
- else
) E9 n$ E% e: ~8 P - { , t+ x+ S3 ]- B9 \
- return LL_ERROR;4 ]$ ^% g9 O3 H+ y+ {
- }
. S% c: u" K# h2 i8 U' O/ u/ e - LL_FLASH_DisenableErase(FLASH,FLASH_TYPEERASE_PAGES);2 _) r8 ?% i6 O1 `- {
- }
' b# M4 [( d$ f" l. e% F: H - return LL_OK;
( f% J$ p. b5 w; T& f3 r1 H - }4 L, }5 e" L+ l, v; a
; \3 g) L2 @3 M8 X. f0 J- LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data)
# q. ~( h! R' O# z3 j2 ` - {
! y8 d( V1 q" L1 T% g1 _ - , Q) q- ~! }$ C( [% @8 J
- uint8_t index = 0U;
s- m8 p+ h" v3 [6 H* C& V - uint8_t nbiterations = 0U;# M/ R$ ?- N2 c) N4 p
-
2 W0 C4 D: K" h9 D6 z5 }1 F+ u - if(ProgramType == ProgaraType_DATA16)
( d) l' Y& f+ z" E+ b, C - nbiterations = 1U;
& ~+ _" w) z7 H4 U0 J6 ]) K# l - else if(ProgramType == ProgaraType_DATA32)
7 o( x5 \, n B# g& p4 R4 D! y7 k/ c- w - nbiterations = 2U;
8 U2 x7 p2 s3 T* g7 Z - else
: |' @! I6 B# U7 q6 a - nbiterations = 4U;6 V8 p6 e7 `' g
- for(index = 0U; index < nbiterations; index++)
6 ?; ~. r. w8 V" ^ - {* K! S c% `+ V5 \) \
- LL_FLASH_Program_TwoBtye((flash_addr + (2U*index)), (uint16_t)(data >> (16U*index)));3 B! c& f( f' Y8 Y4 A
- }
$ m' P2 v% c6 ^% ?" ^; O - % j; i2 v' J1 x4 E. D
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
4 _/ `1 i& b# @) | - {& |0 U. _' p1 J1 @/ D' E
- }
9 ]* w9 S3 }. s1 ^5 e - if (LL_FLASH_IsActiveFlag_EOP(FLASH))
J% F5 `. a3 k - {, o$ {! d. k W7 U3 ?7 n
- LL_FLASH_ClearFlag_EOP(FLASH);
& R5 P: M& H/ b: y8 l - }
/ c0 b' N+ G- S) a7 b, a) k - else, b! v' [) A. ^. j- F4 k4 F2 r7 P
- {
4 O4 v, N1 t+ s" n/ i! c$ u - return LL_ERROR;9 i" M9 m" L1 X! c$ R
- }
6 W1 K2 Q% h( b, x! R7 ]4 ?; S/ z( U - LL_FLASH_DisenableProgram(FLASH);, N- a. q+ s1 M/ I3 m8 j, J+ |
- return LL_OK;
& c! n: G. A' H6 q' i% n: p - }
4 `9 w: V# z" L/ _4 y" p
复制代码
! T' N* y9 {5 D" n8 G6 L6 F
8 _9 S+ x J9 e0 q% l0 g+ f |