不知道为为什么,STM32 LL库并没有FLASH的库函数,于是决定写一个
7 T2 R: w% L5 a1 |; h
% d. z, [5 U. U- M5 m& JLL库的特色,就是一个函数,只占用一个指令周期,比如,设置GPIO输出的状态,就是LL_GPIO_SetOutputPin();
, }. B1 Y! e2 R, G) \: V/ q- ^, l& ?- __STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
* K8 B6 [+ R# m6 \ - {
* t4 Q, T& _/ J: v$ U- L4 [2 ~$ F - WRITE_REG(GPIOx->BSRR, PinMask);2 H$ K. N I0 t' C
- }
复制代码 于是我根据这种风格,已经常用的操作写了一个.h和.c文件9 _5 | z1 E5 D1 L" Z) O
g6 m# C. v6 y( ~' i8 c# z头文件代码5 W) H% i2 M$ j
- #ifndef __STM32F0xx_LL_FLASH_EX_H1 J9 j: j% s$ Y8 I! \
- #define __STM32F0xx_LL_FLASH_EX_H+ s6 ? }# m! M# c+ F6 k
- : G/ S W6 ?+ ^! `. V: Q5 \
- #include "stm32f0xx.h"/ w' Z2 C3 I+ z
- ! ^" j. M8 J6 O/ P
- ( q$ |, x$ f0 y% U* T; ~
- #define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */ 6 d! |+ S2 G' {+ v$ U
- #define FLASH_FLAG_PGERR FLASH_SR_PGERR /*!< FLASH Programming error flag */
0 \1 \; V, e' @4 T; p1 \3 x7 | - #define FLASH_FLAG_WRPERR FLASH_SR_WRPERR /*!< FLASH Write protected error flag */
9 h# T( _% }' Y% ? r. }' A - #define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Operation flag */$ y- k0 l0 p4 \1 v5 t0 J7 E6 N
) t, O. s- d. b- I0 D$ s- #define FLASH_TYPEERASE_PAGES FLASH_CR_PER /*!< FLASH_CR_PER */
. A! Y4 P5 Z# z4 E6 C* B - #define FLASH_TYPEERASE_MASSERASE FLASH_CR_MER /*!< MASSERASE */ O$ M0 X! _1 l) [
! t/ R7 w* @" M/ M) {4 T/ j5 t5 R0 x
1 g. }% ^% p+ c* o5 S- #if defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F031x6) || defined(STM32F038xx) \9 e$ o, g) `7 v" U& S9 U
- || defined(STM32F051x8) || defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F058xx) || defined(STM32F070x6)
6 O6 w. _3 F4 `0 ~( d - #define FLASH_PAGE_SIZE 0x400U
9 ^" ]2 n4 `$ w - #endif /* STM32F030x6 || STM32F030x8 || STM32F031x6 || STM32F051x8 || STM32F042x6 || STM32F048xx || STM32F058xx || STM32F070x6 */
2 a! K0 i* }: y! b! W - - _ B( L: J9 h3 S& N
- #if defined(STM32F071xB) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F070xB) \
8 @) K. o' E' L2 k n - || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC) i. d; w9 c; P: J6 `
- #define FLASH_PAGE_SIZE 0x800U
5 Q. d( [2 t: m1 A; G; S - #endif /* STM32F071xB || STM32F072xB || STM32F078xx || STM32F091xC || STM32F098xx || STM32F030xC */: o Y3 ?6 B. e2 a
- 9 ^4 ?0 D! V& }3 V
- typedef enum {
- e8 U4 {: z; h1 H( y& e - ProgaraType_DATA64,
; d% f5 ^/ q- i2 q& u; T( [: W - ProgaraType_DATA32,
8 X# s9 U. E6 k - ProgaraType_DATA16
' Z* K; d; i& ]; N6 q+ J - }ProgaramDataType;, U- v8 O9 E3 l7 R) D1 v( r% p
^8 e" r- {( ` B) o4 W+ Z, B8 U- typedef enum {\
* G* b! C" W; C, t z - FLASH_Lock=1U,Flash_Unlock=!FLASH_Lock\2 Q$ D6 \; F! V& ~: a
- }FlashStates;8 P! y9 \4 r. N- d* I' Y" C' b, Q" F
- 0 h. N# T, d. C
- /* Set the OBL_Launch bit to launch the option byte loading */
/ |# r# {! u7 i1 a% G& M/ p - __STATIC_INLINE void LL_FLASH_SET_OBL_Launch(FLASH_TypeDef *FLASHx)& _% y% ]: V1 G
- {
, A3 G. O' M* }$ W$ ? s0 O - SET_BIT(FLASHx->CR, FLASH_CR_OBL_LAUNCH);
8 r3 B) Q6 t* V& [3 Q - }+ W9 O9 U% B2 v& Q5 r7 d
- __STATIC_INLINE void LL_FLASH_Lock(FLASH_TypeDef *FLASHx): e8 L1 K8 a: Z; c, q1 ]
- {
4 R1 c. [+ m# g0 \ - SET_BIT(FLASHx->CR, FLASH_CR_LOCK);
3 N* A( O' ^) ], ]$ v - }) h' Y* ]+ T8 x$ ]0 |0 k7 f. P
- , q6 u9 n- Y5 t
3 {4 {4 i( p3 u* t0 @- /* @brief Set flash erase type.
! l6 R0 r2 p& q% Y: s+ l - * @param FLASH_TYPEERASE specifies the FLASH flags to clear. _& _* d/ [7 y) D$ r' c) c
- * This parameter can be any combination of the following values:" j. {: S! X" @$ R {2 V( q
- * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase4 D8 p. `4 B/ Q1 U0 u
- * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag . R: u; e/ f- ]6 ~' h
- * @retval none*/4 U5 y$ J$ t; ?9 P) w
8 A/ d! t4 t: S- __STATIC_INLINE void LL_FLASH_SetTypeErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)
: q$ `' X" ?2 m; T - {
" m- z( Z* V) K$ e$ }2 M - SET_BIT(FLASHx->CR, FLASH_TYPEERASE);
* R- f# C: @- k$ k4 S - }
2 h) f+ t$ f h" U: b& O) C - /* @brief Set flash erase ADDR.! c% O2 k! s! j/ f, }
- * This parameter can be any combination of the following values:% y0 |3 g8 D0 [7 X W7 X8 \
- * @arg @ref EraseADDR uint32_t value/ X, P4 B Y9 ]+ O" g
- * @retval none*/
3 U4 X6 [2 Z* w- x2 x0 S
. }; n+ L% \1 G# x* Q4 V! ?- __STATIC_INLINE void LL_FLASH_SetEraseADDR(FLASH_TypeDef *FLASHx,uint32_t EraseADDR): P, e. n2 b2 g1 @ O
- {+ [0 L, M Z- [( P# c
- WRITE_REG(FLASHx->AR, EraseADDR);
. t3 [* o; e$ z% I - }; ]; X7 ]4 h' @( w4 Q n- u
- /* @brief Set flash erase ADDR.
' T( B& c6 N8 v' _ - * This parameter can be any combination of the following values:1 b9 t; l* d" H U9 W
- * @arg @ref EraseADDR uint32_t value$ N- D, l) U" o# T# t4 S( C
- * @retval none*/
O% Y" H# v* d! ~7 Q! D- T - + o+ u1 f7 p( X. }
- __STATIC_INLINE void LL_FLASH_StartErase(FLASH_TypeDef *FLASHx)
/ r3 P- g4 m" n2 F - {6 Y: D/ O# |& X' z0 A7 \ Y
- SET_BIT(FLASHx->CR, FLASH_CR_STRT);7 m! d3 B- e. r* `7 }5 b
- }
! M D. M. @4 B& K. i+ O - " B! `( ]0 R5 K1 a+ N" V+ i
- /* @brief Clear the specified FLASH flag.5 ~1 H. Z& d: D5 P/ V. k/ q: P9 }
- * @param __FLAG__ specifies the FLASH flags to clear.
, n2 z2 ~. G; v( I, P* I - * This parameter can be any combination of the following values:( V4 L7 Y3 e: H: t3 Z, P$ t
- * @arg @ref FLASH_FLAG_EOP FLASH End of Operation flag * {7 {9 F( q$ D# V# W6 ~ n
- * @arg @ref FLASH_FLAG_WRPERR FLASH Write protected error flag
5 T/ P; G+ D. m - * @arg @ref FLASH_FLAG_PGERR FLASH Programming error flag& g9 N- n) g. Z' [
- * @retval none*/
! D$ h+ e, Y5 m- M
# M2 h) ~9 [2 F1 ~. I, G7 n) j- __STATIC_INLINE void LL_FLASH_ClearFlag(FLASH_TypeDef *FLASHx,uint32_t STATE_FLAG)! ^5 h, D) M) x0 Q) H1 V% z4 q& U
- {+ K5 k1 U; E) G+ ~1 m
- WRITE_REG(FLASHx->SR, STATE_FLAG);
& O% z1 l1 A) n* t% H" ?9 v - }
0 t" N9 X: O( {/ C, ~ - ) h! b7 D% s- h
- /*get bit flash bsy*/
( ^* a' T2 n2 ^# w9 G; z* ? - __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_BSY(FLASH_TypeDef *FLASHx)
) _ a( Y2 j: @: w/ u' _# { - {5 O% i! m! N1 _
- return (READ_BIT(FLASHx->SR, FLASH_SR_BSY) == (FLASH_SR_BSY));$ U6 ]1 f) C. q( u9 [ C
- }
- h2 ~7 a# W Z" c - /*get end of operation bilt*/
* u. Y5 y# T! ~. v - __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_EOP(FLASH_TypeDef *FLASHx)$ I$ \, r, b9 D) y
- {8 X* l; G* ?; q# T# S1 ]8 l$ k
- return (READ_BIT(FLASHx->SR, FLASH_SR_EOP) == (FLASH_SR_EOP)); d G' B" j" D3 |. @! }0 g5 g3 M
- }
4 n0 V0 B0 r% c: u; S2 Z - /*clear end of operation bilt*/
' N% u! ~- ^9 Z# l - __STATIC_INLINE void LL_FLASH_ClearFlag_EOP(FLASH_TypeDef *FLASHx)8 p& z- A2 @1 D% l2 f; a/ q8 n
- {8 y) E# l9 X( V m& |& O
- SET_BIT(FLASHx->SR, FLASH_SR_EOP);//EOP bit Set clear
$ ~* o; k4 }# D+ \* [ - }
$ ]6 g r8 _ V - /* @brief Set flash erase type., ?% P8 h' I( K" X5 c0 E" g6 l
- * @param FLASH_TYPEERASE specifies the FLASH flags to clear.
; [: @$ M, e4 G" f - * This parameter can be any combination of the following values:6 P6 F# d! j e
- * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase6 \; @2 w! V" s
- * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag
# _ i% B' T7 e: B+ }! W - * @retval none*/: S R3 P3 w# u
- __STATIC_INLINE void LL_FLASH_DisenableErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)
" u1 i; p* `8 i3 X - {
5 F/ I F8 l3 j7 F! j1 }" e' A - CLEAR_BIT(FLASHx->CR, FLASH_TYPEERASE);* e4 K ~! b' E4 {$ x8 b* ^
- }& i! w3 t) e5 f- Q" \
r$ c$ H: G7 f9 Y& r3 D1 F- /*EnableProgram*/
' E. \! E" D: ?5 I - __STATIC_INLINE void LL_FLASH_EnableProgram(FLASH_TypeDef *FLASHx)& I1 W5 @) L- Q& Z6 C
- {: }, H# ]# L8 \- E- T9 f- V
- SET_BIT(FLASHx->CR,FLASH_CR_PG);1 O3 W4 x3 _ o7 | i h# u F& V% L
- }
i2 p3 J$ I7 m2 { - /*DisenableProgram*/! N9 m+ `1 I) U X, B" `
- __STATIC_INLINE void LL_FLASH_DisenableProgram(FLASH_TypeDef *FLASHx)
* l4 u U: }- ~" [% @( h5 D$ l - {1 o. U9 q) R* a* ~
- CLEAR_BIT(FLASHx->CR,FLASH_CR_PG);
9 B5 z3 M/ X# S( t: C& n - }
3 C7 q1 t8 q; s$ t - /*read flash's states of lock or unlock*/1 I' Q4 }1 r8 l/ Y0 O1 ]
- __STATIC_INLINE FlashStates LL_FLASH_LockState(FLASH_TypeDef *FLASHx)
) `$ h0 T+ @' ~ Y% P! f - {9 `, P$ [5 z. ]& J0 @
- return (FlashStates)(READ_BIT(FLASHx->CR,FLASH_CR_LOCK));
4 a- u6 y, n$ X1 P6 B - }
4 W) e$ m5 j# H* R* r: J - /*set key for flash*// f. N0 J" Q. Z% b3 V+ {
- __STATIC_INLINE void LL_FLASh_SetKey(FLASH_TypeDef *FLASHx,uint32_t key)/ H* L4 F$ F6 h, f7 j+ p
- {! s8 f1 r2 G# j5 M$ h
- WRITE_REG(FLASH->KEYR,key);
7 Z. E: X6 Z4 b! E( y C - }
8 r7 a; ?% }! b0 y& z& M N
+ i3 d, v/ f- P! Z
+ X& M, X( K: R; f- LL_StatusTypeDef LL_Flash_Unlock(void);; ] d8 d1 n; R& o
- LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t NbPages);
- h# U- t% u9 K7 O1 t8 G - LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data);
% P% [, C# Q3 t - #endif
复制代码
& s# T$ @5 \3 Z& I; z" AC文件代码- a! d( a$ o' P; t9 w7 N
- #include "stm32f0xx_ll_flash_ex.h"3 G- f- e2 O5 _. K
% g2 n& o2 k2 U4 O1 B2 D" t' H- 0 h. D" e; K. Z( N
- void static LL_FLASH_Program_TwoBtye(uint32_t flash_addr,uint16_t data) m' |# o* y- t4 W" p i
- {
' B5 c4 g. E$ p - LL_FLASH_EnableProgram(FLASH);% i |" [: U* V
- *(__IO uint16_t*)(flash_addr) = data;5 W4 \, Z. G, z! |1 c4 j L+ g
- }1 m" `9 u( d) j9 u/ d# u
- Y9 g" S- q, o& t2 R- LL_StatusTypeDef LL_Flash_Unlock(void)
7 n3 Q5 K; T, G# G# J% i! E - {% _ l, H& Y. _; N3 ~
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
( i+ T T& E: N% h. p - {
2 K1 y1 m- I5 l( U% s* o - }
- g. N7 X$ @4 F% ^5 s - if (LL_FLASH_LockState(FLASH)) ! a# g9 x* S8 u' L
- {
; |1 P8 X5 X# A# S5 h - LL_FLASh_SetKey(FLASH,FLASH_KEY1);% b* E! V1 X; r( U
- LL_FLASh_SetKey(FLASH,FLASH_KEY2);
' z' [/ G. l& Q2 z - }
# J6 d$ N3 e i w8 r5 W6 N - return LL_OK;
3 z! a6 j8 s( h5 ?& R/ e - }, B' J. U$ ]4 x1 D- x) `
, p: o H6 R8 x8 Z- ^7 ?/ \- LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t Nb)8 G+ c+ N1 d1 b4 {. a1 W! n
- {
K! \3 T7 ?: w! Y6 G - uint32_t End_addr = 10* FLASH_PAGE_SIZE +page_addr;
, g! v% ], q) l/ w2 L$ I+ r3 E - uint32_t Start_addr = page_addr;6 c2 @( g/ ]8 n: w0 P" O
- for(;Start_addr < End_addr;(Start_addr += FLASH_PAGE_SIZE))5 c: d* k; V% p0 o
- {9 H: u/ s4 G" c6 u2 t
- LL_FLASH_SetTypeErase(FLASH,FLASH_TYPEERASE_PAGES);
7 x* |# V- R* B6 K: [ - LL_FLASH_SetEraseADDR(FLASH,Start_addr);' u8 F) s2 J$ M2 ~ b
- LL_FLASH_StartErase(FLASH);
( S8 j% C8 P4 j; f - while (LL_FLASH_IsActiveFlag_BSY(FLASH))
) t2 O; S8 C# I0 \2 I: |8 J+ t - {
+ t. w9 K' _+ K* n- n. `( {5 F - }
( \! ]' j) ^' K9 Z - if (LL_FLASH_IsActiveFlag_EOP(FLASH)) ; R7 ~3 E$ d" `) K7 [5 V
- {
. q5 y0 y& y8 c$ ] - LL_FLASH_ClearFlag_EOP(FLASH);;
) W0 g; `/ o, U# z - }
3 t$ \3 q4 W- h3 a0 ~ - else
n9 S* T* ^* T - { % ^% i1 Y, D/ V$ j# g* y" w" ?
- return LL_ERROR;
7 [1 m+ ?; K B" J - }
3 z1 ~; b7 M) U* w4 [ - LL_FLASH_DisenableErase(FLASH,FLASH_TYPEERASE_PAGES);2 c* c, c: U+ N+ E! ]
- }
8 H2 k) B3 g* {/ }0 L' r ?" x8 L+ A - return LL_OK;: @/ w2 a& B. N* ~8 {
- }
, B! S' }& W9 n. s5 _ o3 d - ( ]% g- G) z7 f1 G/ j: [9 U
- LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data)
, V4 h0 ?2 Z7 p1 Y) N - {
% Y0 y- J7 [' y" _5 O: ^ -
9 q- R: M9 d. E% U! D5 ?9 B+ D5 u - uint8_t index = 0U;5 B `; B2 m! x) v- N
- uint8_t nbiterations = 0U;+ x1 C) a$ `& U6 P% ~) L) }: K7 l- S
- : L3 r) _" q2 k0 G6 X' s6 ?/ S
- if(ProgramType == ProgaraType_DATA16)
* Y* P9 B: b) I' I5 V - nbiterations = 1U;- w4 H8 f. a/ a2 w) L; m
- else if(ProgramType == ProgaraType_DATA32)3 g1 e+ T! m5 L# ]& q( F7 j o
- nbiterations = 2U;
) _! O/ ~0 B# ?. u+ o! ] - else1 z7 K& I9 U3 k& ]2 c Y' |
- nbiterations = 4U;% a. R2 p9 o# S
- for(index = 0U; index < nbiterations; index++)
7 F0 C4 b) F0 @- ~# v" \ - {
) C7 ?! `& n+ t& Q - LL_FLASH_Program_TwoBtye((flash_addr + (2U*index)), (uint16_t)(data >> (16U*index)));
2 w+ U# F$ j3 g# ~, o* i - }+ G( H' f Q( r* P2 \
- 6 t" w) ] j! J. x2 I
- while (LL_FLASH_IsActiveFlag_BSY(FLASH)) # Q* a+ J; s$ P0 U
- {
7 Z( y9 @) O3 }7 R9 C* G - }9 P/ r) m# G7 R8 A1 e+ Z; _
- if (LL_FLASH_IsActiveFlag_EOP(FLASH))
9 t* d" |: m0 D+ N9 C - {
" W7 Q6 ]2 L( d/ V7 c3 y& h - LL_FLASH_ClearFlag_EOP(FLASH);
/ r% ~0 l: s8 e. u S; E - }) ~+ q% m6 R/ |9 I5 P0 H
- else
3 J. e" L( o9 t - {% H$ r; C- |, d) P) R, l1 H$ X0 {
- return LL_ERROR;: w1 d# v) U! n8 \
- }
/ U! o" f( r! B) ]. i - LL_FLASH_DisenableProgram(FLASH);4 _+ Z. q* M" y9 j
- return LL_OK;
* T2 ], J" h, A( D" A- f - }
9 n6 u# N2 f1 a/ b% w
复制代码
8 O2 w. f/ z5 p; Z( m# M" q: F# F# R( z& ?- ~) q1 B
|