STM32 连续操作flash

STM32 连续操作flash大容量每个扇区 2048 个字节本文需要注意的问题是就是防止栈溢出 1 定义局部变量需要修改启动文件栈的大小设置默认是 0x400 1024 个字节 2 定义一个全局变量 ifndef STMFLASH H defi

大家好,欢迎来到IT知识分享网。

STM32 连续操作flash

编程和擦除闪存
  • 闪存编程一次可以写入16(半字)
  • 闪存擦除操作可以按页面擦除或完全擦除(全擦除)。全擦除不影响信息块。
  • 为了确保不发生过度编程, 闪存编程和擦除控制器块是由一个固定的时钟控制的。
  • 写操作(编程或擦除)结束时可以触发中断。仅当闪存控制器接口时钟开启时,此中断可以用来从
  • WFI模式退出。
主存储块容量:

小容量产品主存储块最大为4K×64位,每个存储块划分为321K字节的页(见表2)

中容量产品主存储块最大为16K×64位,每个存储块划分为1281K字节的页(见表3)。

大容量产品主存储块最大为64K×64位,每个存储块划分为2562K字节的页(见表4)。

互联型产品主存储块最大为32K×64位,每个存储块划分为1282K字节的页(见表5)。

信息块容量:
互联型产品有
2360
×
64

(
见表
5)
其它产品有
258
×
64

(
见表
2
30/754、表
3
、表
4)
闪存存储器接口的特性为:

● 带预取缓冲器的读接口(每字为2×64)

● 选择字节加载器

● 闪存编程/擦除操作

● 访问/写保护

STM32 连续操作flash

STM32 连续操作flash

 STM32 连续操作flash

大容量每个扇区2048个字节 

本文需要注意的问题是就是防止栈溢出

{

1、定义局部变量需要修改启动文件栈的大小(默认设置是0x400=1024个字节)

2、定义一个全局变量

}

#ifndef __STMFLASH_H__ #define __STMFLASH_H__ #include "stm32f1xx_hal.h" enum Flash{ STM32_FLASH_BASE =0x, //flash基地址 STM32_FLASH_SIZE_K =512, // flash 大小KB STM32_FLASH_PAGE_SIZE =2048, // 删去大小Byte PAGE_INT_SIZE = 2048/4, PAGE_SHORT_SIZE = 2048/2 }; uint32_t Read_4Byte_flash(uint32_t addr ); uint8_t Write_4Byte_flash(uint32_t addr ,uint32_t data); uint8_t Write_N_4Byte_flash(uint32_t addr ,uint32_t *data,uint32_t len); uint8_t __NeetErease(uint32_t start_addr ,uint32_t len); #endif /* __STMFLASH_H__ */ 

