|
一、Flash简介 通过对stm32内部的flash的读写可以实现对stm32的编程操作。 stm32的内置可编程Flash在许多场合具有十分重要的意义。如其支持ICP(In Circuit Programming,在电路编程;在线编程)特性使得开发人员对stm32可以警醒调试开发,可以通过JTAG和SWD接口对stm32进行程序烧写;支持IAP(In Application Programming,在应用中编程)使得开发人员可以在stm32运行程序的时候对其内部程序进行更新操作。对一些对数据安全有要求的场合,可编程FLASH可以结合stm32内部唯一的身份标识实现各种各样的防破解方案。并且stm32的FLASH在一些轻量级的防掉电存储方案中也有立足之地。 stm32的FLASH分为主存储块和信息块。主存储块用于保存具体的程序代码和用户数据,信息块用于负责由stm32出厂时放置2KB的启动程序(BootLoader)和512B的用户配置信息区。 主存储器是以页为单位划分的。stm32根据FLASH主存储块容量、页面的不同,系统存储器的不同,分为小容量、中容量、大容量、互联型,共四类产品。 - 小容量产品:主存储块1-32KB, 每页1KB。系统存储器2KB
- 中容量产品:主存储块64-128KB, 每页1KB。系统存储器2KB
- 大容量产品:主存储块256KB以上, 每页2KB。系统存储器2KB
- 互联型产品:主存储块256KB以上, 每页2KB。系统存储器18KB. m# p( B) [: x
对于具体一个产品属于哪类,可以查数据手册,或根据以下简单的规则进行区分:
; e* q3 ]0 p1 x6 bSTM32F101xx、STM32F102xx 、STM32F103xx产品,根据其主存储块容量,一定是小容量、中容量、大容量产品中的一种,STM32F105xx、STM32F107xx是互联型产品。 对Flash的写入操作要遵循“先擦除后写入”的原则。 stm32的内置Flash编程操作都是以页为单位写入的,而写入的操作必须要以32位字或16位半字宽度数据为单位,允许跨页写;写入非字或半字长数据时将导致stm32内部总线错误。 二、程序实现 flash.h - #ifndef __FLASH_H" O, b9 y/ b: u' n/ M4 Q! i
- #define __FLASH_H
* ?% o6 S0 D; j9 X! ? - #include "stm32f10x.h"% I g$ \9 t$ |+ C, d$ ~
- u8 Write_Flash(u32 *buff, u8 len);, D2 R2 }1 y& n( z( K0 ]* u. E
- void Read_Flash(u32 *buff, u8 len);
. D6 _ ~" d# i7 j. l - void Char_To_Int(unsigned char *buffer, unsigned int *data,unsigned int position);
1 ?2 i' b, B3 F+ P# D, e7 C! ? - void Int_To_Char(unsigned char * buffer, unsigned int data,unsigned int position);& h( T8 C; e. ~# d/ g
- #endif
复制代码
9 r- a) ]: s# k8 I) g, B3 | flash.c - #include "flash.h"
B: `" d# ]- e) V3 c - #include "stm32f10x_it.h". }: S6 W2 _9 c6 z# a+ @
- #define WriteFlashAddress ((u32)0x08010000)//读写起始地址(内部flash的主存储块地址从0x08000000开始)
- C$ z9 w, i( O1 ?. N" L - & K; ^8 K7 ?7 L: J8 V
- /*******************************************************************************
& q8 q4 m- e, O3 e, ~ - * 函数名:Write_Flash2 f- {1 E+ S d7 r
- *描述 :写STM32指定地址的Flash
# E/ a* L8 Q8 y - *输入 :buff:写入数据缓冲区,len:写入数据长度
0 I0 W+ W$ D0 V - *输出 :无
: o; k$ v$ Z) N% \) S* d+ q - *返回值 :u8:写成功返回1,失败返回0$ O& c0 F* j, R& Q$ ?& X/ z
- *说明 :无 C! E1 @) \1 i1 i3 s
- *******************************************************************************/
) W' S& M6 U, y6 V( a - u8 Write_Flash(u32 *buff, u8 len)
4 I8 E. m- [* B/ a, K8 o8 O - { 0 c# S5 E- ^2 S+ n: S
- volatile FLASH_Status FLASHStatus;5 R$ l& D a% H! j- A
- u8 k=0;/ ~& h( X3 X4 V# X7 o3 A; F1 y
- u32 Address;" Z( b k: F; q$ @ c5 x, u
- . j5 O5 g1 `) p2 I$ v5 Y9 D
- Address = WriteFlashAddress;
t9 U% @ Z3 H( U/ m1 {& Q ] - FLASHStatus = FLASH_COMPLETE;6 I( H @" `/ S; G, f: |+ r
- FLASH_Unlock();//解锁
% z9 K% N: d: D - FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);//清除所有标志
. l) X! @8 S2 D - FLASHStatus = FLASH_ErasePage(WriteFlashAddress);//扇区擦除
6 ]7 R' _) g0 g0 H% I/ v2 O1 C0 Y* J - if(FLASHStatus == FLASH_COMPLETE)' }9 X9 V: ?. g6 p( J F
- {6 S3 g; z3 S) L: r
- for(k=0;(k<len) && (FLASHStatus == FLASH_COMPLETE);k++)
6 \4 D. ~/ x' m# i. ^ - {$ i& ]9 D& C4 v; V
- FLASHStatus = FLASH_ProgramWord(Address, buff[k]);//写入一个字(32位)的数据入指定地址 R5 Q* h% z$ Y5 e$ g
- Address = Address + 4;//地址偏移4个字节) }& t5 _% Y, @6 g+ G4 ]' ?
- }
, ]: \3 y* w0 F# V+ `+ ~ - FLASH_Lock();//重新上锁,防止误写入
$ H: F( F' r! K/ ^0 l - }+ ^) n; |, h) Q( A6 C/ R
- else
' N6 M% V0 _+ g - {. C2 r/ Q: L, u- a* L% g
- return 0;
# T' m1 d* m" ^' j6 | - }
3 _8 U. k. C( y9 R/ H - if(FLASHStatus == FLASH_COMPLETE)
9 r2 [/ S4 _$ x f! |2 h9 t0 J - {0 S4 ]" z0 M7 g) W* D( J9 j$ s8 b! R
- return 1;$ C3 ], ], w& y0 e; N
- }
4 |8 N0 g# [8 M - return 0;5 a; b1 b3 A" u/ u$ G' F
- }
?8 P( F7 P) R$ I3 O$ e1 f - 2 k0 _& a& S; ?8 I4 A
- /*******************************************************************************
6 V2 t' S1 {; j' V, i - * 函数名:Read_Flash
- l$ d1 a9 i. h, z - *描述 :读STM32指定地址的Flash9 q' `, @6 V# ?- S4 J" _" x3 D
- *输入 :buff:读出数据缓冲区,len:读出数据长度( L8 }) k' E" W0 n
- *输出 :无
# B+ J, P, x( d E, o - *返回值 :无# }6 g% R' ?% K% j1 J# _! \
- *说明 :无
, O/ w. S7 `8 H- s0 [ - *******************************************************************************/' k* \" i& q" k; ~" f
- void Read_Flash(u32 *buff, u8 len)) [5 U1 z! M. \ V# m# M
- {
) e" d* |. P# S3 X - u8 k;1 _4 n( L" D: v+ B
- u32 Address;
4 o, U5 E, O, Q `/ X# `) M& ?& O - 1 }% \5 r/ | H" `/ b5 G: v
- Address = WriteFlashAddress;
- F6 x$ W! L0 ]$ r8 g8 j* }1 ? - for(k=0;k<len;k++)' R& H% ?6 j+ h; s3 D( d& z3 E( i
- {
& E* n+ I6 J' u0 Y0 l1 y - buff[k] = (*(vu32*) Address);//读指定地址的一个字的数据$ _) N3 P5 v0 \4 N6 [
- Address += 4;//地址偏移4个字节
5 }7 N1 N+ a' }3 \( q3 f - }
/ h+ v" k" ?* |8 b6 K8 _5 D - }
复制代码 2 T( z4 B) q# p: M7 y" X% }# J
main.c - int main(void)
5 E5 c, p1 V6 w$ F0 ?6 p5 F0 c" P; B7 V - {
. c/ e+ ]! c0 ^( | - " P) k4 [$ a) P0 v: D* W
- u32 in_data[5]={11,22,33,44,55};//要写入的数据+ w) y7 Y( {; B* O4 X9 r% v! ^# q
- u32 out_data[5];//读存放
8 h: A$ U2 W8 q9 e% t0 v - int i;
0 [1 o0 |- k) k$ w' H# M9 w9 D - u8 STATUS=0;8 w: L, Y# e" W
- USART1_Config();//串口1配置
. @: g" @ V# S( a N- s7 m* Y - GPIO_Configuration();//GPIO配置,用于点亮led! g Z; Y2 M7 U- I- u% o- u
- STATUS=Write_Flash(in_data,5);
* x9 i( {! b# { - Delay(0x02FFFF);0 y/ t, p* ~% i7 p5 q
- if(STATUS)4 f8 A; ^% @: ]4 ]/ O+ }+ T
- {1 _! V+ J0 G- m6 i! F
- GPIO_SetBits(GPIOD, GPIO_Pin_13);//点亮led1* p- W9 v4 O: A
- Read_Flash(out_data,5);
2 t. e r4 m% I) T2 q - printf("\r\n The Five Data Is : \r\n");' j. C& B% t! D2 _; j
- for(i=0;i<5;i++)
, W& q, y- ]+ S; B - {
3 D3 {4 G1 ?8 a - printf("\r %d \r",out_data[i]);" `6 L! ]" ^# x) Q9 z2 `
- }
C5 |) {3 y, W# I' O1 w - }
- q) }" E, I# R' Q9 D - while(1);2 \7 x' ?# H9 i! c2 c$ C' Y1 H: }' n
- }
复制代码 9 b# e$ _4 _+ k0 ?" q
|