STM32内部FLASH读写操作详解

合集下载

STM32内部FLASH读写操作详解

STM32内部FLASH读写操作详解

STM32内部FLASH读写操作详解
在STM32中,FLASH存储器被分为多个扇区。

每个扇区的大小根据芯
片型号而定,可以是16KB、32KB、64KB等大小。

每个扇区又被分为若干
个页,每个页的大小为2KB、4KB、8KB等。

读取FLASH数据的操作相对简单,可以通过读取内存地址的方式来实现。

由于FLASH时序特殊,读取速度相对较慢,所以在使用FLASH存储数
据时需要考虑读取的效率。

写入FLASH数据时,需要注意以下几点:
1.写入数据必须按照页的大小进行,即每次写入的数据不能超过页的
大小。

2.写入数据时,必须将FLASH模块解锁,否则写入操作将被禁止。


入完成后,需要将FLASH模块重新锁定。

3.写入FLASH数据时,如果写入的数据与指定地址处的数据不相同,
会导致页擦除。

所以在写入之前,需要将指定地址处的数据保存下来,并
进行适当的处理。

4.写入FLASH数据后,需要等待写入操作完成,然后进行擦除操作。

擦除操作可以是扇区擦除或页擦除。

除了普通的读写操作,STM32内部FLASH还提供了一些高级的功能,
如扇区擦除、页擦除、半页擦除、字节擦除等。

这些功能可以根据实际需
求进行选择和应用。

总结起来,对于STM32内部FLASH的读写操作,需要注意解锁和锁定FLASH模块、按页写入数据、写入完整性的保证、擦除操作的执行等细节。

通过合理的使用这些操作,可以实现对STM32内部FLASH的有效管理和利用。

STM32学习笔记:读写内部Flash(介绍+附代码)

STM32学习笔记:读写内部Flash(介绍+附代码)

STM32学习笔记:读写内部Flash(介绍+附代码)⼀、介绍⾸先我们需要了解⼀个内存映射:stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯⽚实际的flash⼤⼩,不同的芯⽚flash⼤⼩不同。

RAM起始地址是0x2000 0000,结束地址是0x2000 0000加上芯⽚的RAM⼤⼩。

不同的芯⽚RAM也不同。

Flash中的内容⼀般⽤来存储代码和⼀些定义为const的数据,断电不丢失,RAM可以理解为内存,⽤来存储代码运⾏时的数据,变量等等。

掉电数据丢失。

STM32将外设等都映射为地址的形式,对地址的操作就是对外设的操作。

stm32的外设地址从0x4000 0000开始,可以看到在库⽂件中,是通过基于0x4000 0000地址的偏移量来操作寄存器以及外设的。

⼀般情况下,程序⽂件是从 0x0800 0000 地址写⼊,这个是STM32开始执⾏的地⽅,0x0800 0004是STM32的中断向量表的起始地址。

在使⽤keil进⾏编写程序时,其编程地址的设置⼀般是这样的:程序的写⼊地址从0x08000000(数好零的个数)开始的,其⼤⼩为0x80000也就是512K的空间,换句话说就是告诉编译器flash的空间是从0x08000000-0x08080000,RAM的地址从0x20000000开始,⼤⼩为0x10000也就是64K的RAM。

这与STM32的内存地址映射关系是对应的。

M3复位后,从0x08000004取出复位中断的地址,并且跳转到复位中断程序,中断执⾏完之后会跳到我们的main函数,main函数⾥边⼀般是⼀个死循环,进去后就不会再退出,当有中断发⽣的时候,M3将PC指针强制跳转回中断向量表,然后根据中断源进⼊对应的中断函数,执⾏完中断函数之后,再次返回main函数中。

⼤致的流程就是这样。

1.1、内部Flash的构成:STM32F429 的内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及⼤⼩如下:STM32F103的中容量内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及⼤⼩如下:注意STM32F105VC的是有64K或128页x2K=256k字节的内置闪存存储器,⽤于存放程序和数据。

STM32 FLASH操作

STM32 FLASH操作

STM32 flash操作对芯片内部flash进行操作的函数,包括读取,状态,擦除,写入等等,可以允许程序去操作flash上的数据。

一、存储器映射1、统一编址,程序存储器、数据存储器、外设寄存器组织在一个4GB 的地址空间。

2、小端格式3、映像(stm32f107,256KB产品)可以看到,所谓的256KB闪存,是指主存储,片上FLASH如下图所示:介绍了片上的资源后,来看他们的地址映像。

芯片将4GB的空间,划分为8个512MB的块(block),这些块有些是整块不用的,芯片对地址的安排可以参考数据手册,memory mapping章节中的那个图。

只有block1、2、3、7是使用的。

地址中block7是核内的外设对应的地址,block2是其他外设对应的地址。

block1的低地址64KB是片上SRAM,block0则如下图option bytes即是选项字节;system memory就是系统存储,也即片上ROM;这两部分就是所谓信息块。

Flash就是指主存储,有256KB。

再往下看alias to flash or system memory.....这个区域256KB就是启动开始的区域。

这个区域并没有一个自己的存储器,只是根据BOOT0、BOOT1的接法来选择哪个存储器映射到这个地址上。

如下图选择用户闪存启动,是典型的做法;选择系统存储器,则在ST烧写进去的自举程序引导下,通过USART1下载程序;选择从SRAM执行代码则方便调试,比较快。

二、复位CM3将复位视作异常,优先级最高的异常。

stm32f1有三种复位:系统复位、电源复位、备份区复位。

前两种是真正的复位,对他的响应由硬件完成,这个响应对软件流的影响是这样的:程序指针指向0x0000 0004,这个单元存储的是复位服务子程序(或者汇编叫子过程),同时从0x0000 0000获取堆栈顶的地址。

不同的复位类型还有对其他寄存的不同复位方式,这就完成了复位。

STM32的FLASH操作

STM32的FLASH操作

关于STM32的FLASH操作说到STM32的FLSAH,我们的第一反应是用来装程序的,实际上,STM32的片内FLASH不仅用来装程序,还用来装芯片配置、芯片ID、自举程序等等。

当然,FLASH还可以用来装数据。

FLASH分类根据用途,STM32片内的FLASH分成两部分:主存储块、信息块。

主存储块用于存储程序,我们写的程序一般存储在这里。

信息块又分成两部分:系统存储器、选项字节。

系统存储器存储用于存放在系统存储器自举模式下的启动程序(BootLoader),当使用ISP方式加载程序时,就是由这个程序执行。

这个区域由芯片厂写入BootLoader,然后锁死,用户是无法改变这个区域的。

选项字节存储芯片的配置信息及对主存储块的保护信息。

FLASH的页面STM32的FLASH主存储块按页组织,有的产品每页1KB,有的产品每页2KB。

页面典型的用途就是用于按页擦除FLASH。

从这点来看,页面有点像通用FLASH的扇区。

STM32产品的分类STM32根据FLASH主存储块容量、页面的不同,系统存储器的不同,分为小容量、中容量、大容量、互联型,共四类产品。

小容量产品主存储块1-32KB,每页1KB。

系统存储器2KB。

中容量产品主存储块64-128KB,每页1KB。

系统存储器2KB。

大容量产品主存储块256KB以上,每页2KB。

系统存储器2KB。

互联型产品主存储块256KB以上,每页2KB。

系统存储器18KB。

对于具体一个产品属于哪类,可以查数据手册,或根据以下简单的规则进行区分:STM32F101xx、STM32F102xx 、STM32F103xx产品,根据其主存储块容量,一定是小容量、中容量、大容量产品中的一种,STM32F105xx、STM32F107xx 是互联型产品。

互联型产品与其它三类的不同之处就是BootLoader的不同,小中大容量产品的BootLoader只有2KB,只能通过USART1进行ISP,而互联型产品的BootLoader 有18KB,能通过USAT1、4、CAN等多种方式进行ISP。

