当前位置: 首页 > news >正文

SeanLib系列函数库-MyFlash


查看其它库函数说明,请点击此处跳转到SeanLib主页

1. 本篇内容

本篇提供了一个适用于STM32F429的片内Flash操作库,支持读(一般不使用)、扇区擦除、写(按字节形式)三个方法,相比于HAL库中的函数,本函数库操作更简单方便。
本库不依赖HAL库等其它库文件。
其它的单片机型号暂不支持,但F4系列可能都支持,如果有更新,会更新此篇文章。

2. 使用说明

本库包含 MyFlash.lib 和 MyFlash.h 两个文件,头文件内容如下:

#include"SeanLib.h"/******************************************************************************* *本库适用于 STM32F429 ,其它型号未经测试 扇区划分如下: | Secotor Size | BANK1 | ADDRESS | BANK2 | ADDRESS | | 16K | 0 | 0x08000000 | 12 | 0x08100000 | | 16K | 1 | 0x08004000 | 13 | 0x08104000 | | 16K | 2 | 0x08008000 | 14 | 0x08108000 | | 16K | 3 | 0x0800C000 | 15 | 0x0810C000 | | 64K | 4 | 0x08010000 | 16 | 0x08110000 | | 128K | 5 | 0x08020000 | 17 | 0x08120000 | | 128K | 6 | 0x08040000 | 18 | 0x08140000 | | 128K | 7 | 0x08060000 | 19 | 0x08160000 | | 128K | 8 | 0x08080000 | 20 | 0x08180000 | | 128K | 9 | 0x080A0000 | 21 | 0x081A0000 | | 128K | 10 | 0x080C0000 | 22 | 0x081C0000 | | 128K | 11 | 0x080E0000 | 23 | 0x081E0000 | *******************************************************************************/typedefstruct{/*************************************************************************** 功能:读字节函数(一般用不上读Flash的函数) ***************************************************************************/void(*Read)(unsignedintAddr,unsignedchar*Data,unsignedintLength);/*************************************************************************** 功能:擦除指定编号的扇区,如0、1、2...23 ***************************************************************************/Sean_Result_t(*Erase)(unsignedcharSector);/*************************************************************************** 功能:写入一组字节数据 参数: Addr:Flash地址,必须是4字节对齐地址 Data:要写入的数据指针 Length:要写入的数据长度,允许不是4的倍数 返回值:操作完成状态或错误代码 ***************************************************************************/Sean_Result_t(*Write)(unsignedintAddr,unsignedchar*Data,unsignedintLength);}MyFlash_t;//系统已经创建一个Flash对象,应用程序中不需要再定义,可以直接使用MyFlash,其中封装了一些支持的方法externMyFlash_t MyFlash;

使用Write方法写入可以确保写入成功,因为该方法在写入后会回读校验。

2.1 扇区擦除

Flash在写之前需要先擦除,因为Flash的存储单元仅允许由1写为0,若要由0改写为1,仅能通过擦除操作完成。而Flash的寿命与擦除次数有关,一般为10000次,因此项目中应谨慎擦除,采用合理的Flash存储策略,比如存储log,应先擦除1个扇区,之后开始逐条存储,在此扇区存满之前都不需要再擦除。
擦除是以扇区为单位的,单片机的扇区大小并不都是相同的,具体请看头文件开头部分的表格,列出了每个扇区的大小。

2.2 实例代码

以下是从SD卡读文件写入到Flash的代码:

