不知道为为什么,STM32 LL库并没有FLASH的库函数,于是决定写一个; N+ g4 z% Q" @! O
2 r. w1 |" Z3 V/ x0 q ALL库的特色,就是一个函数,只占用一个指令周期,比如,设置GPIO输出的状态,就是LL_GPIO_SetOutputPin();; u# J; i2 a) U( I
- __STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
8 n. E" [( X5 ^ - {6 ^& p# B' p* v f
- WRITE_REG(GPIOx->BSRR, PinMask);
* F1 A2 r" j# W3 n - }
复制代码 于是我根据这种风格,已经常用的操作写了一个.h和.c文件9 I8 _! G; e4 b9 U( r( P
5 S Y9 M m0 {/ U, }1 a
头文件代码$ T0 h P& j% W
- #ifndef __STM32F0xx_LL_FLASH_EX_H* Y o% z. X9 X L) B
- #define __STM32F0xx_LL_FLASH_EX_H
$ F6 m1 S# T- M) n0 d' O
6 Q. a' n! M# ^1 G" _/ i# m! j0 q- #include "stm32f0xx.h"( [* u' a: V) O6 a5 o8 N$ P
9 Z, g4 l$ q* Z- 8 Z2 z6 i& }1 V' G* |4 b
- #define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */ ) c+ i6 a4 D. p. R6 a
- #define FLASH_FLAG_PGERR FLASH_SR_PGERR /*!< FLASH Programming error flag */
) F; P" a! k7 y+ l - #define FLASH_FLAG_WRPERR FLASH_SR_WRPERR /*!< FLASH Write protected error flag */
9 Y" @/ T! b: ]9 D5 B - #define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Operation flag */
/ u: N6 {/ d$ [# C! R: p$ K. C - 8 U" f( y9 d/ I2 S( @
- #define FLASH_TYPEERASE_PAGES FLASH_CR_PER /*!< FLASH_CR_PER */
$ t; q9 B! C o$ [- @' w - #define FLASH_TYPEERASE_MASSERASE FLASH_CR_MER /*!< MASSERASE */0 |1 v6 j( \: S9 N2 ?, ?# D+ D {
- 0 a+ Y( I6 C- _# ^' ~5 N
- # ^1 C3 C4 n. q# `: Y- H2 c. H
- #if defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F031x6) || defined(STM32F038xx) \
2 i5 y- d3 A1 D) O9 j* A, T, a - || defined(STM32F051x8) || defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F058xx) || defined(STM32F070x6) s) P9 }+ r8 L: p) R% q
- #define FLASH_PAGE_SIZE 0x400U5 A9 W- D! X$ |% e0 o. F4 u9 r
- #endif /* STM32F030x6 || STM32F030x8 || STM32F031x6 || STM32F051x8 || STM32F042x6 || STM32F048xx || STM32F058xx || STM32F070x6 */
0 a @: e0 x8 I8 p0 N' u
' P, H4 R/ A" Z) l- #if defined(STM32F071xB) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F070xB) \% z9 c! |4 ^( \
- || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC)' |5 k( j! h: N& q5 p
- #define FLASH_PAGE_SIZE 0x800U
; C t2 c% i. x! i - #endif /* STM32F071xB || STM32F072xB || STM32F078xx || STM32F091xC || STM32F098xx || STM32F030xC */
' W7 C) s7 z7 I5 Q( D - 2 m7 t' u8 H- N0 G8 P6 b/ u
- typedef enum {7 K+ L7 R" Y6 z- ~
- ProgaraType_DATA64,$ V+ U; x1 }# k" L5 ~! o
- ProgaraType_DATA32,
) q: Z, l) v s4 K5 d+ B( ]- ` - ProgaraType_DATA16& V4 D/ T3 Y' t) |
- }ProgaramDataType;
8 q9 D9 Z O. i7 Z. R, u( o9 H9 p8 i - ( x# e; E) k7 e" P% @
- typedef enum {\$ z3 ]% Z, U! z0 Z) x6 m1 S! J7 H
- FLASH_Lock=1U,Flash_Unlock=!FLASH_Lock\$ E) r. E2 D, i0 t5 ^, K2 i' c5 |
- }FlashStates;) U9 P( l% }5 e4 f6 e; [3 s
- - t" ]* m7 y i2 y, p4 @2 H1 U2 z
- /* Set the OBL_Launch bit to launch the option byte loading */
9 \$ }9 r8 K. U - __STATIC_INLINE void LL_FLASH_SET_OBL_Launch(FLASH_TypeDef *FLASHx); `/ ^" b8 N+ J2 s, q$ s9 h
- {" X8 e+ S! W# n8 L0 B% H
- SET_BIT(FLASHx->CR, FLASH_CR_OBL_LAUNCH);
* v" _# L E, N - } I/ ~, ]" `8 |+ ]: T
- __STATIC_INLINE void LL_FLASH_Lock(FLASH_TypeDef *FLASHx)
6 c! H; a& I4 S6 _8 Y - {) a; h% `6 I; T' ?
- SET_BIT(FLASHx->CR, FLASH_CR_LOCK);8 ^$ ~! \ U- u! z' R6 W+ a7 P
- }- s# E" r$ F2 T& z& O
1 \7 e% q0 {) P# o n7 {5 F5 V9 j- ' }, P& V5 w/ \0 b, m) h9 a6 ?
- /* @brief Set flash erase type.
* t$ M; l# E% E/ b, ` - * @param FLASH_TYPEERASE specifies the FLASH flags to clear.
?, E. ~" m8 u - * This parameter can be any combination of the following values:( q: v; c ] ]% J6 X
- * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase! e: x1 [4 B# d4 Q/ L
- * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag
1 l: L) n# @( @ G$ C - * @retval none*/
" I: M8 B/ W& W3 u0 @. j
2 _/ }& p- {$ p8 P( [" ^( r* a1 h- __STATIC_INLINE void LL_FLASH_SetTypeErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)
" D9 n. @: f9 D1 j7 r8 [5 L - {
! y* N+ E0 _& M, V+ I - SET_BIT(FLASHx->CR, FLASH_TYPEERASE);, O) v- B% P) c; |. h' H
- }
& L6 `3 L( X. U2 `/ S; z: w - /* @brief Set flash erase ADDR.
, a4 r7 v5 P3 Y8 B7 o# Y - * This parameter can be any combination of the following values:# h0 W/ g+ F& Z4 E; p
- * @arg @ref EraseADDR uint32_t value
6 K* _4 E/ m4 v - * @retval none*/2 D- ~3 k- X& w9 h K/ q
8 ^4 i. ^5 \7 a! f0 Z U( C- n- __STATIC_INLINE void LL_FLASH_SetEraseADDR(FLASH_TypeDef *FLASHx,uint32_t EraseADDR). m5 D- h$ I5 Q! @
- {6 s7 i# C2 {6 O
- WRITE_REG(FLASHx->AR, EraseADDR);, _) s5 D+ Y. O6 }$ e4 q
- }
\# C6 r5 B% q$ J6 @ - /* @brief Set flash erase ADDR. i/ z1 }5 b& z0 i, `$ r* F0 q
- * This parameter can be any combination of the following values:. P, p* C N$ h% M& {& [: P! B
- * @arg @ref EraseADDR uint32_t value
6 V, L7 y* J) ? - * @retval none*/ c: [) `/ y& Z9 I* x/ W% e; w
- 0 a- t; e6 J h% n4 l5 y
- __STATIC_INLINE void LL_FLASH_StartErase(FLASH_TypeDef *FLASHx)
# D- d" X7 S" H8 I7 W9 i# c' S - {
- i2 L- O2 l O* S; Y% ~ - SET_BIT(FLASHx->CR, FLASH_CR_STRT);( Q) I) f7 f% O5 B
- }9 g, ~! u% R% m( Y* M" e
- 2 y5 _9 r3 I1 V/ l
- /* @brief Clear the specified FLASH flag.3 o1 i8 }6 k9 d
- * @param __FLAG__ specifies the FLASH flags to clear.
5 z0 _ g# N. o6 O9 Q - * This parameter can be any combination of the following values:
3 M; W! T: T: V- i$ ^$ k - * @arg @ref FLASH_FLAG_EOP FLASH End of Operation flag
- e4 A& D$ `: M0 s: F: x - * @arg @ref FLASH_FLAG_WRPERR FLASH Write protected error flag
9 G; N8 {3 b' }; p# Z+ A# B$ P - * @arg @ref FLASH_FLAG_PGERR FLASH Programming error flag
1 N* a; p9 p) F& R! u- c. G - * @retval none*/
! {, x; J5 {( y# p, o4 u7 s
% f% T/ Q/ |4 J! T- __STATIC_INLINE void LL_FLASH_ClearFlag(FLASH_TypeDef *FLASHx,uint32_t STATE_FLAG); W7 p% s1 }: m+ L. F. ?$ Z. Y
- {
1 `9 D4 e+ U* R7 m9 J, m5 s - WRITE_REG(FLASHx->SR, STATE_FLAG);: A/ ~3 `( M/ b$ j- [* @( @
- }) H+ f8 x5 v* l6 h% W. j
" c! K1 f9 T' g. H* {) X- E4 |- /*get bit flash bsy*/
% u8 \) n. m' m( n9 w; P/ q& g* q - __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_BSY(FLASH_TypeDef *FLASHx)
; i( Z+ F0 Z4 I# | - {
" m: a6 M- n* K0 Z - return (READ_BIT(FLASHx->SR, FLASH_SR_BSY) == (FLASH_SR_BSY));
4 a' V, {: ^3 H7 W - }
8 b6 O6 Z9 t9 W, l. |7 g, w - /*get end of operation bilt*/
4 Z) x* X* [, d+ J' b( \, k - __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_EOP(FLASH_TypeDef *FLASHx)0 N% h8 f& Q; C+ L% @8 m
- {/ d6 q) `9 l. Z- p1 b1 b
- return (READ_BIT(FLASHx->SR, FLASH_SR_EOP) == (FLASH_SR_EOP));
6 _5 @) o+ P7 j% t - }& {6 O! h6 N* q; O4 I4 I
- /*clear end of operation bilt*/; t0 n' V l% I0 h! o
- __STATIC_INLINE void LL_FLASH_ClearFlag_EOP(FLASH_TypeDef *FLASHx)6 q/ p+ j+ w- {8 m
- {4 Y, A. M1 N1 T5 q% n
- SET_BIT(FLASHx->SR, FLASH_SR_EOP);//EOP bit Set clear0 H! {6 m5 |$ a0 M% ]
- }. e5 a3 w5 Q4 d& b' `& C+ W
- /* @brief Set flash erase type.
, J/ \# |+ M4 Y - * @param FLASH_TYPEERASE specifies the FLASH flags to clear.
2 [; d* S) u( |% F1 v - * This parameter can be any combination of the following values:2 G, T5 a8 X5 S5 K# }& i+ p' S: g
- * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase
6 {2 e6 b$ D8 |, j) S - * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag
5 J3 t& b1 l* z& ^. C - * @retval none*/* M5 n' r& Q' G7 e4 |1 l4 y8 a5 s
- __STATIC_INLINE void LL_FLASH_DisenableErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)' i) B" Y0 c$ c) i( A4 u
- {6 X! Q2 G4 q, _9 e+ c! x9 J
- CLEAR_BIT(FLASHx->CR, FLASH_TYPEERASE);
+ x, ~; t, }! D. X$ y& x: | - }) I" j* m9 s* I
( p. n% v2 k* N& \) h3 n6 ?: h- /*EnableProgram*/* u3 Z, z' a; q' `! I6 ]8 Y6 J( ]
- __STATIC_INLINE void LL_FLASH_EnableProgram(FLASH_TypeDef *FLASHx). n/ `( Z% q0 p3 K; @3 K
- {
! |/ V1 ?0 R* z' _ - SET_BIT(FLASHx->CR,FLASH_CR_PG);% Y- z# Y9 [/ z2 A
- }
( y! @$ g' Q0 C; i# S8 R! z - /*DisenableProgram*/
$ e3 U+ [1 w0 q1 _ - __STATIC_INLINE void LL_FLASH_DisenableProgram(FLASH_TypeDef *FLASHx)
6 ?3 ^9 L) v3 i( O - {
# g# f! h( e, W* ^/ U G& P+ W - CLEAR_BIT(FLASHx->CR,FLASH_CR_PG);
. \1 e9 W X7 h1 \ - }6 P; d1 U2 x ]
- /*read flash's states of lock or unlock*/
1 O4 ~$ Z6 L0 |8 ~/ c6 t7 M G - __STATIC_INLINE FlashStates LL_FLASH_LockState(FLASH_TypeDef *FLASHx)! t! x/ I- q8 [ r& o
- {
" D7 s3 ]2 I8 Q* \ - return (FlashStates)(READ_BIT(FLASHx->CR,FLASH_CR_LOCK));- F6 y) X9 \; B, X2 C5 q8 I7 }8 j
- }
8 W6 Y% [8 q0 D - /*set key for flash*/
s! t( x Z% E' a - __STATIC_INLINE void LL_FLASh_SetKey(FLASH_TypeDef *FLASHx,uint32_t key)
+ E* G' H. R& A: q4 s - {* O% ?1 O+ R/ X6 w
- WRITE_REG(FLASH->KEYR,key);
$ G3 Y6 P3 C$ @ - }
S$ P6 o+ q3 ?& h - 2 {$ w7 L" p# `3 J* i6 [/ J/ e8 E
- : q: u2 P: X* w3 [
- LL_StatusTypeDef LL_Flash_Unlock(void);. N+ S' l- m( o$ c3 D" Z
- LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t NbPages);
! A% { e7 V* a$ n. M# Z ` - LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data);$ F% w" }* r/ e) f+ u" u
- #endif
复制代码
, p( E" V/ {1 b7 H! t: M% iC文件代码3 k$ n0 C; \, c
- #include "stm32f0xx_ll_flash_ex.h"
% I j: k- Y# O, e. ?9 O0 Q/ y - ( M, H9 O9 ~& I1 g' b5 }
- / T& X% ?* d, E+ P# L" R0 C
- void static LL_FLASH_Program_TwoBtye(uint32_t flash_addr,uint16_t data)9 I9 h; E/ g. z/ p. E! w
- {6 P5 P9 R( ]( D" y) I
- LL_FLASH_EnableProgram(FLASH);
+ a8 U# l0 f; w" N. x - *(__IO uint16_t*)(flash_addr) = data;
/ i* `. L B# ]) ]- r+ C - }2 q! b+ [4 j% M3 {7 C, ]0 P1 l( T
- + T) B" `' A2 D) Q$ W
- LL_StatusTypeDef LL_Flash_Unlock(void)
6 n) Z# G; M3 U) `9 W3 n2 ]$ T - {+ @7 W0 g" `' O6 `) S) K
- while (LL_FLASH_IsActiveFlag_BSY(FLASH)) 8 C* I/ W S( V! K% h
- {
. \1 G# B7 F, }5 N! W5 E& z0 Q* b8 K: \ - }
: ~( \3 i/ C0 @0 R - if (LL_FLASH_LockState(FLASH)) V3 ]6 Q9 I; C6 {. Y) G
- { ' ^7 B E: C! I; B5 m3 j5 m" Q
- LL_FLASh_SetKey(FLASH,FLASH_KEY1);
! _/ c; F4 g7 p+ k- |5 { - LL_FLASh_SetKey(FLASH,FLASH_KEY2);
+ I# P: Q5 \) v8 U/ Y. v o2 @! _ - }
) `, b6 ]0 C7 `2 G - return LL_OK;
/ n- J& Y4 u) P% f7 V0 P - }
6 q# v( ^. s* M6 s3 B% Y$ u$ _ - - u/ q7 L& N3 y$ b6 Q, o
- LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t Nb)( ?) f4 X3 o0 I; j$ G' c5 u, v$ g
- {! p; _" z( `5 H$ f8 j
- uint32_t End_addr = 10* FLASH_PAGE_SIZE +page_addr;
( ?3 k3 Q* X& M' p - uint32_t Start_addr = page_addr;
( p# p8 k9 U' q" F. w% ? - for(;Start_addr < End_addr;(Start_addr += FLASH_PAGE_SIZE))# N+ a* t9 Y! n8 C( f5 z/ @. Z: W a- s
- {
2 g6 f3 }4 U3 L9 w9 p - LL_FLASH_SetTypeErase(FLASH,FLASH_TYPEERASE_PAGES);5 y6 N6 G# i0 C& }
- LL_FLASH_SetEraseADDR(FLASH,Start_addr);
' j6 T. b% ^& x; @) _7 o" o - LL_FLASH_StartErase(FLASH); $ k* n4 }9 P" J' j3 p" o$ u7 X
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
1 M1 w6 Z2 N" \# a0 v* r4 d - {
6 f2 n4 R& K, d# ~ - } j. g( Z- S* m# G! ]" \
- if (LL_FLASH_IsActiveFlag_EOP(FLASH))
$ l2 k2 _% K+ d- m) M, Z - {
& l+ Q" w% F; ]1 [ \. D3 Z+ p - LL_FLASH_ClearFlag_EOP(FLASH);; 3 R: }2 A' t* [1 C
- } % x$ q+ l6 Y- S0 T$ N
- else2 n. k0 {# Y6 X8 b5 y# D
- {
$ a6 |/ k- l2 I) ] C' G' C" Z% F! R/ B. T - return LL_ERROR;, v" E7 h% Y( v
- } q. W! l% t- l; t
- LL_FLASH_DisenableErase(FLASH,FLASH_TYPEERASE_PAGES);
% B1 W- Q" v( u B3 n- Z" z$ p - }
# J4 c( h- J/ t* z, J! C" H - return LL_OK;, I0 J' }2 Y7 y% }& Q4 k- _6 I
- }) m5 n6 h8 ]! R- _, g* {
- ) q# ?$ ?9 y8 g4 r! d8 b
- LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data)2 }) F6 a8 M/ W
- {& h0 O* T' F0 V2 U7 U
-
( _/ S8 z( B& f' j ]' q9 g/ y - uint8_t index = 0U;
" s: z9 r& e4 Q# t1 n7 |1 j - uint8_t nbiterations = 0U;
\0 Q2 g. l: c* H4 t -
' f. { ^, F4 e( [7 G1 F6 f9 R - if(ProgramType == ProgaraType_DATA16) j8 ^5 A, @* C% j" w
- nbiterations = 1U;
6 J8 N1 O" C" h, z7 G6 G. | - else if(ProgramType == ProgaraType_DATA32)) _9 O& q- o% m$ r# k: N
- nbiterations = 2U;
5 e4 k6 ^9 q! b% A! c% |$ s9 Z2 X u - else
) X4 \8 t- I5 H2 M# f - nbiterations = 4U;! S7 P3 j, U: u# [1 ~4 G" i
- for(index = 0U; index < nbiterations; index++)( o- G( i0 h% W9 b! t' M; i: S# Q% t7 a0 Q
- {8 l* P9 W9 W- c& N% P5 \: {6 A7 t
- LL_FLASH_Program_TwoBtye((flash_addr + (2U*index)), (uint16_t)(data >> (16U*index))); V% \( `2 n/ K; p$ i/ g5 e
- }- F4 F, k/ } f. i, K
-
/ d. c: v4 V* X7 _$ f W& B: }8 F - while (LL_FLASH_IsActiveFlag_BSY(FLASH))
7 A3 s! u5 Q' ~, o - {
8 q0 Z/ r. ~; T( N, s. N5 h - }
' i& y4 j) _, x. G6 T - if (LL_FLASH_IsActiveFlag_EOP(FLASH)) $ j5 t8 w# {5 A# M; B+ L
- {
/ M1 q' q: @4 L - LL_FLASH_ClearFlag_EOP(FLASH);) n: L; S, g @$ e
- }+ H0 g4 V3 l/ @2 X% n$ G$ `
- else
8 m/ I6 K6 }& T4 k i; m3 R( r4 O - {+ q8 z% S6 ]+ I7 `8 K
- return LL_ERROR;
; z: E. n4 e. r - }
# X1 A# x: p3 G( W }6 s" q) C - LL_FLASH_DisenableProgram(FLASH);3 T* |# b# r. g, t6 x9 J
- return LL_OK;
+ P8 F7 f- z6 N( D! d - }
; ^3 r' d0 U; K$ h% a. w2 P1 t) e
复制代码 ! N% a' |1 y* }6 [" P: {' c
& K1 l2 m8 g- k
|