#include "flash.h" #include "string.h" #include "stdlib.h" uint32_t Read_4Byte_flash(uint32_t addr ) { uint32_t data; if(addr >STM32_FLASH_BASE) data= *(uint32_t*)addr; else data=0; return data; } uint8_t Write_4Byte_flash(uint32_t addr ,uint32_t data) { uint16_t page=0; uint32_t _offset=0; FLASH_EraseInitTypeDef hflash; uint32_t error=0; uint32_t flash_data[STM32_FLASH_PAGE_SIZE/4]; uint16_t i=0; page=((uint32_t)addr-STM32_FLASH_BASE)/STM32_FLASH_PAGE_SIZE; _offset = (((uint32_t)addr-STM32_FLASH_BASE)%STM32_FLASH_PAGE_SIZE)/4; if(Read_4Byte_flash(addr)!=0xffffffff)//需要先擦出再写入 { //擦除 //读取flash数据到缓冲 for(;i<STM32_FLASH_PAGE_SIZE/4;i++) { flash_data[i]=Read_4Byte_flash(STM32_FLASH_BASE+page*STM32_FLASH_PAGE_SIZE+i*4); } //擦除页 hflash.TypeErase=FLASH_TYPEERASE_PAGES; //擦除类型 hflash.Banks = FLASH_BANK_1; hflash.PageAddress = STM32_FLASH_BASE+page*STM32_FLASH_PAGE_SIZE;//页基地址 hflash.NbPages = 1;//需要擦除的页数 HAL_FLASH_Unlock(); if(HAL_FLASHEx_Erase(&hflash,&error)==HAL_OK) { flash_data[_offset] = data; } for(i=0;i<STM32_FLASH_PAGE_SIZE/4;i++) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,STM32_FLASH_BASE+page*STM32_FLASH_PAGE_SIZE+i*4,flash_data[i]); } HAL_FLASH_Lock(); } else //直接可以编程写入数据 { HAL_FLASH_Unlock(); HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,addr,data); HAL_FLASH_Lock(); } return Read_4Byte_flash(addr)==data?1:0; } uint8_t __NeetErease(uint32_t start_addr ,uint32_t len) { //该函数len必须是4的倍数 即 len%4==0 volatile uint32_t i=0; for(;i<len;i++) { if(Read_4Byte_flash(start_addr)!=0xffffffff) { break; } start_addr+=4; } return i==len ? 0:1; } uint8_t _Erease_Flash(uint32_t base_addr) { uint8_t flag=0; FLASH_EraseInitTypeDef hflash; //擦除页 hflash.TypeErase=FLASH_TYPEERASE_PAGES; //擦除类型 hflash.Banks = FLASH_BANK_1; hflash.PageAddress = base_addr;//页基地址 hflash.NbPages = 1;//需要擦除的页数 uint32_t error=0; if(HAL_FLASHEx_Erase(&hflash,&error)==HAL_OK) { flag=1; } return flag; } static uint32_t flash_data[STM32_FLASH_PAGE_SIZE/4] ;// __attribute__ ((at(0X))); uint8_t Write_One_Page_Data(uint32_t base_addr,uint32_t page_offst,uint32_t *data,volatile uint32_t erease_size) { volatile uint8_t flag=0; uint16_t i=0; volatile uint32_t cur_addr=0; // uint32_t tempdata=0; //uint32_t flash_data[STM32_FLASH_PAGE_SIZE/4]; // uint32_t *flash_data =(uint32_t*)malloc(erease_size); // if(flash_data==0) // { // flag=0; // } HAL_FLASH_Unlock(); if(__NeetErease(base_addr,erease_size)) { memset((void*)flash_data,0,STM32_FLASH_PAGE_SIZE); for(i=0;i<page_offst ;i++) { cur_addr = base_addr + i*4; flash_data[i]=Read_4Byte_flash(cur_addr); } _Erease_Flash(base_addr); //写入数据 for(i=page_offst;i<(erease_size+page_offst);i++) { flash_data[i]=*data; data++; } for(i=0;i<erease_size+page_offst;i++) { cur_addr = base_addr+i*4; if(cur_addr%4==0&& cur_addr >STM32_FLASH_BASE) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,cur_addr,flash_data[i]); } } } else //不需要擦除就从偏移开始 { for(i=page_offst;i<erease_size+page_offst;i++) { cur_addr = base_addr+i*4; if(cur_addr%4==0&& cur_addr >STM32_FLASH_BASE) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,cur_addr,*data); data++; } } } HAL_FLASH_Lock(); return flag; } /* 本函数操作的整型数据 4个字节;flash是以一个字节为一个地址的 addr 起始地址 data 数据开始地址 surplus 整型数据长度1len=4Byte ;最大为 STM32_FLASH_PAGE_SIZE/4; */ uint8_t Write_N_4Byte_flash(uint32_t addr ,uint32_t *data,uint32_t len) { volatile uint32_t start_page=0; //起始页 volatile uint32_t page_size=0; //需要操作页的大小 volatile uint32_t _offset=0; //页操作页码的起始地址 volatile uint32_t page_offset=0; //页偏移 volatile uint32_t erease_size=0; //本次操作页可以使用的剩余大小 volatile uint32_t base_addr=0; //本次操作页的基地址 volatile uint32_t surplus=0; start_page=((uint32_t)addr-STM32_FLASH_BASE)/STM32_FLASH_PAGE_SIZE; _offset = (((uint32_t)addr-STM32_FLASH_BASE)%STM32_FLASH_PAGE_SIZE)/4; if(PAGE_INT_SIZE-_offset>=len) { page_size=1; surplus=0; } else { page_size=1; surplus = len-(PAGE_INT_SIZE-_offset); page_size +=surplus/PAGE_INT_SIZE + surplus%PAGE_INT_SIZE>0?1:0; } surplus=len; for(page_offset=0;page_offset<page_size;page_offset++) { if(page_offset==0) { erease_size =(PAGE_INT_SIZE-_offset)<surplus ? (PAGE_INT_SIZE-_offset):surplus; base_addr = STM32_FLASH_BASE + start_page*STM32_FLASH_PAGE_SIZE; surplus = len-erease_size; } else { _offset=0; erease_size =surplus>PAGE_INT_SIZE ? PAGE_INT_SIZE:surplus; base_addr = STM32_FLASH_BASE + (start_page+page_offset)*STM32_FLASH_PAGE_SIZE; surplus = surplus-erease_size; } Write_One_Page_Data(base_addr,_offset,data,erease_size); data+=erease_size; //_offset=0; } return 1; } 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/144980.html

(0)
上一篇 2025-04-22 21:20
下一篇 2025-04-22 21:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信