//根据固件大小,计算需要擦除的扇区数量unsignedcharCalc_Erase_Count(unsignedintSize){constunsignedintSector_Size[16]={131072,// 0: 128KB262144,// 1: 256KB393216,// 2: 384KB524288,// 3: 512KB540672,// 4: 528KB557056,// 5: 544KB573440,// 6: 560KB589824,// 7: 576KB655360,// 8: 640KB786432,// 9: 768KB917504,// 10: 896KB1048576,// 11: 1MB1179648,// 12: 1.125MB1310720,// 13: 1.25MB1441792,// 14: 1.375MB1572864};// 15: 1.5MBunsignedcharcount;for(count=0;count<16;count++){if(Size<=Sector_Size[count]){returncount+1;}}return0;}//从指定的起始扇区号开始擦除指定数量的扇区Sean_Result_tFlash_Erase_Sectors(unsignedcharSector_Start,unsignedcharCount){unsignedchari;Sean_Result_t ret;for(i=0;i<Count;i++){ret=MyFlash.Erase(Sector_Start+i);if(ret!=Sean_PASS){returnSean_FAIL;}}returnSean_PASS;}unsignedcharbuf[1024]__attribute__((aligned(4)));//打开指定的固件文件,返回文件大小,若文件存在,则保持文件开启unsignedintOpen_File(constchar*Path){FRESULT ret;unsignedintFW_Size;ret=f_open(&File,Path,FA_OPEN_EXISTING|FA_READ);//打开文件if(ret==FR_OK)//打开成功时,返回文件大小{FW_Size=f_size(&File);//读取固件大小if(FW_Size==0)//若固件文件异常,则删除该文件{printf("Size of file is 0, delete file\r\n");f_close(&File);f_unlink(Path);return0;}returnFW_Size;}printf("Failed to open file %s:%s\r\n",Path,File_Err[ret]);return0;}//更新MCU的固件Sean_Result_tUpdate_MCU(constchar*FW_Path){FRESULT ret;unsignedintFW_Size;unsignedintRem_Count,Finish_Count;floatProcess;FW_Size=Open_File(FW_Path);//打开文件并读取固件大小if(FW_Size==0){returnSean_FAIL;}unsignedcharErase_Count;Erase_Count=Calc_Erase_Count(FW_Size);//计算要擦除的Flash扇区数量if(Flash_Erase_Sectors(8,Erase_Count)!=Sean_PASS)//从第8个扇区开始擦除需要擦除的所有扇区{printf("Failed to erase sector:%hhu\r\n",8+Erase_Count);f_close(&File);returnSean_FAIL;}unsignedintWrite_Addr=0x08080000;//固件起始地址unsignedintReadLen;unsignedshortPackage;Rem_Count=FW_Size;Finish_Count=0;while(Rem_Count>0)//读取固件写入Flash{Package=Rem_Count>1024?1024:Rem_Count;//每包大小1024字节ret=f_read(&File,buf,Package,&ReadLen);//从文件中读一包数据if(ret!=FR_OK||Package!=ReadLen)//读取失败,关闭文件{printf("Read file error: %s\r\n",File_Err[ret]);f_close(&File);returnSean_FAIL;}if(MyFlash.Write(Write_Addr,buf,Package)!=Sean_PASS){printf("Failed to write flash\r\n");f_close(&File);returnSean_FAIL;}Rem_Count-=Package;Finish_Count+=Package;Process=(float)Finish_Count;Process*=100.0f;Process/=(float)FW_Size;printf("Download process: %.1f%%\r\n",Process);if(Rem_Count==0)//更新完成,关闭文件{f_close(&File);returnSean_PASS;}Write_Addr+=Package;}returnSean_FAIL;}

这里演示了擦除、写入的完整过程,Calc_Erase_Count函数用于计算要擦除的扇区数量,因为擦除操作耗时较长,扇区越大耗时越长,所以要采用最少化擦除原则。

http://www.jsqmd.com/news/674497/

相关文章:

  • 30岁测试工程师的焦虑!
  • 扫频正弦啁啾信号在音频测量中的优势与应用
  • 因果AI:用户增长领域的“决策透视镜”
  • 异步编程中的高效数据过滤
  • Droplt进阶玩法:不止按后缀分类,教你用‘协议’实现更智能的文件自动化流程
  • Dify多模态工作流卡顿故障排查手册(附12个真实生产环境Debug日志片段)
  • C语言学习笔记6
  • 2026年比较好的帆布袋厂家对比推荐 - 品牌宣传支持者
  • X-World:小鹏面向规模化端到端自动驾驶的可控自车中心多相机世界模型
  • 如何选择Embedding模型
  • 魔兽争霸III优化终极指南:免费开源插件WarcraftHelper完全配置教程
  • Linux驱动-IMX6ULL开发板qemu环境搭建
  • 别再乱用Mybatis-Plus的@TableField了!5种FieldStrategy实战避坑指南(附Spring Boot配置)
  • 2026年口碑好的帆布袋定制/高质量帆布袋厂家精选合集 - 行业平台推荐
  • jQuery 遍历 - 后代
  • 把 ABAP 变体真正用活,动态保存、加载与删除的一套做法
  • 前端交互性能优化实例
  • 国产异步SRAM单片机外扩专用存储芯片
  • 鹿城靠谱的短视频公司
  • OpenGL学习资料
  • 保姆级教程:用SwitchyOmega+GFWList规则,5分钟搞定Chrome/Firefox代理自动切换
  • WooCommerce 多联盟站点动态追加 Affiliate ID 教程
  • TrueNAS Scale存储池与磁盘健康管理深度指南:SMART测试、休眠策略与温度警报设置
  • C#合并首尾相连多段线实战
  • 基于TMS320F28035的汇川变频器源码:MD290、MD380、MD500三种型号及新的...
  • jQuery 遍历 - 祖先
  • 博通(Broadcom)数据中心交换机芯片的介绍
  • 鸿蒙市场份额飙升但国产厂商仍观望,生态差距与商业考量成阻碍
  • 22.React.js 中所谓的 “Pure Component” 是怎样的一类组件?
  • Spring Cloud Eureka停更后,我们团队是如何平滑迁移到Nacos的(附完整配置对比)