STM32实现内部Flash的读写(HAL库版)

STM32实现内部Flash的读写(HAL库版)

STM32实现内部Flash的读写(HAL库版) Flash 中⽂名字叫闪存,是⼀种长寿命的⾮易失性(断电数据不丢失)的存储器。

可以对称为块的存储器单元块进⾏擦写和再编程,在进⾏写⼊操作之前必须先执⾏擦除。

⼀个Nand Flash由多个块(Block)组成,每个块⾥⾯⼜包含很多页(page)。

每个页对应⼀个空闲区域/冗余区域(spare area),这个区域不是⽤来存储数据的,⽤于放置数据的校验值检测和纠错的。

块,是Nand Flash的擦除操作的基本/最⼩单位。

页,是Nand Flash的写⼊操作的基本/最⼩的单位。

⾸先简要写⼀下FLASH的读写流程: 对FLASH写⼊数据 解锁FLASH 擦除FLASH 写⼊数据到FLASH 锁住FLASH FLASH读取数据(直接读取相应的FLASH地址即可) 操作MCU⾥的Flash,还有⼏个注意事项: 1、往Flash写⼊数据的时候,要先对要写⼊的页进⾏擦除,如果要写的页⾥有数据,要先读出来在缓存区,再把页擦除,再写⼊数据;在擦除页之后,只要这次你写的数据⼤⼩不够⼀页,可以连续写⼊。

2、要计算好程序的内存,因为你的程序也是保存在MCU的Flash⾥的,如果你操作到保存着程序的内存,程序就会死掉,⾄于程序内存怎么看,你可以⽣成bin⽂件,bin⽂件的⼤⼩就是你程序所占内存的⼤⼩了,⽣成bin⽂件可以参考博客:;程序内存基本都是从Flash内存⼀开始存起的,这⾥以STM32Fo72c8t6举例,如下图。

看图可以看出,这个芯⽚的Flash内存范围是0x0800 0000 ~ 0x0802 0000 ,假设我要烧录进去的bin⽂件为10K,那我们操作Flash的时候,地址就要从0x0800 0000 + (0x400*11) 开始,避开程序的存储位置,Flash地址偏移1位就是1个字节。

3、要注意MCU⼀页的⼤⼩,⼀些MCU⼀页是1KB,⼀些MCU⼀页是2KB 下⾯举个例⼦写⼊数据0x0001到Flash中uint16_t my_add = 0x0001; uint32_t Robot_Num_Flash_Add = 0x08005000;FLASH_EraseInitTypeDef My_Flash; //声明 FLASH_EraseInitTypeDef 结构体为 My_FlashHAL_FLASH_Unlock();//解锁FlashMy_Flash.TypeErase = FLASH_TYPEERASE_PAGES; //标明Flash执⾏页⾯只做擦除操作My_Flash.PageAddress = Robot_Num_Flash_Add; //声明要擦除的地址My_Flash.NbPages = 1; //说明要擦除的页数,此参数必须是Min_Data = 1和Max_Data =(最⼤页数-初始页的值)之间的值uint32_t PageError = 0; //设置PageError,如果出现错误这个变量会被设置为出错的FLASH地址HAL_FLASHEx_Erase(&My_Flash, &PageError); //调⽤擦除函数擦除uint16_t Write_Flash_Data = my_add; //对Flash进⾏烧写,FLASH_TYPEPROGRAM_HALFWORD 声明操作的Flash地址的16位的,此外还有32位跟64位的操作,⾃⾏翻查HAL库的定义即可 HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Robot_Num_Flash_Add, Write_Flash_Data);HAL_FLASH_Lock(); //锁住Flash 写完之后,接着就到读了,Flash写有次数限制,写的次数在1W次还是10W次(忘了)就不可写⼊了,⽽读是没有次数限制的,读多少次都可以,下⾯就把写⼊到Flash⾥的数据0x0001读出来uint32_t Robot_Num_Flash_Add = 0x08005000; ID_Num = *(__IO uint16_t*)( Robot_Num_Flash_Add ); //*(__IO uint16_t *)是读取该地址的参数值,其值为16位数据,⼀次读取两个字节,*(__IO uint32_t *)就⼀次读4个字节 printf("ID_num:0x%x\r\n", ID_Num); 经过上⾯的程序就可以实现 STM32 中 Flash 数据的读写了,具体怎么读写,每个案⼦不同,各位就可以根据需求去修改,只要注意好注意事项即可,代码已经实测可⽤。

关于STM32的flash读写数据和HardFault

关于STM32的flash读写数据和HardFault

关于STM32的flash读写数据和HardFault今天调试程序的时候需要把掉电前的数据存储到flash中之后等待下次初始化的时候把数据读进来。

刚刚开始的时候去找了一些stm32的flash的操作,真的是废话连篇的真正能用到的没几句话,这里我把自己调试好的flash读写数据的子函数跟大家分享一下。

