不知道为为什么,STM32 LL库并没有FLASH的库函数,于是决定写一个, Q0 {; f% x. O+ q
' n( d, u' L5 Y, z$ f1 lLL库的特色,就是一个函数,只占用一个指令周期,比如,设置GPIO输出的状态,就是LL_GPIO_SetOutputPin();7 ? c0 @8 [! @3 G2 o* h3 {
- __STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)+ g7 L* Z; C, s9 y3 m. w8 M" L# r
- {2 l# g) n% q, J
- WRITE_REG(GPIOx->BSRR, PinMask);
2 W3 F$ z4 H& v - }
复制代码 于是我根据这种风格,已经常用的操作写了一个.h和.c文件; J' D$ s- C- Z! a
3 A2 {; y. `' ^2 U. v+ T& V8 o8 |头文件代码
, g' ?- t x, F/ {- #ifndef __STM32F0xx_LL_FLASH_EX_H7 P' d4 \6 U: T6 B3 h9 }5 b
- #define __STM32F0xx_LL_FLASH_EX_H
7 Y; o3 r: y5 N- U
. S. B( }+ t3 c) a- #include "stm32f0xx.h"2 N$ k" a" l& p" q! q
3 Q; e2 k8 q2 B% l
- ~/ A- D/ {, V9 T$ N$ l5 G% r- #define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */
& i' q8 \6 i8 d7 B7 B - #define FLASH_FLAG_PGERR FLASH_SR_PGERR /*!< FLASH Programming error flag */
$ d: E6 W( K: }9 f+ c& i, g - #define FLASH_FLAG_WRPERR FLASH_SR_WRPERR /*!< FLASH Write protected error flag */
: B6 }3 @. S! W - #define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Operation flag */
. E0 H8 m0 _ F% V+ Z: F" O
5 u$ L/ P9 N9 q2 f- #define FLASH_TYPEERASE_PAGES FLASH_CR_PER /*!< FLASH_CR_PER */
3 G: _ J) t. i( M1 L+ T - #define FLASH_TYPEERASE_MASSERASE FLASH_CR_MER /*!< MASSERASE */
% S9 Q4 X/ I- y0 X$ _& ] - , g( {2 M4 x6 p2 _) `+ b8 c) `
- 3 E7 R' {, S0 ]+ H/ J; t5 u9 _( L
- #if defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F031x6) || defined(STM32F038xx) \8 Q6 x3 q( ?( p" S6 A0 A
- || defined(STM32F051x8) || defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F058xx) || defined(STM32F070x6); e: E0 H. `2 e2 _ p: Q
- #define FLASH_PAGE_SIZE 0x400U! H5 G2 X- J1 a
- #endif /* STM32F030x6 || STM32F030x8 || STM32F031x6 || STM32F051x8 || STM32F042x6 || STM32F048xx || STM32F058xx || STM32F070x6 */6 u# p/ Y* f/ F# B
- . E( v, N+ Y3 H3 c. w5 G d; O
- #if defined(STM32F071xB) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F070xB) \3 k, C" l ~" Q8 m5 L
- || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC)
2 `! B2 A; q1 X& G; S - #define FLASH_PAGE_SIZE 0x800U7 f, t, _- \- c" C7 e4 q2 ~
- #endif /* STM32F071xB || STM32F072xB || STM32F078xx || STM32F091xC || STM32F098xx || STM32F030xC */
' L& C! ?* L2 V' `9 D9 |7 c$ r9 j - 6 I2 M5 u) q2 U% S5 J
- typedef enum {
: G8 s( V7 l# G" p; e; W - ProgaraType_DATA64,
9 w1 D7 J0 u. s0 t5 C - ProgaraType_DATA32,
7 A! a2 E3 @9 p3 f; Z- i - ProgaraType_DATA16
) x5 j" f; |$ a. B& \4 w6 r& j - }ProgaramDataType;! ^2 T; h; a1 D& |0 U
- 4 p' A+ M! _# f, ~* s4 \! R8 F
- typedef enum {\" k( @3 h% _! H
- FLASH_Lock=1U,Flash_Unlock=!FLASH_Lock\
1 [8 y0 S; h* ^7 n8 @6 T+ U - }FlashStates;
* i/ H. `! r/ U7 I - 9 K* z) q" |8 V: Z* r$ m
- /* Set the OBL_Launch bit to launch the option byte loading */6 i( [6 E! a! i# s8 T8 N; B% a
- __STATIC_INLINE void LL_FLASH_SET_OBL_Launch(FLASH_TypeDef *FLASHx); A* H' i& T* ~% w2 I, n
- {
# m/ p0 G% K5 x' v3 p; M X+ w. } - SET_BIT(FLASHx->CR, FLASH_CR_OBL_LAUNCH);# p! t2 q5 w% ^# h/ R/ L$ u( ^' G
- }
; k# M4 h) O( L! P! V - __STATIC_INLINE void LL_FLASH_Lock(FLASH_TypeDef *FLASHx)
- B2 ]. V- Z" i: l: v$ y# e R - {
, P. G$ I" d0 p$ {) d; g - SET_BIT(FLASHx->CR, FLASH_CR_LOCK);
5 C* M0 r4 L# y5 `& v2 j- r. b - }) T) \# m' K0 T6 j5 R0 [
- 3 \. J6 |$ D! T5 C* k
% n/ x7 J' W' R% n2 D- /* @brief Set flash erase type.
) G0 w8 L* b3 `1 j4 S5 u% h# U - * @param FLASH_TYPEERASE specifies the FLASH flags to clear.
" v, u, `- C& G) S - * This parameter can be any combination of the following values:
% g& L5 x7 J* a y - * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase5 I/ W- [* Z8 i/ M
- * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag
+ q+ t/ w0 N- L/ b0 H# v: v% C - * @retval none*/
& V8 i4 y, w4 r a, F
1 \! r) s5 b; Y- m/ Y- __STATIC_INLINE void LL_FLASH_SetTypeErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)4 T. V& c! l$ U) i2 Z
- {
; b! i7 _- _ ]5 `7 P' v - SET_BIT(FLASHx->CR, FLASH_TYPEERASE);
1 {. Y; z4 b/ \+ S - }0 { k: e: R ?" Y0 P
- /* @brief Set flash erase ADDR.7 `9 |3 W: p- O" ^
- * This parameter can be any combination of the following values:
5 C/ v% Z# F1 L$ _! _5 L0 c3 S - * @arg @ref EraseADDR uint32_t value4 r- {( s4 j7 R7 {
- * @retval none*/. I5 Z/ N6 A) h5 G
- 9 J0 T# g' o' J0 v
- __STATIC_INLINE void LL_FLASH_SetEraseADDR(FLASH_TypeDef *FLASHx,uint32_t EraseADDR)+ u( ?/ C7 w/ [! E* B- R
- {
/ y* ?8 t3 O) R, m2 i - WRITE_REG(FLASHx->AR, EraseADDR);
# H, f* m; Z" n" K, W - }
' t! e! Y1 f6 }* ?/ }% ?, U - /* @brief Set flash erase ADDR.
2 C8 \) R$ l* h7 P5 j6 ~, ] - * This parameter can be any combination of the following values:) E4 ^( Q! r6 K$ E4 x$ ?
- * @arg @ref EraseADDR uint32_t value+ C X5 T9 t- n9 ^+ s6 ~4 f5 E
- * @retval none*/! X8 [8 f( t" Y: n$ R
, G' G, }" }7 e. y* |- __STATIC_INLINE void LL_FLASH_StartErase(FLASH_TypeDef *FLASHx)& x4 }, d- l2 m5 Q/ g
- {
8 m# H4 X1 X% P1 u$ e - SET_BIT(FLASHx->CR, FLASH_CR_STRT);8 G* T' G1 n. Z# J( {! P, u
- }8 f: ?0 A5 _. G. n
- 3 y! r8 t+ U0 v! @; ]- [6 Q' `
- /* @brief Clear the specified FLASH flag.: x6 u; K+ ^5 f% p; R
- * @param __FLAG__ specifies the FLASH flags to clear.
2 n/ W4 B. j$ U- c - * This parameter can be any combination of the following values:# n. V. N- f& m! E
- * @arg @ref FLASH_FLAG_EOP FLASH End of Operation flag 1 F( c( `* e, F3 b' d
- * @arg @ref FLASH_FLAG_WRPERR FLASH Write protected error flag 1 X$ s9 X3 s) m5 ]& a# E4 |
- * @arg @ref FLASH_FLAG_PGERR FLASH Programming error flag# Q% i d& C/ |4 Z* h3 ?. g0 U# F
- * @retval none*/
, n: T2 f9 z4 N5 w7 E - $ g' n* y' c1 d* I
- __STATIC_INLINE void LL_FLASH_ClearFlag(FLASH_TypeDef *FLASHx,uint32_t STATE_FLAG). G6 z2 F& \ J; g
- {: L- e( h6 a1 F P1 _
- WRITE_REG(FLASHx->SR, STATE_FLAG);4 s$ K8 ~& H" Y6 Z; |+ t0 {: y
- }
" b: C' S7 y3 R
$ p) ]: ]$ H' l5 c+ c4 y- /*get bit flash bsy*/
9 \8 _$ c: g7 @+ e( I% \ - __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_BSY(FLASH_TypeDef *FLASHx)
3 o" H; e0 `# j: W - {0 B7 ?& D D) i% h5 }6 X8 m
- return (READ_BIT(FLASHx->SR, FLASH_SR_BSY) == (FLASH_SR_BSY));$ Y. Y3 h7 b- ]. B7 E
- }
% t$ q; a" e: _; q9 d# B* j - /*get end of operation bilt*/6 H9 B! Z1 X0 N, w7 K1 D" D
- __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_EOP(FLASH_TypeDef *FLASHx)2 T( N+ G" }$ A9 d
- {
2 A: S! w" Q( L/ ? - return (READ_BIT(FLASHx->SR, FLASH_SR_EOP) == (FLASH_SR_EOP));
- ]% x4 n" x' \) ]" G U5 s5 o - }
2 I$ K- ^ B3 }* w+ x - /*clear end of operation bilt*/
1 Q, G1 A" A! g4 F, q - __STATIC_INLINE void LL_FLASH_ClearFlag_EOP(FLASH_TypeDef *FLASHx)
+ k% F. }: c8 ]1 @& M - {& O5 \7 w& t0 K1 R$ |! `
- SET_BIT(FLASHx->SR, FLASH_SR_EOP);//EOP bit Set clear' a4 X) K6 k% x. L1 X* K
- }! ~! N; z) S9 S
- /* @brief Set flash erase type.
: E9 s. J' Y: K% Z1 ^% I+ i - * @param FLASH_TYPEERASE specifies the FLASH flags to clear.
8 Y8 M" C3 x) l# O/ c& s2 W - * This parameter can be any combination of the following values:6 e5 U; {- C9 l# z
- * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase
6 \& _: g' `) K1 l5 ]) P2 F: U$ [ - * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag ' Q8 T# f I; r7 }" v7 \/ a3 B/ A
- * @retval none*/
[& i1 \" U/ M0 u8 N7 B' B - __STATIC_INLINE void LL_FLASH_DisenableErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)
4 R& ^0 V* S/ J& m9 I0 M - {
5 F) F; o0 D, N7 a - CLEAR_BIT(FLASHx->CR, FLASH_TYPEERASE);
k( a5 J, y; s1 n# K( ?1 H - }
% d' P4 w. C! n
0 i" _6 a9 w. _4 _$ ~- /*EnableProgram*/
' g% y" H6 {! B - __STATIC_INLINE void LL_FLASH_EnableProgram(FLASH_TypeDef *FLASHx)0 W) F# p4 ~# G% f- |' F
- {* {$ m$ Z5 N2 j) u* Q
- SET_BIT(FLASHx->CR,FLASH_CR_PG);, q2 W8 v; \0 [
- }- v6 j3 ^$ ^- G. ?, d8 ?0 B6 _
- /*DisenableProgram*/
) J9 F9 k# |6 g4 e$ q - __STATIC_INLINE void LL_FLASH_DisenableProgram(FLASH_TypeDef *FLASHx)
1 j* I z. R$ x) l8 J& w - {8 t+ I' c0 C3 B4 _! z2 y
- CLEAR_BIT(FLASHx->CR,FLASH_CR_PG);# M# ]9 I) U! X9 a9 a1 C, ]
- }2 o, o8 l, L! c% {. _/ ^
- /*read flash's states of lock or unlock*/6 ^8 m! H- _$ n- B3 V' I; S/ S
- __STATIC_INLINE FlashStates LL_FLASH_LockState(FLASH_TypeDef *FLASHx)
5 [6 ^- k9 u6 @* | - {
6 d$ R2 w$ B% r6 E- V - return (FlashStates)(READ_BIT(FLASHx->CR,FLASH_CR_LOCK));$ ]. x1 |1 V" A) M+ P3 W0 T) h
- }2 }% v9 b0 R( H: N1 o
- /*set key for flash*/
3 z- l4 F- M$ D4 Q0 L! [ - __STATIC_INLINE void LL_FLASh_SetKey(FLASH_TypeDef *FLASHx,uint32_t key)+ [: M8 i: e8 F( {$ t
- {% i6 H. B7 _: U1 {7 ^- s% n4 t
- WRITE_REG(FLASH->KEYR,key);- w- p$ E# W0 `
- }
, i- a. R% z- L' M) k- x( u( f - 7 \5 z, i7 n, L- k$ f9 S
- " }3 l" t" t s" a: a [$ v3 e
- LL_StatusTypeDef LL_Flash_Unlock(void);
' n1 d+ s( |. w5 y+ H: Q% r - LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t NbPages);
3 Y. t2 Y$ \' M2 s& r* y) f - LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data);
7 N7 I6 ^& s0 `, Y# ^ - #endif
复制代码 , L5 z( `6 U2 b9 T- q
C文件代码4 {# @" Y1 {" P6 h+ o
- #include "stm32f0xx_ll_flash_ex.h"! }7 O+ s) D; Y% Q2 _1 @
- W$ F. C+ C& Z l. y
- , N1 ~$ q: v' `( C
- void static LL_FLASH_Program_TwoBtye(uint32_t flash_addr,uint16_t data). [/ U8 T, o R- T& D3 H
- {
4 I) o3 y7 M2 }7 u9 r" e Q: P - LL_FLASH_EnableProgram(FLASH);$ Q: x: |" b0 z
- *(__IO uint16_t*)(flash_addr) = data;
8 E e9 f5 t+ e - }# H0 `- J. V2 V1 {0 t/ W! L
- # t, T7 ]: B( P% K
- LL_StatusTypeDef LL_Flash_Unlock(void)
( @- r" U1 {% B( P - {( \9 D/ Y0 \' r( @8 ^. W, d& c
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
0 e/ T, D' M7 q% ^& ~ - {9 |- b8 X$ H0 `0 m5 H
- } + N/ I% |( g& v, `- p
- if (LL_FLASH_LockState(FLASH)) + K- K/ i7 r1 {9 ?( ?" j
- { & ?8 p2 e2 ^/ u7 A, g6 [
- LL_FLASh_SetKey(FLASH,FLASH_KEY1);3 D* e, F6 b3 W6 [7 S
- LL_FLASh_SetKey(FLASH,FLASH_KEY2);! t4 o5 c4 l7 J' h
- }
* V: f5 ?, w/ \) M' Q' I - return LL_OK;% J0 e$ n, H3 H3 R2 \; D% n$ o' Q6 ^8 S5 d, Z
- }
+ P8 ]% s$ G3 i
; H T& a7 M1 D! F" \8 D* J! ^- LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t Nb). d/ B( j- h# u, x
- {
& K1 r- R3 H5 x) Y7 ~2 k. F - uint32_t End_addr = 10* FLASH_PAGE_SIZE +page_addr;
! P$ N0 q9 E9 y9 _ n/ q" i8 i - uint32_t Start_addr = page_addr;- g U7 m; V& g) u
- for(;Start_addr < End_addr;(Start_addr += FLASH_PAGE_SIZE)); d! ^) Y! Z' F; E9 o) {7 I
- {
6 ^0 m. ]/ e- O v* i - LL_FLASH_SetTypeErase(FLASH,FLASH_TYPEERASE_PAGES);
: X1 b9 O$ | y - LL_FLASH_SetEraseADDR(FLASH,Start_addr);( @0 l/ D5 v2 r9 P+ `' e
- LL_FLASH_StartErase(FLASH); ; J+ A$ C5 Z8 q
- while (LL_FLASH_IsActiveFlag_BSY(FLASH)) ' i8 ^7 W5 W& o6 f! P
- {
( ~7 c( g. R( p - } % o& t& s! i: J! l4 T
- if (LL_FLASH_IsActiveFlag_EOP(FLASH))
$ W' G) R3 ^) g# Q - { 8 Q! ~2 d4 m: \. I( e
- LL_FLASH_ClearFlag_EOP(FLASH);; : s* Z' c! j2 V8 k! {
- } 6 v& f" A3 b, [* [9 ?, V: O8 X
- else
- \% t6 c/ L6 f2 ~* Q& a1 O$ ]/ M1 |! X - { ! M0 k& w% e0 q3 ^! \% c8 D: ]
- return LL_ERROR;
2 `4 |. B! i( l' ?, K5 a0 ]8 w7 k1 j - }$ J! y( A6 Q1 @, J# h
- LL_FLASH_DisenableErase(FLASH,FLASH_TYPEERASE_PAGES);! T7 _& b6 v! m; h6 t0 K
- }4 L. l. c) m1 Q- J! P2 I3 f
- return LL_OK;6 o( b( y$ t9 _2 W# v, B( @: \
- }/ K( Q; p9 B7 D& V: ^$ d
- 9 ], Y+ S2 q% H
- LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data)
: C* z% o3 n! B" A! V0 P - {9 ?0 e2 h& s4 c# n
- 8 _4 |# ?5 ~" f, N" G
- uint8_t index = 0U;( z- m9 {1 N' p' c: |, w
- uint8_t nbiterations = 0U;0 E7 S# V' U& n3 H
-
, i$ S0 a/ {2 E - if(ProgramType == ProgaraType_DATA16)4 T. A& X/ H" C0 S5 v
- nbiterations = 1U;0 U9 Q; n, p+ M) U$ m. t- y* \
- else if(ProgramType == ProgaraType_DATA32)
8 r- n$ c. O5 d. \. g7 t - nbiterations = 2U;
8 m$ f, Y6 N4 W4 d. r1 M - else
; m' _# ^- P, F! A - nbiterations = 4U;
" a' @3 i7 p4 v! C( J! E: N - for(index = 0U; index < nbiterations; index++)
6 N& a" z& l! e# s - {
# H( r; T7 \, u5 J0 @) Q - LL_FLASH_Program_TwoBtye((flash_addr + (2U*index)), (uint16_t)(data >> (16U*index)));
. j" R- g( ~' F! E# G. V% ]! s' P, F - }3 _3 |: `/ [. v ^+ G6 f) F8 P$ k
- : h) z& d+ i6 p( ] i! U+ x) ^9 h" A, B
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
4 M$ S; p9 h1 U2 M4 G6 s - {* c2 K. e. y% l; b. N/ \4 K
- }: t3 G% e! R' V& Z" k) Y
- if (LL_FLASH_IsActiveFlag_EOP(FLASH))
# T& b8 _( u4 Y4 J3 R4 W/ G* s9 ` - {7 D/ D1 V( _( A0 z! T; H
- LL_FLASH_ClearFlag_EOP(FLASH);
( p) B3 X, P) X' o$ u7 }$ i. r - }
% H# i! n( T5 g& q4 M6 E$ H - else4 j' g- u) l8 H4 }; E" M
- {
% V, u, E. ?/ J - return LL_ERROR;
/ O" {. d; ?. R" A, X0 c - }
0 @- h- I! i. y4 R( ` - LL_FLASH_DisenableProgram(FLASH);
) e2 i+ ]/ ]: o3 y) ] - return LL_OK;
3 [. d: o5 K3 Q8 J# X$ I9 w( o1 k! ? - }
( c$ e0 a9 h" t, c [. L; j* t
复制代码
& X4 u2 U7 U, O- q6 W
% z, S: ^% O2 s: A: Q' E" |2 d |