不知道为为什么,STM32 LL库并没有FLASH的库函数,于是决定写一个4 J" S6 J* S$ C$ _1 V
5 ]8 t+ X" K: P# I u" z
LL库的特色,就是一个函数,只占用一个指令周期,比如,设置GPIO输出的状态,就是LL_GPIO_SetOutputPin();
9 D! `# D1 a* G: K- J- __STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)1 t+ a/ m/ W7 C% }+ \1 a) ]& P4 w1 S
- {+ o% m1 [- s q7 j6 u
- WRITE_REG(GPIOx->BSRR, PinMask);
8 D* z" |9 l p! _6 u- {( z* L. r - }
复制代码 于是我根据这种风格,已经常用的操作写了一个.h和.c文件
& W" c, z6 S- p# l, X! y( Z0 R5 r7 p( V* {3 j, ~. t
头文件代码
8 {( q4 e7 r4 Y. I/ d- #ifndef __STM32F0xx_LL_FLASH_EX_H
" c/ x+ B1 i* c0 s - #define __STM32F0xx_LL_FLASH_EX_H F) h) Q9 f& L5 l: p( D
+ F1 t. {4 O- X* Q n$ T- #include "stm32f0xx.h"
0 }( w6 j4 _* N - ' z. K& c4 G: u% v2 B, i+ u8 c
. g- _/ i5 T5 k' D- #define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */
6 B: Q% B# i% R7 ?! J - #define FLASH_FLAG_PGERR FLASH_SR_PGERR /*!< FLASH Programming error flag */
% Y& r$ G( z o5 [* M6 d" I. K) |( O! M - #define FLASH_FLAG_WRPERR FLASH_SR_WRPERR /*!< FLASH Write protected error flag */
( W2 p) ?4 }; ~3 W7 u6 ^ - #define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Operation flag */! T* j5 ?: }" \9 o% f8 G7 k2 i6 ]6 X7 t
( j# N: g: g+ N5 }0 m& R$ f- #define FLASH_TYPEERASE_PAGES FLASH_CR_PER /*!< FLASH_CR_PER */
$ J9 T/ |& t# w - #define FLASH_TYPEERASE_MASSERASE FLASH_CR_MER /*!< MASSERASE */
/ k: F! j$ s2 ^ x: |# O3 d2 |& e
" W8 d4 g% `- c( R3 N& i
% k+ `2 J# h7 F- #if defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F031x6) || defined(STM32F038xx) \
1 a( R8 }+ _6 G! h( @ - || defined(STM32F051x8) || defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F058xx) || defined(STM32F070x6)
: B% y/ L2 g. I3 W$ Y. g - #define FLASH_PAGE_SIZE 0x400U
* D" v1 a3 `1 J& d0 w - #endif /* STM32F030x6 || STM32F030x8 || STM32F031x6 || STM32F051x8 || STM32F042x6 || STM32F048xx || STM32F058xx || STM32F070x6 */
( A0 y, l9 R- l - 0 W W5 F" I8 n+ h8 F. D
- #if defined(STM32F071xB) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F070xB) \
# e1 A3 T) S9 Q* T4 \# B2 j - || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC)
% q& T) H! d. W J% X* ]+ q - #define FLASH_PAGE_SIZE 0x800U& o3 u7 r4 X: S
- #endif /* STM32F071xB || STM32F072xB || STM32F078xx || STM32F091xC || STM32F098xx || STM32F030xC */
8 }1 w7 q0 s7 @2 m- | - 8 ~3 n/ D4 E; s4 `4 M
- typedef enum {
- v) M7 U! Z$ T' A5 n2 c) [0 V6 D$ \ - ProgaraType_DATA64,( H0 \0 R0 d) m$ y
- ProgaraType_DATA32,
6 _# l/ ]7 [, [2 `$ K: H% Q4 Z" v" I - ProgaraType_DATA16
7 P1 x5 f# {. q6 f0 y1 x; T+ U' t% G - }ProgaramDataType;
/ z, \# o' S! { `0 W2 N - * `9 U" S& h- \
- typedef enum {\
$ [; i. X: c2 u$ I O! M - FLASH_Lock=1U,Flash_Unlock=!FLASH_Lock\
% P7 h% ^9 j* z1 b; e - }FlashStates;
! B3 W; s) {; I+ r! h - 3 W% H% Y; @$ k- _ B
- /* Set the OBL_Launch bit to launch the option byte loading */
9 f2 S. W F! n- [8 V1 ^" f - __STATIC_INLINE void LL_FLASH_SET_OBL_Launch(FLASH_TypeDef *FLASHx)
8 F2 \* q/ z; y1 { - {1 l4 ?! q5 I) z3 n: p# _/ _
- SET_BIT(FLASHx->CR, FLASH_CR_OBL_LAUNCH);$ s* c }0 `4 l
- }
: W; K) I7 G! J0 T/ ~8 y1 V$ B - __STATIC_INLINE void LL_FLASH_Lock(FLASH_TypeDef *FLASHx)- J9 l% {8 K; c2 h5 x& y! O
- {
6 Q+ }0 m1 e V$ o: ]2 r - SET_BIT(FLASHx->CR, FLASH_CR_LOCK);4 V4 ]% e& L( g, ?/ I
- }
. \' G7 ^; M) q# X0 ~8 d
: D, D. X2 I4 ?' R; m- |3 p9 _* _ G. M
- /* @brief Set flash erase type.
) T0 g8 ~9 t; Q4 D \ - * @param FLASH_TYPEERASE specifies the FLASH flags to clear.
6 q' X) c. [& N: z7 h8 M# U - * This parameter can be any combination of the following values:
; j+ h, m$ l8 | - * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase
9 O9 s3 k2 B1 P) Z1 \ - * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag
& w1 U8 o2 x4 W9 Q4 B6 ` - * @retval none*/& [% b! [$ _9 x8 @
4 `% {5 i" [/ g. D- __STATIC_INLINE void LL_FLASH_SetTypeErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)
/ M/ _2 ? {& B3 }* u - {
. n- P4 e2 X3 g3 I0 X9 _7 H, a - SET_BIT(FLASHx->CR, FLASH_TYPEERASE);5 A4 ^6 O" t* q. u
- }. W! D' A# L2 T2 W" a
- /* @brief Set flash erase ADDR.
: g; M" z3 z6 t2 X1 Y; \! ^ f - * This parameter can be any combination of the following values:
~: N! j$ C! s, P$ ~; v3 q - * @arg @ref EraseADDR uint32_t value
% F9 I9 k0 @. s7 N - * @retval none*/
' V) P* ~/ N" ]& K
) W; p: T$ S( Z7 i' B' A, R- __STATIC_INLINE void LL_FLASH_SetEraseADDR(FLASH_TypeDef *FLASHx,uint32_t EraseADDR)
/ ]! ^/ b2 Q- ?5 ] - {, b. t1 e; P4 P) _) Z1 V2 x
- WRITE_REG(FLASHx->AR, EraseADDR);3 O" o& e, F# E; M% j" X: v
- }0 _) d, }% \& G% ^, c& L. w
- /* @brief Set flash erase ADDR.6 |4 y S V" X' o
- * This parameter can be any combination of the following values:
8 E% }9 }0 ?" i$ q7 L- }% c- n - * @arg @ref EraseADDR uint32_t value: T% X% n0 r1 O4 l: L' f! D. B
- * @retval none*/
6 D0 `- W# u5 Q* r8 {0 B0 I
, c( x2 A$ W/ J) a R. } E$ x2 U! e; f- __STATIC_INLINE void LL_FLASH_StartErase(FLASH_TypeDef *FLASHx)
q* r1 o+ i7 m+ z5 z9 Y - {/ h/ { U7 N1 ^: J6 s1 M
- SET_BIT(FLASHx->CR, FLASH_CR_STRT);2 K7 i! h8 |' M1 j& P9 V# c ?+ j
- }
6 a+ T3 k' s$ V- s
* P+ i3 E# E: u+ E, a- E- /* @brief Clear the specified FLASH flag.
! Q, U7 c1 m+ `# a9 _0 k/ \- i e - * @param __FLAG__ specifies the FLASH flags to clear.
1 n/ Q) _7 ~1 B6 A - * This parameter can be any combination of the following values:+ q$ Z& m w1 u% z- E+ b& C
- * @arg @ref FLASH_FLAG_EOP FLASH End of Operation flag
: I2 A% x4 q- V+ u$ S - * @arg @ref FLASH_FLAG_WRPERR FLASH Write protected error flag + I n2 ~2 ^3 J0 o
- * @arg @ref FLASH_FLAG_PGERR FLASH Programming error flag- h! O; R" l5 b8 m/ v% q* P
- * @retval none*/
) t. w$ @: ^4 h - 6 r4 W* P' h' V! O7 {% e. K s
- __STATIC_INLINE void LL_FLASH_ClearFlag(FLASH_TypeDef *FLASHx,uint32_t STATE_FLAG)3 _3 g5 R2 V" `, ? }# i
- {' i) U) v% p8 B Z, \
- WRITE_REG(FLASHx->SR, STATE_FLAG);
4 A! o' N. V; B& q9 i - }0 W% v6 M, Q: T# d
- - |* S7 b, J' ?8 E% P$ n9 r1 N! |
- /*get bit flash bsy*/
, J5 H5 M; t9 i7 ] - __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_BSY(FLASH_TypeDef *FLASHx)! Q0 i* S5 J4 r4 E# _/ w
- {
W7 S" |, K% \ - return (READ_BIT(FLASHx->SR, FLASH_SR_BSY) == (FLASH_SR_BSY));
! B$ K6 y& y0 L' Z+ w8 o# |3 r* q - }
, K$ F9 q1 a3 R) P8 l! ^ - /*get end of operation bilt*// j1 i1 N8 n3 I5 ]8 |& D
- __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_EOP(FLASH_TypeDef *FLASHx)+ Y2 P8 C9 M% O' H
- {
5 T6 B$ n! b, h. S) s0 X, q - return (READ_BIT(FLASHx->SR, FLASH_SR_EOP) == (FLASH_SR_EOP));
5 D" o, y8 S* v+ f+ n5 o1 H - }+ |3 ~- p/ m; u
- /*clear end of operation bilt*/) C8 g& u( g1 z2 r7 ^8 M& t" M: H
- __STATIC_INLINE void LL_FLASH_ClearFlag_EOP(FLASH_TypeDef *FLASHx). H- `( G k8 V0 n7 r" t
- {
9 ?* [' ]# ` [# N! d; I) ` - SET_BIT(FLASHx->SR, FLASH_SR_EOP);//EOP bit Set clear
3 {5 N2 _3 y, X; c5 \ - }- C: [+ Y( M# W9 K) ~5 @% m0 K
- /* @brief Set flash erase type.
* E: F* {& ?8 [& ]3 N( p - * @param FLASH_TYPEERASE specifies the FLASH flags to clear./ u F) @- O! d: Y! B$ \
- * This parameter can be any combination of the following values:9 O0 q& B4 T7 U( p; T0 B9 b% E, B6 k" k
- * @arg @ref FLASH_TYPEERASE_PAGES PAGES Erase
2 K8 r! N2 ~3 G - * @arg @ref FLASH_TYPEERASE_MASSERASE FLASH Write protected error flag ; j" ]; a7 M. P9 o2 k' S- [0 T
- * @retval none*/
' ~- c L4 t# ]! X - __STATIC_INLINE void LL_FLASH_DisenableErase(FLASH_TypeDef *FLASHx,uint32_t FLASH_TYPEERASE)7 c% O \3 b( v% k. h O
- {
2 J9 h0 S3 D& \ - CLEAR_BIT(FLASHx->CR, FLASH_TYPEERASE);
+ v6 V( P& B" ^4 Q6 m1 w6 @ - }
: @$ A' C4 k2 T: x8 k
6 U @3 Y1 w9 h* N( {- /*EnableProgram*/
9 d- s2 T5 W, f3 E - __STATIC_INLINE void LL_FLASH_EnableProgram(FLASH_TypeDef *FLASHx)& C- d9 `2 W z- t
- {1 s/ `/ g8 |/ t
- SET_BIT(FLASHx->CR,FLASH_CR_PG); _8 H+ _. b& }6 p' i
- }% C i1 H5 F# V( V) E' W1 C
- /*DisenableProgram*/* T( q( Z3 l7 d% }) S
- __STATIC_INLINE void LL_FLASH_DisenableProgram(FLASH_TypeDef *FLASHx)! ]+ m/ V* x# ~* S Z! J K
- {
$ F1 F, A; z6 v V3 l, K - CLEAR_BIT(FLASHx->CR,FLASH_CR_PG);
# K# d' {5 W2 ~2 f8 q3 s7 X - }- r6 L& G0 t- E) B+ r
- /*read flash's states of lock or unlock*/: v3 {) [% D, W# a- c8 ^! m5 H
- __STATIC_INLINE FlashStates LL_FLASH_LockState(FLASH_TypeDef *FLASHx)& a8 E5 O7 Z' b3 P1 x! f6 y
- {, a, D& Z8 d" ], C
- return (FlashStates)(READ_BIT(FLASHx->CR,FLASH_CR_LOCK));7 |& Z0 ?" H: m2 }/ j" _
- }
9 u( j M" ~ N d* E( v0 N4 H - /*set key for flash*/& [3 T. C3 F' q9 N1 A4 M
- __STATIC_INLINE void LL_FLASh_SetKey(FLASH_TypeDef *FLASHx,uint32_t key)
" `# r! \( U" _) _& `8 W+ C2 F6 d - {
* X3 E4 N: l5 Q, V. }, J9 h - WRITE_REG(FLASH->KEYR,key);, J# V! _% {* m4 `$ d
- }
O O2 C0 ~9 ~% r" f
# g& w) v3 h9 [0 Z( b4 d8 [# [
5 |7 e) a6 j! l. H, a- LL_StatusTypeDef LL_Flash_Unlock(void);
3 `( f; C# a" r1 s+ G: b/ f6 O, f - LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t NbPages);+ v8 L- W! o, u3 M$ |
- LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data);2 }5 N* u0 H1 o! E2 t4 I
- #endif
复制代码
& v/ V' O$ g3 G" |8 x+ nC文件代码
y' ^: M" ` e1 }4 Q- #include "stm32f0xx_ll_flash_ex.h"
X; o4 j1 f7 P3 f - ) a( V3 j! x+ D& n2 @8 [
( X" j9 _- ^- r5 B3 y- void static LL_FLASH_Program_TwoBtye(uint32_t flash_addr,uint16_t data)& I* G; h* w# s$ ~
- {. i) e. g2 g& N( {1 B9 x" L* G
- LL_FLASH_EnableProgram(FLASH);9 k3 r% e+ N& a4 P
- *(__IO uint16_t*)(flash_addr) = data;
4 d. ^: V) A" W1 f0 `7 L6 I - }
4 w+ A6 Q1 k& I% K - 8 |' B# j$ G( H0 j
- LL_StatusTypeDef LL_Flash_Unlock(void); G9 B4 x" o4 G5 q
- {
& T5 I7 E/ v- _: {1 i m P( A/ k: b! k - while (LL_FLASH_IsActiveFlag_BSY(FLASH))
# i3 r2 k" H1 \- q6 D - {
% J$ A e, I' Y @; f& a R - } : R4 |+ t+ W4 S5 p& P) T* |
- if (LL_FLASH_LockState(FLASH))
, R6 G5 f G7 M2 z - {
, X+ t% B A0 y1 s/ ` - LL_FLASh_SetKey(FLASH,FLASH_KEY1);
/ q* e$ C% l5 m1 F8 g6 H) y4 Z# `5 R - LL_FLASh_SetKey(FLASH,FLASH_KEY2);6 _- H$ z# L8 [: G
- }% g1 m4 e3 `8 A, d9 i
- return LL_OK;
$ M0 O* H/ u% f4 y9 Z' C; B9 V# C - }
2 Z5 W& u" f$ z
7 g# s1 o7 \0 O4 G, g- LL_StatusTypeDef LL_Flash_PageErase(uint32_t page_addr,uint16_t Nb)
( R) H8 U0 I a* o' W0 E. C - {
; e! n5 @ n8 P5 D8 f9 f/ }; b* { - uint32_t End_addr = 10* FLASH_PAGE_SIZE +page_addr; _: f% {& t/ @1 i) \* a
- uint32_t Start_addr = page_addr;5 C/ S) n# m/ H2 \# J# x6 R
- for(;Start_addr < End_addr;(Start_addr += FLASH_PAGE_SIZE))
; i9 c( T* k0 _* y* t! M - {
' Y+ ~. H, j1 @ - LL_FLASH_SetTypeErase(FLASH,FLASH_TYPEERASE_PAGES);, |( h. A3 A$ C4 Z4 b* P" M
- LL_FLASH_SetEraseADDR(FLASH,Start_addr);/ \; s6 y1 F3 L6 W) Y: y
- LL_FLASH_StartErase(FLASH); A+ T! U1 N! f: p) O2 e; i5 f
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
4 X; J' u+ T8 { - {
* ], n. |) U- u, z7 l - }
1 x' o( C0 F( y7 ^ - if (LL_FLASH_IsActiveFlag_EOP(FLASH))
, {- M# [& S$ H) H' h: Y, E( N - { - a. q( ^; x( j
- LL_FLASH_ClearFlag_EOP(FLASH);; 3 c& H2 @ Q3 ^
- }
% x# d. Z0 e# D5 g% W* U - else# a+ ?, k2 y4 v! A' H6 |
- { 9 b) {' C" C M. [
- return LL_ERROR;
1 {! X& c) r0 x) | - }
1 |/ X8 k; d- H5 [ - LL_FLASH_DisenableErase(FLASH,FLASH_TYPEERASE_PAGES);1 o: w. T) L, p5 H: v) D
- }3 E# [- V& Q% P8 f6 T E5 L
- return LL_OK;4 u$ g, }4 l1 k" a' \2 `- E5 b( t
- }
/ @' w, n4 l, E8 d8 {# ?" v1 o
$ c& X7 k6 Q9 j# z- LL_StatusTypeDef LL_FLASH_Program(ProgaramDataType ProgramType,uint32_t flash_addr,uint64_t data)3 m+ q7 e7 ` V: z) X
- {/ Q9 k: Y* q& r2 R, }
- # V5 t* c# o' G1 x! l" w
- uint8_t index = 0U;
! q: Y* x4 v# h6 b/ p* ]8 K* k6 f) s - uint8_t nbiterations = 0U;( `) Y" M0 ^, {: I/ t0 L0 t0 z
-
! A( }) ^/ k0 m- U% y - if(ProgramType == ProgaraType_DATA16)
! e! n# b5 d; v; z% v7 C d - nbiterations = 1U;
! b& [4 h' L7 G- A8 F1 g - else if(ProgramType == ProgaraType_DATA32)
0 b6 z5 D5 J" y' h: t3 i' V - nbiterations = 2U;& R% ?# X0 E4 `4 c- `3 k6 }6 ^+ ^
- else2 J' c: _& I( A$ w8 E
- nbiterations = 4U;
1 q x( V0 J6 n4 m - for(index = 0U; index < nbiterations; index++)
9 W Y% w' I; U2 N# { - {; D4 {7 p5 T9 P
- LL_FLASH_Program_TwoBtye((flash_addr + (2U*index)), (uint16_t)(data >> (16U*index)));
5 `& h, h3 `( q; v. C/ S) m - }
% [0 [1 z. W, A/ j: g. F2 d, a - / V+ W3 H5 a) ]. `- i" _, i
- while (LL_FLASH_IsActiveFlag_BSY(FLASH)) 3 D' ^' b8 n: ~- V2 |' w. X. y
- {& ]3 ]3 B3 U7 \% J
- }
& p0 p1 y1 O ~* ?3 W9 Q - if (LL_FLASH_IsActiveFlag_EOP(FLASH)) * V* _+ N: j% f. S" }2 [6 X
- {
4 n9 h4 `) h6 k7 M - LL_FLASH_ClearFlag_EOP(FLASH);
# k& N7 {8 d3 U+ [" k$ u# q - }
+ o1 ^, G) N6 l - else
+ }; G, O% Z0 b0 D% Z8 c - {- M* y+ {# @0 }0 k2 ?2 A
- return LL_ERROR;3 Z; ^" Z- {- J$ o3 i* e
- }
# G- U. H$ \" G8 ~. t. o - LL_FLASH_DisenableProgram(FLASH); p3 m4 S3 ^! [7 e* @
- return LL_OK;8 H+ ^, A) p3 ^: h# D
- }1 p2 f1 t% m0 l: Z5 i8 V5 [, s
复制代码
- k+ ]4 h% b8 d! G" D
# ]' K2 e# F7 T/ V% f w |