void FLASH_WriteByte(u32 addr ,u16 flashdata1){FLASH_Status FLASHstatus = FLASH_COMPLETE;FLASH_Unlock();//解锁FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);FLASHstatus=FLASH_ErasePage(addr);//擦除整页FLASHstatus=FLASH_ProgramHalfWord(addr, flashdata1);//写入数据FLASH_Lock();//锁定}这个子函数就是将数据flashdata1写到地址addr中去。

数据的长度是可变的。

当需要读入数据的时候可以直接访问地址,如:rdata=*(u16 *)0x08014000; //读flash中默认数据0x08014000是存储的地址。

这样大家应该很清楚了吧。

flash读写数据还是比较简单的,这里希望能帮到大家。

但是在写入数据的时候,又遇到了另一个问题,就是程序运行的时候进入到这个HardFault_Handler函数中死循环了,不知道大家有没有遇到过这个问题,后来我查了一些资料,发现可能是存储器的分配有问题。

然后把地址改到更大的地方,又试了试,发现已经可以了。

建议大家这样试一试。

下面是我找的关于防止误擦除有用程序代码的方法方法一:首先要计算程序代码有多少,把FLASH存取地址设置在程序代码以外的地方,这样就不会破坏用户程序。

STM32库开发实战指南-M4:50-读写内部FLASH

STM32库开发实战指南-M4:50-读写内部FLASH

第50章读写内部FLASH本章参考资料:《STM32F4xx参考手册》、《STM32F4xx规格书》、库说明文档《stm32f4xx_dsp_stdperiph_lib_um.chm》。

50.1STM32的内部FLASH简介在STM32芯片内部有一个FLASH存储器,它主要用于存储代码,我们在电脑上编写好应用程序后,使用下载器把编译后的代码文件烧录到该内部FLASH中,由于FLASH存储器的内容在掉电后不会丢失,芯片重新上电复位后,内核可从内部FLASH中加载代码并运行,见图50-1。

图50-1STM32的内部框架图除了使用外部的工具(如下载器)读写内部FLASH外,STM32芯片在运行的时候,也能对自身的内部FLASH进行读写,因此,若内部FLASH存储了应用程序后还有剩余的空间,我们可以把它像外部SPI-FLASH那样利用起来,存储一些程序运行时产生的需要掉电保存的数据。

由于访问内部FLASH的速度要比外部的SPI-FLASH快得多,所以在紧急状态下常常会使用内部FLASH存储关键记录;为了防止应用程序被抄袭,有的应用会禁止读写内部FLASH中的内容,或者在第一次运行时计算加密信息并记录到某些区域,然后删除自身的部分加密代码,这些应用都涉及到内部FLASH的操作。

1.内部FLASH的构成STM32的内部FLASH包含主存储器、系统存储器、OTP区域以及选项字节区域,它们的地址分布及大小见表50-1。

表50-1STM32内部FLASH的构成区域块名称块地址大小主存储器块1扇区00x08000000-0x08003FFF16Kbytes扇区10x08004000-0x08007FFF16Kbytes扇区20x08008000-0x0800BFFF16Kbytes扇区30x0800C000-0x0800FFFF16Kbyte扇区40x08010000-0x0801FFFF64Kbytes扇区50x08020000-0x0803FFFF128Kbytes扇区60x08040000-0x0805FFFF128Kbytes扇区70x08060000-0x0807FFFF128Kbytes扇区80x08080000-0x0809FFFF128Kbytes扇区90x080A0000-0x080B FFFF128Kbytes扇区100x080C0000-0x080D FFFF128Kbytes扇区110x080E0000-0x080F FFFF128Kbytes 块2扇区120x08100000-0x08103FFF16Kbytes扇区130x08104000-0x08107FFF16Kbytes扇区140x08108000-0x0810BFFF16Kbytes扇区150x0810C000-0x0810FFFF16Kbyte扇区160x08110000-0x0811FFFF64Kbytes扇区170x08120000-0x0813FFFF128Kbytes扇区180x08140000-0x0815FFFF128Kbytes扇区190x08160000-0x0817FFFF128Kbytes扇区200x08180000-0x0819FFFF128Kbytes扇区210x081A0000-0x081B FFFF128Kbytes扇区220x081C0000-0x081D FFFF128Kbytes扇区230x081E0000-0x081F FFFF128Kbytes系统存储区0x1FFF0000-0x1FFF77FF30Kbytes OTP区域0x1FFF7800-0x1FFF7A0F528bytes选项字节块10x1FFF C000-0x1FFF C00F16bytes 块20x1FFE C000-0x1FFE C00F16bytes各个存储区域的说明如下:主存储器一般我们说STM32内部FLASH的时候,都是指这个主存储器区域,它是存储用户应用程序的空间,芯片型号说明中的1M FLASH、2M FLASH都是指这个区域的大小。

STM32-FLASH读写

STM32-FLASH读写

最近在学STM32,要用到内部flash存点数据,一开始在网上看了很多例程,自己写了一个,当到单片机中,一点反应没有,于是又到网上看了又看,找啊找,发现这样的读写内部flash 的软件不多,而且说的也不是很明确(个人观点),特地总结了一下,希望对刚学STM32的小伙伴有帮助。

注意:写数据的地址(红色字),如果你的boot1=x,boot0=0,那么你的启动模式是用户闪存存储器,而这个用户闪存存储器的地址就是0x08000000。

这个很重要!!!!!我用的是STM32F103VET6,下面是写内部flash的子程序:#include "flash.h"#define STARTADDR 0x0807F800 //主存储器第255页首地址volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;/*读内部flash的指定地址的N个字节;ReadAddress:指定地址。

ReadBuf:数据存储指针。

ReadNum:读取字节数。

*/void ReadFlashNBtye(uint32_t ReadAddress, uint8_t *ReadBuf, int32_t ReadNum){int DataNum = 0;ReadAddress = (uint32_t)STARTADDR + ReadAddress;while(DataNum < ReadNum){*(ReadBuf + DataNum) = *(__IO uint8_t*) ReadAddress++;DataNum++;}// return DataNum;}/*向内部flash写入数据WriteAddress:写数据地址偏移量。

WriteData:写入的数据。

*/void WriteFlashOneWord(uint32_t WriteAddress,uint32_t WriteData){FLASH_Unlock();FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);FLASHStatus = FLASH_ErasePage(STARTADDR);//擦除一页FLASH_EraseAllPages():擦除全// 部FLASH 页面if(FLASHStatus == FLASH_COMPLETE){FLASHStatus = FLASH_ProgramWord(STARTADDR + WriteAddress, WriteData);}FLASH_Lock();}函数调用:例:u8 Temp_Data[4] = { 0 };WriteFlashOneWord( 0 , 0x12345678 );delay_ms(10);ReadFlashNBtye( 0 , Temp_Data , 4 );delay_ms(10);这样数据就写入了内部flash,读出时就放在了Temp_Data[4]中。

读写STM32内部flash读写代码

读写STM32内部flash读写代码

读写STM32内部flash读写代码分类:单片机stm32 2012-03-25 06:16 10343人阅读评论(2) 收藏举报flashfunctionbyte编程存储io由于老师的要求,所以写了一份读写STM32内部FLASH的代码,这样的话就可以把STM32里面没有用来保存代码段的部分用来存储数据了。

由于《stm32flash编程手册》是很久很久以前看的,现在也没心情去仔细看那份手册了。

大概浏览了一下,只看到了STM32里面的flash是以16位为单位读写的。

为什么记住这个,因为之前想写一个字节老是出错,所以翻翻手册,果然看到不能写1个字节数据。

而且还发现,flash写地址为奇数时也会出错。

所以这份代码里面写flash的地址只能是偶数。

浏览过程中还发现,手册里面说写flash和擦除flash的时候会影响cpu的运行速度,没仔细看(真心不想看)。

其他具体手册里面的资料的话没有了,看有没有高手仔细看完,然后写个总结什么的。

而且flash的读写保护也没看清楚,好像这些保护都是针对页大小来保护的话。

这样的话就可以只保护代码段,这些放数据段不用保护了,这样可以省下flash芯片,不错吧。

废话不多说,直接上代码。

flash读写代码也不用初始化,拿来直接就用。

哈哈。

-------------------DataFlash.c----------------------------------#include "DataFlash.h"uint16_t Flash_Write_Without_check(uint32_t iAddress, uint8_t *buf, uint16_t iNumByteToWrite) {uint16_t i;volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;i = 0;// FLASH_UnlockBank1();while((i < iNumByteToWrite) && (FLASHStatus == FLASH_COMPLETE)) {FLASHStatus = FLASH_ProgramHalfWord(iAddress, *(uint16_t*)buf);i = i+2;iAddress = iAddress + 2;buf = buf + 2;}return iNumByteToWrite;}/*** @brief Programs a half word at a specified Option Byte Data address. * @note This function can be used for all STM32F10x devices.* @param Address: specifies the address to be programmed.* @param buf: specifies the data to be programmed.* @param iNbrToWrite: the number to write into flash* @retval if success return the number to write, -1 if error**/int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite) {/* Unlock the Flash Bank1 Program Erase controller */ uint32_t secpos;uint32_t iNumByteToWrite = iNbrToWrite;uint16_t secoff;uint16_t secremain;uint16_t i = 0;uint8_t tmp[FLASH_PAGE_SIZE];FLASH_UnlockBank1();secpos=iAddress & (~(FLASH_PAGE_SIZE -1 )) ;//扇区地址secoff=iAddress & (FLASH_PAGE_SIZE -1); //在扇区内的偏移secremain=FLASH_PAGE_SIZE-secoff; //扇区剩余空间大小volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;if(iNumByteToWrite<=secremain) secremain = iNumByteToWrite;//不大于4096个字节while( 1 ) {Flash_Read(secpos, tmp, FLASH_PAGE_SIZE); //读出整个扇区for(i=0;i<secremain;i++) { //校验数据if(tmp[secoff+i]!=0XFF)break; //需要擦除}if(i<secremain) { //需要擦除FLASHStatus = FLASH_ErasePage(secpos); //擦除这个扇区if(FLASHStatus != FLASH_COMPLETE)return -1;for(i=0;i<secremain;i++) { //复制tmp[i+secoff]=buf[i];}Flash_Write_Without_check(secpos ,tmp ,FLASH_PAGE_SIZE);//写入整个扇区} else {Flash_Write_Without_check(iAddress,buf,secremain);//写已经擦除了的,直接写入扇区剩余区间.}if(iNumByteToWrite==secremain) //写入结束了break;else {secpos += FLASH_PAGE_SIZE;secoff = 0;//偏移位置为0buf += secremain; //指针偏移iAddress += secremain;//写地址偏移iNumByteToWrite -= secremain; //字节数递减if(iNumByteToWrite>FLASH_PAGE_SIZE)secremain=FLASH_PAGE_SIZE;//下一个扇区还是写不完else secremain = iNumByteToWrite; //下一个扇区可以写完了}}FLASH_LockBank1();return iNbrToWrite;}/*** @brief Programs a half word at a specified Option Byte Data address. * @note This function can be used for all STM32F10x devices.* @param Address: specifies the address to be programmed.* @param buf: specifies the data to be programmed.* @param iNbrToWrite: the number to read from flash* @retval if success return the number to write, without error**/int Flash_Read(uint32_t iAddress, uint8_t *buf, int32_t iNbrToRead) { int i = 0;while(i < iNbrToRead ) {*(buf + i) = *(__IO uint8_t*) iAddress++;i++;}return i;}-------------------DataFlash.h----------------------------------#ifndef __DATAFLASH_H__#define __DATAFLASH_H__#include "stm32f10x.h"#include "stm32f10x_flash.h"#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) || defined (STM32F10X_XL)#define FLASH_PAGE_SIZE ((uint16_t)0x800)#else#define FLASH_PAGE_SIZE ((uint16_t)0x400)#endifint Flash_Read(uint32_t iAddress, uint8_t *buf, int32_t iNbrToRead) ;int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite);#endif。

STM32内部FLASH读写操作详解

STM32内部FLASH读写操作详解

STM32芯片内部的FLASH存储器,主要用于存储我们代码。

如果内部FLASH存储完我们的代码还有剩余的空间,那么这些剩余的空间我们就可以利用起来,存储一些需要掉电保存的数据。

本文以STM32103ZET6为例。

STM32103ZET6属于大容量产品,其闪存模块组织如下:其主存储器大小为512KB,分为256页,每页大小都为2KB。

我们的程序- 般默认烧写到第0页的起始地址(0x08000000)处。

当BOOT0引脚和BOOT1引脚都接GND时,就是从这个地址开始运行代码的。

这个地址在keil中可以看到:回I Options for Target'FLASH'D evic e Target ' Output | Li sting User C/C++ Asm Linkei Debug Utilities ' 假如我们要下载的程序大小为4.05KB,则第0、1、2页用于保存我们的程 序,我们需要掉电保存的数据只能保存在第3〜第255页这一部分空间内。

我们最终要下载的程序大小可在工程对应的.map 文件中看到。

.map 文件可以双 击工程的Target 的名字快速打开,如:下面对STM32内部FLASH 进行简单的读写测试: 内部FLASH 读写测试 流程图如下:本流程图省略异常情况,只考虑成功的情况:由反£419S ( 4P eike :iSTMicroelectnnics STM32F13GZE1rm乂 ।F -J y.dPtripl\Cn\ifeij sEN32H[h :_na5hh二| 立府211以一Lr a nd " c^tu J ■EL户 inagt latalsROM Totals耳 QR Ct它 PcOirn.!:T u Tt57HJx_hkp.c wn n Fil K _< a n,= tTn32Fllx cezce 口system.1示例代码:本例的关键代码如下(以读写第255页为例):/、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、上、上Ki> /力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、Ki^、上、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、上、上Ki> 个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个小* ------------------------------------------- STM32 Demo ------------------------------------------- 工程说明:STM32内部FLASH 实验 作 者:ZhengNian博 客:zhengnianli.github.io 公众号:嵌入式大杂烩Ki^、上、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、上、上Ki> 个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个小Ki^、上、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、上、卜 / 力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、/#define MAIN_CONFIG #include "config.h/* STM32F103ZET6有256页,每一页的大小都为2KB */#define ADDR_FLASH_PAGE_255 ((uint32_t)0x0807F800) /* Page255 2KB */* * * * */* FLASH读写测试结果*/#define TEST_ERROR -1 /* 错误(擦除、写入错误)*/#define TEST_SUCCESS 0 /* 成功*/#define TEST_FAILED 1 /* 失败*/ /* Flash读写测试buf */#define BufferSize 6uint16_t usFlashWriteBuf[BufferSize]={0x0101,0x0202,0x0303,0x0404,0x0505,0x0606};uint16_t usFlashReadBuf[BufferSize] = {0};/*供本文件调用的函数声明*/ static int FlashReadWriteTest(void);小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小** 函数:main** --------------------------------------------------------------------------------------------------------- ** 参数:void**返回:无**说明:主函数小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小int main(void){/*上电初始化*/SysInit();/*内部Flash读写测试*/if (TEST_SUCCESS == FlashReadWriteTest()){printf("Flash test success!\n");}else{printf("Flash test failed!\n");}while (1) {}}小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小**函数:FlashReadWriteTest,内部Flash读写测试函数** ---------------------------------------------------------------------------------------------------------** 参数:void**返回:TEST_ERROR:错误(擦除、写入错误)TEST_SUCCESS:成功TEST_FAILED:失败**说明:无小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小小/*J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* *J* /static int FlashReadWriteTest(void) (uint32_t ucStartAddr;/*解锁*/FLASH_Unlock();/*擦除操作*/ucStartAddr = ADDR_FLASH_PAGE_255;if (FLASH_COMPLETE != FLASH_ErasePage(ucStartAddr)) (printf("Erase Error!\n");return TEST_ERROR;)else(ucStartAddr = ADDR_FLASH_PAGE_255;printf("擦除成功,此时FLASH中值为:\n");for (int i = 0; i < BufferSize; i++) (usFlashReadBuf[i] = *(uint32_t*)ucStartAddr;printf("ucFlashReadBuf[%d] = 0x%.4x\n”, i, usFlashReadBuf[i]);ucStartAddr += 2;))/*写入操作*/ucStartAddr = ADDR_FLASH_PAGE_255;printf("\n往FLASH中写入的数据为:\n");for (int i = 0; i < BufferSize; i++)(if (FLASH_COMPLETE != FLASH_ProgramHalfWord(ucStartAddr, usFlashWriteBuf[i]))(printf("Write Error!\n");return TEST_ERROR;)printf("ucFlashWriteBuf[%d] = 0x%.4x\n", i, usFlashWriteBuf[i]);ucStartAddr += 2;)/*上锁*/FLASH_Lock();/*读取操作*/ucStartAddr = ADDR_FLASH_PAGE_255;printf("\n从FLASH中读出的数据为:\n");for (int i = 0; i < BufferSize; i++)(usFlashReadBuf[i] = *(_IO uint16_t*)ucStartAddr;printf("ucFlashReadBuf[%d] = 0x%.4x\n”, i, usFlashReadBuf[i]); ucStartAddr += 2;)/*读出的数据与写入的数据做比较*/for (int i = 0; i < BufferSize; i++)(if (usFlashReadBuf[i] != usFlashWriteBuf[i])(return TEST_FAILED;))return TEST_SUCCESS;)/、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、上、上/力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、、上、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、上、上个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个小** End Of File、上、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、上、上个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个个小、上、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、卜、上、卜 / 力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、力、/ (1)进行解锁操作STM32的闪存编程是由内嵌的闪存编程/擦除控制器(FPEC)管理,这个模块包含的寄存器如下:STM32复位后,FPEC模块是被保护的,不能写入FLASH_CR寄存器;通过写入特定的序列到FLASH_KEYR寄存器可以打开FPEC模块(即写入KEY1和KEY2),只有在写保护被解除后,我们才能操作相关寄存器。

关于STM32的FLASH操作

关于STM32的FLASH操作

关于STM32的FLASH操作STM32是一款由意法半导体(STMicroelectronics)推出的32位精简型单片机系列。

它采用了ARM Cortex-M内核,并在Flash和内存等方面进行了优化,提供了强大的性能和丰富的外设功能。

FLASH是STM32芯片上的一种非易失性存储器,可以用于存储应用程序代码、数据、配置信息等。

在STM32中进行FLASH操作可以通过编程和标准库函数两种方式实现。

下面将依次介绍这两种方法的使用。

一、编程方式编程方式是直接对FLASH进行底层的读写操作,需要对相关寄存器进行配置和控制。

1.写入数据在STM32的FLASH中写入数据的操作需要经历以下步骤:1) 解锁FLASH:通过FLASH_Unlock(函数解锁FLASH,使其可写入。

2) 擦除FLASH:通过FLASH_ErasePage(函数擦除要写入的FLASH扇区。

3) 写入数据:通过FLASH_ProgramByte(、FLASH_ProgramHalfWord(、FLASH_ProgramWord(等函数对FLASH进行数据写入。

4) 上锁FLASH:通过FLASH_Lock(函数上锁FLASH,防止误操作。

以下是一个简单的例子,演示如何通过编程方式对STM32的FLASH进行数据写入:```c#include "stm32f10x_flash.h"void ConfigureFlash(void)FLASH_Unlock(; // 解锁FlashFLASH_ClearFlag(FLASH_FLAG_EOP , FLASH_FLAG_PGERR ,FLASH_FLAG_WRPRTERR); // 清除状态标志FLASH_ErasePage(FLASH_START_ADDR); // 擦除扇区FLASH_Lock(; // 上锁Flash```2.读取数据读取STM32的FLASH数据需要通过指针的方式直接读取存储器的地址,如下所示:```c#define READ_FLASH(addr) (*(volatile uint32_t*)(addr))void ReadFlash(void)uint32_t data = READ_FLASH(FLASH_START_ADDR);//在这里对读取的数据进行处理```二、标准库函数方式STM32提供了一套标准库函数,方便开发者进行FLASH操作。

STM32F103RCT6之FLASH读写操作

STM32F103RCT6之FLASH读写操作

STMFLASH_Lock();//操作结束后,锁定 } 10、从指定的地址读指定长度的数据 void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)
{ u16 i; for(i=0;i { pBuffer[i]=STMFLASH_ReadHalfWord(ReadAddr);//读取改地址数据 ReadAddr+=2;// 一次读取两字节的数据,因此地址要相应的+2 } } 以上是根据正点原子迷你 STM32 开发板的历程做的解析,其实懂得了 操作原理后,完全可以自己去写了。
STM32F103RCT6 之 FLASH 读写操作
一、STM32F103 的 FLASH 简介 1、如图所示,STM32F103 内部 FLASH 存储区分为三个区域:主存储 区、信信息块和闪存存储器接口寄存器。 储存储区是我们读写 FLASH 的主要的存储区,MCU 程序以及一些需要 掉电保存的数据都是存储在这个区域的。 信息快:程序启动代码被存储在这部分。 最后的寄存器则是 FLASH 读写需要配置的一些寄存器位置。
} 4、等待操作完成函数
u8 STMFLASH_WaitDone(u16 time) { u8 res; do { res=STMFLASH_GetStatus();//读取 FLASH 状态是否处于忙碌状态 if(res!=1)break;//非忙碌状态则 break
delay_us(1);
time--; }while(time); if(time==0)res=0xff;//TIMEOUT 超时了,res 等于 0xff return res;//操作完成返回 0
主存储器的起始位置 0x08000000,除去程序占用的空间,剩余部分就可 以作为数据保存的区域了,所以在利用内部 FLASH 存储数据的时候, 一定不要占用程序本身所占用的空间,否则会导致死机。

读写STM32内部flash读写代码

读写STM32内部flash读写代码

读写STM32内部flash读写代码分类:单片机stm32 2012-03-25 06:16 10343人阅读评论(2) 收藏举报flashfunctionbyte编程存储io由于老师的要求,所以写了一份读写STM32内部FLASH的代码,这样的话就可以把STM32里面没有用来保存代码段的部分用来存储数据了。

由于《stm32flash编程手册》是很久很久以前看的,现在也没心情去仔细看那份手册了。

大概浏览了一下,只看到了STM32里面的flash是以16位为单位读写的。

为什么记住这个,因为之前想写一个字节老是出错,所以翻翻手册,果然看到不能写1个字节数据。

而且还发现,flash写地址为奇数时也会出错。

所以这份代码里面写flash的地址只能是偶数。

浏览过程中还发现,手册里面说写flash和擦除flash的时候会影响cpu的运行速度,没仔细看(真心不想看)。

其他具体手册里面的资料的话没有了,看有没有高手仔细看完,然后写个总结什么的。

而且flash的读写保护也没看清楚,好像这些保护都是针对页大小来保护的话。

这样的话就可以只保护代码段,这些放数据段不用保护了,这样可以省下flash芯片,不错吧。

废话不多说,直接上代码。

flash读写代码也不用初始化,拿来直接就用。

哈哈。

-------------------DataFlash.c----------------------------------#include "DataFlash.h"uint16_t Flash_Write_Without_check(uint32_t iAddress, uint8_t *buf, uint16_t iNumByteToWrite) {uint16_t i;volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;i = 0;// FLASH_UnlockBank1();while((i < iNumByteToWrite) && (FLASHStatus == FLASH_COMPLETE)) {FLASHStatus = FLASH_ProgramHalfWord(iAddress, *(uint16_t*)buf);i = i+2;iAddress = iAddress + 2;buf = buf + 2;}return iNumByteToWrite;}/*** @brief Programs a half word at a specified Option Byte Data address. * @note This function can be used for all STM32F10x devices.* @param Address: specifies the address to be programmed.* @param buf: specifies the data to be programmed.* @param iNbrToWrite: the number to write into flash* @retval if success return the number to write, -1 if error**/int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite) {/* Unlock the Flash Bank1 Program Erase controller */ uint32_t secpos;uint32_t iNumByteToWrite = iNbrToWrite;uint16_t secoff;uint16_t secremain;uint16_t i = 0;uint8_t tmp[FLASH_PAGE_SIZE];FLASH_UnlockBank1();secpos=iAddress & (~(FLASH_PAGE_SIZE -1 )) ;//扇区地址secoff=iAddress & (FLASH_PAGE_SIZE -1); //在扇区内的偏移secremain=FLASH_PAGE_SIZE-secoff; //扇区剩余空间大小volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;if(iNumByteToWrite<=secremain) secremain = iNumByteToWrite;//不大于4096个字节while( 1 ) {Flash_Read(secpos, tmp, FLASH_PAGE_SIZE); //读出整个扇区for(i=0;i<secremain;i++) { //校验数据if(tmp[secoff+i]!=0XFF)break; //需要擦除}if(i<secremain) { //需要擦除FLASHStatus = FLASH_ErasePage(secpos); //擦除这个扇区if(FLASHStatus != FLASH_COMPLETE)return -1;for(i=0;i<secremain;i++) { //复制tmp[i+secoff]=buf[i];}Flash_Write_Without_check(secpos ,tmp ,FLASH_PAGE_SIZE);//写入整个扇区} else {Flash_Write_Without_check(iAddress,buf,secremain);//写已经擦除了的,直接写入扇区剩余区间.}if(iNumByteToWrite==secremain) //写入结束了break;else {secpos += FLASH_PAGE_SIZE;secoff = 0;//偏移位置为0buf += secremain; //指针偏移iAddress += secremain;//写地址偏移iNumByteToWrite -= secremain; //字节数递减if(iNumByteToWrite>FLASH_PAGE_SIZE)secremain=FLASH_PAGE_SIZE;//下一个扇区还是写不完else secremain = iNumByteToWrite; //下一个扇区可以写完了}}FLASH_LockBank1();return iNbrToWrite;}/*** @brief Programs a half word at a specified Option Byte Data address. * @note This function can be used for all STM32F10x devices.* @param Address: specifies the address to be programmed.* @param buf: specifies the data to be programmed.* @param iNbrToWrite: the number to read from flash* @retval if success return the number to write, without error**/int Flash_Read(uint32_t iAddress, uint8_t *buf, int32_t iNbrToRead) { int i = 0;while(i < iNbrToRead ) {*(buf + i) = *(__IO uint8_t*) iAddress++;i++;}return i;}-------------------DataFlash.h----------------------------------#ifndef __DATAFLASH_H__#define __DATAFLASH_H__#include "stm32f10x.h"#include "stm32f10x_flash.h"#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) || defined (STM32F10X_XL)#define FLASH_PAGE_SIZE ((uint16_t)0x800)#else#define FLASH_PAGE_SIZE ((uint16_t)0x400)#endifint Flash_Read(uint32_t iAddress, uint8_t *buf, int32_t iNbrToRead) ;int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite);#endif。

stm32 flash读写例程

stm32 flash读写例程

stm32 flash读写例程摘要:I.简介- 介绍STM32 单片机和FLASH 存储器- 阐述STM32 FLASH 读写的重要性II.STM32 FLASH 读写原理- 介绍STM32 FLASH 的基本结构和特性- 讲解STM32 FLASH 读写的基本原理和流程III.STM32 FLASH 读写例程- 提供一个STM32 FLASH 读写例程的详细步骤- 解释例程中涉及到的关键代码和函数IV.总结- 总结STM32 FLASH 读写例程的关键点和注意事项- 提出进一步优化和改进的建议正文:I.简介STM32 是一种广泛应用于嵌入式系统的ARM Cortex-M 内核单片机。

它具有高性能、低功耗、多功能、易扩展等特点,被广泛应用于各种电子产品和工业控制领域。

在STM32 单片机中,FLASH 存储器是一种重要的非易失性存储器,用于存储程序代码和数据。

因此,熟练掌握STM32 FLASH 读写技术是进行嵌入式系统开发的基本技能之一。

II.STM32 FLASH 读写原理STM32 FLASH 存储器通常分为两个区域:系统区域和用户区域。

系统区域包含芯片制造商预先烧写的程序代码和数据,用户区域则用于存储用户自己的程序代码和数据。

STM32 FLASH 读写操作需要先对FLASH 进行初始化,然后通过特定的指令和函数进行读写操作。

STM32 FLASH 读写的基本原理和流程如下:1.初始化FLASH:在进行FLASH 读写操作之前,需要先对FLASH 进行初始化。

通过设置FLASH 的访问权限、时序和引脚等参数,为后续的读写操作做好准备。

2.读写FLASH 数据:通过使用特定的读写指令和函数,可以实现对FLASH 存储器中的数据进行读取和写入。

读取操作可以从FLASH 中获取程序代码和数据,而写入操作则可以将数据写入FLASH 的指定地址。

III.STM32 FLASH 读写例程下面提供一个简单的STM32 FLASH 读写例程,展示如何实现对FLASH 存储器的读写操作。

stm32 flash读写例程

stm32 flash读写例程

标题:深入理解STM32 Flash读写例程在嵌入式系统开发中,STM32系列芯片广泛应用于各类产品中,而Flash存储器作为其中重要的一部分,在储存程序代码和数据时扮演着至关重要的角色。

本文将深入探讨STM32芯片上的Flash读写例程,帮助读者更全面地理解和应用这一重要功能。

一、Flash存储器简介Flash存储器是一种非易失性存储器,它能够在断电后保持存储的数据不变。

在STM32芯片中,Flash存储器通常用于存储程序代码和配置数据,具有较大的存储容量和较快的读取速度。

Flash存储器通常被划分为多个扇区,每个扇区的大小和属性可能会有所差异。

二、STM32 Flash读写例程的基本操作在实际的嵌入式系统开发中,我们通常会需要对Flash存储器进行读写操作。

下面是一个简单的STM32 Flash读写例程,以帮助读者初步了解其基本操作:1. 初始化Flash模块:在进行Flash读写操作之前,首先需要初始化Flash模块,包括解锁Flash、擦除Flash扇区等操作。

2. 写入数据到Flash:一旦Flash模块初始化完成,就可以向Flash存储器中写入所需的数据。

需要注意的是,写入数据到Flash时,需要特别小心,以避免损坏已有的数据。

3. 从Flash读取数据:一旦数据写入Flash完成,就可以用相同的方式从Flash中读取数据。

三、深入探讨STM32 Flash读写例程的细节和注意事项虽然上面的例程提供了一个基本的操作流程,但在实际的项目中,我们还需要更深入地了解一些细节和注意事项,以确保程序的可靠性和稳定性。

1. Flash的扇区擦除:在对Flash进行写入操作之前,通常需要先对写入位置区域所在的Flash扇区进行擦除操作。

这是因为Flash的写入操作是以页为单位进行的,而擦除操作是以扇区为单位进行的。

如果不进行擦除操作,可能会导致写入操作失败或数据异常。

2. 写入数据的校验:在向Flash存储器写入数据后,需要进行数据的校验操作,以确保数据写入的正确性。

stm32 flash读写例程

stm32 flash读写例程

stm32 flash读写例程摘要:1.STM32 Flash存储器概述2.STM32 Flash读写操作步骤3.STM32 Flash读写实例4.注意事项正文:一、STM32 Flash存储器概述STM32 Flash存储器分为两个区域:系统区域和用户区域。

系统区域存储固件和启动代码,用户区域用于存储用户数据。

STM32提供了丰富的库函数和HAL(硬件层)驱动程序,方便开发者实现对Flash存储器的读写操作。

二、STM32 Flash读写操作步骤1.初始化:对Flash模块进行初始化,包括时钟、GPIO等。

2.擦除:在进行写入操作前,需要对目标区域进行擦除。

擦除方式以页为单位。

3.写入:将数据写入Flash存储器。

注意写入地址为奇数时可能会出错。

4.读取:从Flash存储器中读取数据。

三、STM32 Flash读写实例以下是一个简单的STM32 Flash读写实例:1.定义Flash 写入数据函数:```cvoid FlashWrite(uint32_t add, uint16_t dat) {// 打开Flash控制时钟RCCHSICMD(ENABLE);// 设置Flash写入地址FLASH_WriteAddress = add;// 写入16位数据FLASH_DataWrite(dat);// 等待Flash写入完成while (FLASH_BusyStatus != 0);// 关闭Flash控制时钟RCCHSICMD(DISABLE);}```2.定义Flash 读取数据函数:```cuint16_t FlashRead(uint32_t add){// 打开Flash控制时钟RCCHSICMD(ENABLE);// 设置Flash读取地址FLASH_ReadAddress = add;// 读取16位数据uint16_t data = FLASH_DataRead();// 关闭Flash控制时钟RCCHSICMD(DISABLE);return data;}```四、注意事项1.Flash 读写操作时,需注意地址和数据长度。

STM32:Flash擦除与读写操作(HAL库)

STM32:Flash擦除与读写操作(HAL库)

STM32:Flash擦除与读写操作(HAL库)应⽤平台:STM32F030F4P6ST官⽅库:STM32Cube_FW_F0_V1.9.0背景知识绝⼤多数的单⽚机和微控制器(ARM,x86),地址空间都是以字节为单位的,也就是说⼀个地址是⼀个字节。

Flash存储器有个特点,就是只能写0,不能写1。

所以如果原来的地址有数据了,意味着有⼀些位为0,这些位就相当于⽆效了。

所以必须写之前确保他们都为1,只有擦除才可以。

另外每次擦除都必须擦除⼀个4K⼤⼩的扇区,这是flash的特性所决定的。

对Flash操作前必需打开内部振荡器。

STM32F030F4P6的Flash存储简介STM32F030F4P6硬件配置: FLASH (16KB) RAM (4KB)(包含4个扇区,1个扇区包含4个页,每页有1Kbyte空间)⽤户可以对Flash进⾏program 和 erase 操作。

Main Flash memory programmingThe main Flash memory can be programmed 16 bits at a time.Flash memory eraseThe Flash memory can be erased page by page or completely (Mass Erase).Flash memory addresses Size(byte)Name Description0x0800 0000 - 0x0800 03FF 1 Kbyte Page 0Sector 00x0800 0400 - 0x0800 07FF 1 Kbyte Page 1Sector 00x0800 0800 - 0x0800 0BFF 1 Kbyte Page 2Sector 00x0800 0C00 - 0x0800 0FFF 1 Kbyte Page 3Sector 00x0800 1000 - 0x0800 13FF 1 Kbyte Page 4Sector 10x0800 1400 - 0x0800 17FF 1 Kbyte Page 5Sector 10x0800 1800 - 0x0800 1BFF 1 Kbyte Page 6Sector 10x0800 1C00 - 0x0800 1FFF 1 Kbyte Page 7Sector 10x0800 2000 - 0x0800 23FF 1 Kbyte Page 8Sector 20x0800 2400 - 0x0800 27FF 1 Kbyte Page 9Sector 20x0800 2800 - 0x0800 2BFF 1 Kbyte Page 10Sector 20x0800 2C00 - 0x0800 2FFF 1 Kbyte Page 11Sector 20x0800 3000 - 0x0800 33FF 1 Kbyte Page 12Sector 30x0800 3400 - 0x0800 37FF 1 Kbyte Page 13Sector 30x0800 3800 - 0x0800 3BFF 1 Kbyte Page 14Sector 3Flash memory addresses Size(byte)Name Description0x0800 3C00 - 0x0800 3FFF 1 Kbyte Page 15Sector 3 STM32F030F4P6的Flash读写参考代码(HAL库)/* Base address of the Flash sectors */#define ADDR_FLASH_PAGE_0 ((uint32_t)0x08000000) /* Base @ of Page 0, 1 Kbyte */#define ADDR_FLASH_PAGE_1 ((uint32_t)0x08000400) /* Base @ of Page 1, 1 Kbyte */#define ADDR_FLASH_PAGE_2 ((uint32_t)0x08000800) /* Base @ of Page 2, 1 Kbyte */#define ADDR_FLASH_PAGE_3 ((uint32_t)0x08000C00) /* Base @ of Page 3, 1 Kbyte */#define ADDR_FLASH_PAGE_4 ((uint32_t)0x08001000) /* Base @ of Page 4, 1 Kbyte */#define ADDR_FLASH_PAGE_5 ((uint32_t)0x08001400) /* Base @ of Page 5, 1 Kbyte */#define ADDR_FLASH_PAGE_6 ((uint32_t)0x08001800) /* Base @ of Page 6, 1 Kbyte */#define ADDR_FLASH_PAGE_7 ((uint32_t)0x08001C00) /* Base @ of Page 7, 1 Kbyte */#define ADDR_FLASH_PAGE_8 ((uint32_t)0x08002000) /* Base @ of Page 8, 1 Kbyte */#define ADDR_FLASH_PAGE_9 ((uint32_t)0x08002400) /* Base @ of Page 9, 1 Kbyte */#define ADDR_FLASH_PAGE_10 ((uint32_t)0x08002800) /* Base @ of Page 10, 1 Kbyte */#define ADDR_FLASH_PAGE_11 ((uint32_t)0x08002C00) /* Base @ of Page 11, 1 Kbyte */#define ADDR_FLASH_PAGE_12 ((uint32_t)0x08003000) /* Base @ of Page 12, 1 Kbyte */#define ADDR_FLASH_PAGE_13 ((uint32_t)0x08003400) /* Base @ of Page 13, 1 Kbyte */#define ADDR_FLASH_PAGE_14 ((uint32_t)0x08003800) /* Base @ of Page 14, 1 Kbyte */#define ADDR_FLASH_PAGE_15 ((uint32_t)0x08003C00) /* Base @ of Page 15, 1 Kbyte *//* Private define ------------------------------------------------------------*/#define FLASH_USER_START_ADDR ADDR_FLASH_PAGE_15 /* Start @ of user Flash area */#define FLASH_USER_END_ADDR ADDR_FLASH_PAGE_15 + FLASH_PAGE_SIZE /* End @ of user Flash area */#define DATA_32 ((uint32_t)0x12345678)/*Variable used for Erase procedure*/static FLASH_EraseInitTypeDef EraseInitStruct;uint32_t Address = 0;/*** @brief Main program* @param None* @retval None*/int main(void){/* STM32F0xx HAL library initialization:- Configure the Flash prefetch- Systick timer is configured by default as source of time base, but usercan eventually implement his proper time base source (a general purposetimer for example or other time source), keeping in mind that Time baseduration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined andhandled in milliseconds basis.- Low Level Initialization*/HAL_Init();/* Configure the system clock to48 MHz */SystemClock_Config();/* Unlock the Flash to enable the flash control register access *************/HAL_FLASH_Unlock();/* Erase the user Flash area(area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********//* Fill EraseInit structure*/EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;EraseInitStruct.PageAddress = FLASH_USER_START_ADDR;EraseInitStruct.NbPages = (FLASH_USER_END_ADDR - FLASH_USER_START_ADDR) / FLASH_PAGE_SIZE;EraseInitStruct.NbPages = (FLASH_USER_END_ADDR - FLASH_USER_START_ADDR) / FLASH_PAGE_SIZE;if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK){/*Error occurred while page erase.User can add here some code to deal with this error.PageError will contain the faulty page and then to know the code error on this page,user can call function 'HAL_FLASH_GetError()'*//* Infinite loop */while (1){/* User doing something here */}}/* Program the user Flash area word by word(area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/Address = FLASH_USER_START_ADDR;while (Address < FLASH_USER_END_ADDR){if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, DATA_32) == HAL_OK){Address = Address + 4;}else{/* Error occurred while writing data in Flash memory.User can add here some code to deal with this error */while (1){/* User doing something here */}}}/* Lock the Flash to disable the flash control register access (recommendedto protect the FLASH memory against possible unwanted operation) *********/HAL_FLASH_Lock();/* Check if the programmed data is OKMemoryProgramStatus = 0: data programmed correctlyMemoryProgramStatus != 0: number of words not programmed correctly ******/Address = FLASH_USER_START_ADDR;MemoryProgramStatus = 0x0;while (Address < FLASH_USER_END_ADDR){data32 = *(__IO uint32_t *)Address;if (data32 != DATA_32){MemoryProgramStatus++;}Address = Address + 4;}/*Check if there is an issue to program data*/if (MemoryProgramStatus == 0){/* User doing something here */}elseelse{while (1){/* User doing something here */ }}/* Infinite loop */while (1){}}。

STM32FLASH操作

STM32FLASH操作

STM32 flash操作对芯片内部flash进行操作的函数,包括读取,状态,擦除,写入等等,可以允许程序去操作flash上的数据。

一、存储器映射1、统一编址,程序存储器、数据存储器、外设寄存器组织在一个4GB的地址空间。

2、小端格式3、映像(stm32f107,256KB产品)可以看到,所谓的256KB闪存,是指主存储,片上FLASH如下图所示:介绍了片上的资源后,来看他们的地址映像。

芯片将4GB的空间,划分为8个512MB的块(block),这些块有些是整块不用的,芯片对地址的安排可以参考数据手册,memory mapping章节中的那个图。

只有block1、2、3、7是使用的。

地址中block7是核内的外设对应的地址,block2是其他外设对应的地址。

block1的低地址64KB是片上SRAM,block0则如下图option bytes即是选项字节;system memory就是系统存储,也即片上ROM;这两部分就是所谓信息块。

Flash就是指主存储,有256KB。

再往下看alias to flash or system memory.....这个区域256KB就是启动开始的区域。

这个区域并没有一个自己的存储器,只是根据BOOT0、BOOT1的接法来选择哪个存储器映射到这个地址上。

如下图选择用户闪存启动,是典型的做法;选择系统存储器,则在ST烧写进去的自举程序引导下,通过USART1下载程序;选择从SRAM执行代码则方便调试,比较快。

二、复位CM3将复位视作异常,优先级最高的异常。

stm32f1有三种复位:系统复位、电源复位、备份区复位。

前两种是真正的复位,对他的响应由硬件完成,这个响应对软件流的影响是这样的:程序指针指向0x0000 0004,这个单元存储的是复位服务子程序(或者汇编叫子过程),同时从0x0000 0000获取堆栈顶的地址。

不同的复位类型还有对其他寄存的不同复位方式,这就完成了复位。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

STM32 芯片内部的 FLASH 存储器,主要用于存储我们代码。

如果内部FLASH存储完我们的代码还有剩余的空间,那么这些剩余的空间我们就可以利用起来,存储一些需要掉电保存的数据。

本文以STM32103ZET6为例。

STM32103ZET6属于大容量产品,其闪存模块组织如下:其主存储器大小为512KB,分为256页,每页大小都为2KB。

我们的程序一般默认烧写到第0页的起始地址(0x08000000)处。

当BOOT0引脚和BOOT1引脚都接GND时,就是从这个地址开始运行代码的。

这个地址在keil中可以看到:假如我们要下载的程序大小为4.05KB,则第0、1、2页用于保存我们的程序,我们需要掉电保存的数据只能保存在第3~第255页这一部分空间内。

我们最终要下载的程序大小可在工程对应的.map文件中看到。

.map文件可以双击工程的Target的名字快速打开,如:下面对STM32内部FLASH进行简单的读写测试:内部FLASH读写测试流程图如下:本流程图省略异常情况,只考虑成功的情况:示例代码:本例的关键代码如下(以读写第255页为例):/******************************************************************** ************************************------------------------------------------STM32 Demo---------------------------------------------------** 工程说明:STM32内部FLASH实验* 作者:ZhengNian* 博客:zhengnianli.github.io* 公众号:嵌入式大杂烩********************************************************************** ***********************************/#define MAIN_CONFIG#include "config.h"/* STM32F103ZET6有256页,每一页的大小都为2KB */#define ADDR_FLASH_PAGE_255 ((uint32_t)0x0807F800) /* Page255 2KB *//* FLASH读写测试结果 */#define TEST_ERROR -1 /* 错误(擦除、写入错误) */#define TEST_SUCCESS 0 /* 成功 */#define TEST_FAILED 1 /* 失败 *//* Flash读写测试buf */#define BufferSize 6uint16_t usFlashWriteBuf[BufferSize] ={0x0101,0x0202,0x0303,0x0404,0x0505,0x0606};uint16_t usFlashReadBuf[BufferSize] = {0};/* 供本文件调用的函数声明 */static int FlashReadWriteTest(void);/******************************************************************** ************************************* 函数: main**------------------------------------------------------------------------------------------------------** 参数: void** 返回: 无** 说明: 主函数********************************************************************* ***********************************/int main(void){/* 上电初始化 */SysInit();/* 内部Flash读写测试 */if (TEST_SUCCESS == FlashReadWriteTest()){printf("Flash test success!\n");}else{printf("Flash test failed!\n");}while (1){}}/******************************************************************** ************************************* 函数: FlashReadWriteTest, 内部Flash读写测试函数**------------------------------------------------------------------------------------------------------** 参数: void** 返回: TEST_ERROR:错误(擦除、写入错误) TEST_SUCCESS:成功TEST_FAILED:失败** 说明: 无********************************************************************* ***********************************/static int FlashReadWriteTest(void){uint32_t ucStartAddr;/* 解锁 */FLASH_Unlock();/* 擦除操作 */ucStartAddr = ADDR_FLASH_PAGE_255;if (FLASH_COMPLETE != FLASH_ErasePage(ucStartAddr)){printf("Erase Error!\n");return TEST_ERROR;}else{ucStartAddr = ADDR_FLASH_PAGE_255;printf("擦除成功,此时FLASH中值为:\n");for (int i = 0; i < BufferSize; i++){usFlashReadBuf[i] = *(uint32_t*)ucStartAddr;printf("ucFlashReadBuf[%d] = 0x%.4x\n", i, usFlashReadBuf[i]);ucStartAddr += 2;}}/* 写入操作 */ucStartAddr = ADDR_FLASH_PAGE_255;printf("\n往FLASH中写入的数据为:\n");for (int i = 0; i < BufferSize; i++){if (FLASH_COMPLETE != FLASH_ProgramHalfWord(ucStartAddr, usFlashWriteBuf[i])){printf("Write Error!\n");return TEST_ERROR;}printf("ucFlashWriteBuf[%d] = 0x%.4x\n", i, usFlashWriteBuf[i]);ucStartAddr += 2;}/* 上锁 */FLASH_Lock();/* 读取操作 */ucStartAddr = ADDR_FLASH_PAGE_255;printf("\n从FLASH中读出的数据为:\n");for (int i = 0; i < BufferSize; i++){usFlashReadBuf[i] = *(__IO uint16_t*)ucStartAddr;printf("ucFlashReadBuf[%d] = 0x%.4x\n", i, usFlashReadBuf[i]);ucStartAddr += 2;}/* 读出的数据与写入的数据做比较 */for (int i = 0; i < BufferSize; i++){if (usFlashReadBuf[i] != usFlashWriteBuf[i]){return TEST_FAILED;}}return TEST_SUCCESS;}/******************************************************************** *************************************** End Of File********************************************************************* ***********************************/(1)进行解锁操作STM32 的闪存编程是由内嵌的闪存编程/擦除控制器(FPEC)管理,这个模块包含的寄存器如下:STM32 复位后, FPEC 模块是被保护的,不能写入 FLASH_CR 寄存器;通过写入特定的序列到 FLASH_KEYR 寄存器可以打开 FPEC 模块(即写入 KEY1和KEY2),只有在写保护被解除后,我们才能操作相关寄存器。

固件库中的函数为:/* 解锁 */void FLASH_Unlock(void);(2)擦除将要写的页STM32 的 FLASH 在编程的时候,也必须要求其写入地址的 FLASH 是被擦除了的(也就是其值必须是 0XFFFF),否则无法写入,在 FLASH_SR 寄存器的PGERR 位将得到一个警告。

STM32 的闪存擦除分为两种:页擦除和整片擦除。

也就是其最小擦除单位为1页,尽管你只需往某页里写10个字节数据或者更少的数据,你也必须先擦除该页(2*1024个字节)。

我们这里使用按页擦除,固件库中按页擦除的函数为:/* 按页擦除 */FLASH_Status FLASH_ErasePage(uint32_t Page_Address);其返回值为枚举:typedef enum{FLASH_BUSY = 1, /* 忙 */FLASH_ERROR_PG, /* 编程错误 */FLASH_ERROR_WRP, /* 写保护错误 */FLASH_COMPLETE, /* 操作完成 */FLASH_TIMEOUT /* 操作超时 */}FLASH_Status;(3)往上一步擦写成功的页写入数据STM32 闪存的编程每次必须写入16 位。

相关文档
最新文档