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

【嵌入式】STM32内部NOR Flash磨损平衡与掉电保护总结

在这里插入图片描述

1. NOR Flash与NAND Flash

先deepseek看结论:

特性Nor FlashNAND Flash
读取速度快(支持随机访问,直接执行代码)较慢(需按页顺序读取)
写入/擦除速度慢(擦除需5秒,写入需逐字节操作)快(擦除4ms,按块操作)
存储密度低(1MB-1GB,适合小容量)高(8GB-1TB+,适合大容量)
擦写寿命约10万次约100万次
成本
坏块管理无需坏块管理,可靠性高需ECC纠错和坏块管理
代码执行直接运行代码需将代码加载到RAM运行
  • 本次只针对STM32内部Flash,即Nor Flash进行总结,不考虑坏块问题。
  • 本次设计结合实际项目,存储固定个数的文件进行说明,文件存储时包含文件索引+文件内容。

2. 掉电保护原理

2.1 Flash擦除过程掉电

参考链接nor flash之擦除与写入,擦除的步骤有三步:

  1. 先设置全0,此过程掉电,FLASH前面部分数据会变成0,后面部分数据不变;
  2. 擦除,此过程掉电,FLASH全部数据可能是错乱的数值;
  3. 维持全1,此过程掉电,FLASH中大部分数据读出是0xFF,某些部分读出的数据可能为其他数值;

通过设置magic num,且存放在扇区头部,可以解决前两种问题,但第三种无法解决,这种问题只能通过扫描是否全是0xFF来检查并重新擦除!

2.2 Flash写入过程掉电

掉电后,前面写入的数据为正常数据,后面未写入,仍未0xFF。
比如写一个结构体,可能会出现写一半的情况,可通过一个状态字段来进行识别,后面进行详细说明。

2.3 磨损平衡

考虑到FLASH的寿命,写入数据时是增量写入的,比如修改一个变量或者结构,会重新写入一个新的,同时将旧的标记为已删除,这个标记可以和状态字段整合到一起。
还需要考虑扇区写满后数据转移的问题,本次项目中采用主扇区和备份扇区交替写入的机制来控制磨损平衡,需添加扇区头结构,对扇区进行标识,要做到既可以在启动时选择到正确的扇区,又可以识别出破坏的扇区。

2.4 断电数据恢复

当写扇区头或者写文件时,如果掉电,那么本次的数据需在启动时识别出来,并可以恢复到增量写入时上个文件完整的数据。本次项目未考虑数据恢复的问题,只识别出了是否发生了损坏,损坏会全部擦除,上位机重新下发文件。

3. 扇区头部结构

考虑到自己项目中文件较小,且写入频次较低,项目设计并没采用类似easyFlash库那样对所有扇区进行平衡写入。为了加快搜索,项目中对文件索引单独存储一个扇区,同时结合另一个相同大小的扇区进行写满后换扇区写入。同样,文件数据也采用两个扇区进行交替写入。
不管哪个扇区,考虑到擦除中断电导致扇区被破坏,每个扇区的头部添加如下结构:

typedef struct tagSectorHeader{uint32_t u32Magic; //魔术字,0x12345678uint32_t u32SectorStatus; //扇区的状态 
}TSectorHeader;
//扇区的状态
#define SECTOR_STATUS_INIT 0xFFFFFFFF   //未使用
#define SECTOR_STATUS_USED 0x00FFFFFF   //已使用,写完数据后设置该装填
#define SECTOR_STATUS_ERASE 0x0000FFFF  //擦除中,先搬运数据,搬运完毕后擦除扇区,变为未使用

这里使用了Flash中的一个小技巧,对同一个地址,写4字节数据时,可以多次写入,但必须按照先写0x00FFFFFF再写0x0000FFFF这种方式进行写入,只要之前是FF位置的数据就可以写入。

判定扇区是否损坏:

uint32_t isBadSector(TSectorHeader *pHdr)
{// 魔术字无效且不是初始值 或 魔术字是初始值但扇区状态不是初始值if (pHdr->u32Magic != SECTOR_MAGIC_NUM && pHdr->u32Magic != 0xFFFFFFFF || pHdr->u32Magic == 0xFFFFFFFF && pHdr->u32SectorStatus != SECTOR_STATUS_INIT){return 1; // 扇区损坏}return 0;
}

第一次写扇区头:

int32_t writeNewSectorHdr(uint32_t u32SectorAddr)
{// 标记新扇区 - 使用状态if (writeSectorStatus(u32SectorAddr + offsetof(TSectorHeader, u32SectorStatus), SECTOR_STATUS_USED) != 0){return -1;}// 标记新扇区 - 魔术字uint32_t u32Magic = SECTOR_MAGIC_NUM;if (AflFlashWriteWords(u32SectorAddr + offsetof(TSectorHeader, u32Magic), &u32Magic, 1) != 0){return -1;}return 0;
}

更改扇区状态:

int32_t writeSectorStatus(uint32_t u32StatusStartAddr, SECTOR_STATUS_DEFINE statusNow)
{int32_t iRet = 0;FILEINDEX_STATUS_DEFINE statusLast; // 注意状态写入必须按状态定义的顺序进行写入!AflFlashReadWords(u32StatusStartAddr, &statusLast, 1);if (statusNow == SECTOR_STATUS_USED){if (statusLast != SECTOR_STATUS_INIT){ASSERT(1, "last sector status err!");  return -1;}}else if (statusNow == SECTOR_STATUS_ERASE){if (statusLast != SECTOR_STATUS_USED){ASSERT(1, "last sector status err!");return -1;}}else{}iRet = AflFlashWriteWords(u32StatusStartAddr, &statusNow, 1);return iRet;
}

4. 文件索引结构

//文件索引的操作状态
#define FILEINDEX_STATUS_INIT 0xFFFFFFFF         //未使用
#define FILEINDEX_STATUS_PRE_WRITE 0x00FFFFFF    //准备写入
#define FILEINDEX_STATUS_FIN_WRITE 0x0000FFFF    //已写入 写入索引结构数据即更新,文件数据靠CRC校验
#define FILEINDEX_STATUS_FIN_DEL 0x000000FF      //已删除
//#define FILEINDEX_STATUS_PRE_DEL 0x000000FF    //准备删除 该操作可以用来恢复上次的数据,本次设计无需恢复数据
//文件索引信息
typedef struct tagFileIndex
{uint32_t u32DataStatus;      // 操作状态uint32_t u32IndexAddr;       // 该索引在扇区中的起始地址uint32_t u32DataAddr;        // 该文件在Flash中的起始地址uint32_t u32DataLen;         // 数据块的长度uint16_t u16FileCRC;         // 数据校验值uint16_t u16AlignReserved;   // 对齐保留// 其他数据
}TFileIndex;

写索引时,先写状态为准备写入,然后写结构体字段,写完后再修改状态为写入完成。
比如写一个文件,会先写索引结构,再写文件内容,索引结构中添加状态字段来进行控制,文件内容没写完掉电,可通过检查索引结构中的文件长度、CRC来对文件内容进行校验。

写索引数据:

// 写索引数据,状态无需传入,内部控制
int32_t writeFileIndexToFlash(uint32_t u32CopyToAddr, TFileIndex *ptfileIndex)
{int32_t iRet = 0;do{// 先写状态为【准备写入】iRet = writeFileIndexStatus(u32CopyToAddr + offsetof(TFileIndex, u32DataStatus), FILEINDEX_STATUS_PRE_WRITE);if (iRet != 0)break;//写索引地址iRet = AflFlashWriteWords(u32CopyToAddr + offsetof(TFileIndex, u32IndexAddr), &u32CopyToAddr, 1);if (iRet != 0)break;// 写剩余的其他所有数据iRet = AflFlashWriteWords(u32CopyToAddr + offsetof(TFileIndex, u32DataAddr), (uint32_t *)&ptfileIndex->u32DataAddr, (sizeof(TFileIndex) - offsetof(TFileIndex, u32DataAddr))/4);if (iRet != 0)break;// 最后,写状态为【已写入】iRet = writeFileIndexStatus(u32CopyToAddr + offsetof(TFileIndex, u32DataStatus), FILEINDEX_STATUS_FIN_WRITE);if (iRet != 0)break;ptfileIndex->u32DataStatus = FILEINDEX_STATUS_FIN_WRITE;ptfileIndex->u32IndexAddr = u32CopyToAddr;} while (0);if (iRet != 0){DEBUG(DEBUG_ERROR, ("writeFileIndexToFlash Error!!"));}return iRet;
}

写文件数据(略),过程就是先写索引,再写数据,最后检查写入的文件CRC是否正确。

5. 总结

以上是状态控制的核心代码,其他和写文件数据内容相关、扇区切换相关略去了,以后有机会可以写个通用的、小型的模块。
数据恢复的思路如下,本次检查到非法数据,直接擦了:

当写入新的结构时(注意这个结构必须具备唯一标识符),需将旧的结构标记为准备删除,然后写新的结构,当新结构数据写完后,会将旧的结构数据再标记为已删除。这样初始化时扫描所有数据,如果同一个标识符的结构,一个状态为准备删除,一个为准备写入,此时认为数据未拷贝完,可以将准备写入改为已删除,废掉这个数据,重新拷贝一个新的,此时即使再次掉电也没问题。如果同一个标识符的结构,一个状态为准备删除,一个为写入完成,此时认为数据已经拷贝完,将准备删除改为已删除即可。

6. 调试中问题

  • 使用ST-Link单步调试读写flash代码,可能会出现写失败,甚至数据被篡改,改为J-Link解决该问题。

相关文章:

【嵌入式】STM32内部NOR Flash磨损平衡与掉电保护总结

1. NOR Flash与NAND Flash 先deepseek看结论: 特性Nor FlashNAND Flash读取速度快(支持随机访问,直接执行代码)较慢(需按页顺序读取)写入/擦除速度慢(擦除需5秒,写入需逐字节操作&…...

什么是磁盘阵列(RAID)?如何提高磁盘阵列的性能

什么是磁盘阵列 ‌磁盘阵列(RAID)是一种将多个独立的硬盘组合成一个逻辑存储单元的技术,旨在提高数据存储的性能、容量、可靠性和冗余性‌。‌磁盘阵列通过将数据分割成多个区段并分别存储在不同的硬盘上,利用个别磁盘提供数据加…...

轻量级日志管理平台Grafana Loki

文章目录 轻量级日志管理平台Grafana Loki背景什么是Loki为什么使用 Grafana Loki?架构Log Storage Grafana部署使用基于 Docker Compose 安装 LokiMinIO K8s集群部署Loki采集Helm 部署方式和案例 参考 轻量级日志管理平台Grafana Loki 背景 在微服务以及云原生时…...

k8s集群部署

集群结构 角色IPmaster192.168.35.135node1192.168.35.136node2192.168.35.137 部署 #需在三台主机上操作 //关闭防火墙 [rootmaster ~]# systemctl disable --now firewalld//关闭selinux [rootmaster ~]# sed -i s/enforcing/disabled/ /etc/selinux/config//关闭swap分区…...

STM32MP157A-FSMP1A单片机移植Linux系统SPI总线驱动

SPI总线驱动整体上与I2C总线驱动类型,差别主要在设备树和数据传输上,由于SPI是由4根线实现主从机的通信,在设备树上配置时需要对SPI进行设置。 原理图可知,数码管使用的SPI4对应了单片机上的PE11-->SPI4-NSS,PE12-->SPI4-S…...

系统基础与管理(2025更新中)

‌一、Linux 核心架构与组件‌ ‌内核架构‌ ‌核心职责‌: 管理进程生命周期、内存分配、硬件驱动交互及文件系统操作。 模块化设计支持动态加载硬件驱动(如modprobe加载内核模块),提升灵活性和扩展性。 ‌内存管理‌&#xff1a…...

Python--内置函数与推导式(下)

3. 内置函数 数学运算类 函数说明示例​abs​绝对值​abs(-10) → 10​​pow​幂运算​pow(2, 3) → 8​​sum​求和​sum([1,2,3]) → 6​​divmod​返回商和余数​divmod(10, 3) → (3, 1)​ 数据转换类 # 进制转换 print(bin(10)) # 0b1010 print(hex(255)) # 0x…...

可狱可囚的爬虫系列课程 14:10 秒钟编写一个 requests 爬虫

一、前言 当重复性的工作频繁发生时,各种奇奇怪怪提高效率的想法就开始萌芽了。当重复代码的模块化封装已经不能满足要求的时候,更高效的方式就被揭开了神秘的面纱。本文基于这样的想法,来和大家探讨如何 10 秒钟编写一个 requests 爬虫程序。…...

Windows golang安装和环境配置

【1】、golang 1.19 sdk下载 https://download.csdn.net/download/notfindjob/90422529 【2】、安装 【3】、配置 GOPATH目录 【4】、LiteIDE下载安装 https://download.csdn.net/download/notfindjob/90422580 【5】、打开LiteIDE,选择查看->管理GOPATH&…...

IP-------GRE和MGRE

4.GRE和MGRE 1.应用场景 现实场景 居家工作,公司工作,分公司工作----------需要传输交换数据--------NAT---在该场景中需要两次NAT(不安全) 为了安全有两种手段-----1.物理专线---成本高 2.VPN--虚拟专用网---隧道技术--封装技…...

LabVIEW形状误差测量系统

在机械制造领域,形状与位置公差(GD&T)直接影响装配精度与产品寿命。国内中小型机加工企业因形状误差导致的返工率高达12%-18%。传统测量方式存在以下三大痛点: ​ 设备局限:机械式千分表需人工读数,精度…...

django校园互助平台~源码

博主介绍:✌程序猿徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...

Vue进阶之AI智能助手项目(五)——ChatGPT的调用和开发

AI智能助手项目 前端页面Layout布局页面-viewssrc/views/chat/layout/Permission.vuesrc/views/chat/layout/sider/index.vuesrc/views/chat/layout/sider/List.vuesrc/views/chat/layout/sider/Footer.vueComponents 组件Header/index.vueMessage/index.vue前端页面 Layout布…...

Jenkins重启后Maven的Project加载失败

个人博客地址:Jenkins重启后Maven的Project加载失败 | 一张假钞的真实世界 Jenkins重启后发现Maven的项目都没有正常加载。检查Jenkins的启动日志发现以下错误信息: java.io.IOException: Unable to read /home/jenkins/.jenkins/jobs/test-maven/conf…...

【docker】docker pull拉取中不断重复下载问题,解决方案之一,磁盘空间扩容

问题类似这样 存储空间不足 如果 Docker 运行环境的磁盘空间不足,拉取的镜像可能会被自动清理,导致重复下载。可以检查磁盘使用情况: df -h docker system df如果空间不足,可以清理一些不用的容器和镜像: docker sy…...

Ubuntu指令(一)

一、终端操作指令 打开终端,有两种便捷方式: 直接点击系统中的终端按钮;使用快捷键ctrl alt T。 关闭终端,同样有多种选择: 在终端输入exit指令;使用快捷键ctrl d;直接点击终端窗口的关闭…...

nnUNet V2修改网络——加入MultiResBlock模块

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 MultiRes Block 是 MultiResUNet 中核心组件之一,旨在解决传统 U-Net 在处理多尺度医学图像时的局…...

Spring Boot + Vue 接入腾讯云人脸识别API(SDK版本3.1.830)

一、需求分析 这次是基于一个Spring Boot Vue的在线考试系统进行二次开发,添加人脸识别功能以防止学生替考。其他有对应场景的也可按需接入API,方法大同小异。 主要有以下两个步骤: 人脸录入:将某个角色(如学生&…...

【SpringSecurity】springboot整合SpringSecurity实现登录校验与权限认证

【SpringSecurity】springboot整合SpringSecurity实现登录校验与权限认证 【一】SpringSecurity框架简介【二】SpringSecurity与shiro【1】SpringSecurity特点【2】shiro特点【3】SpringSecurity和shiro总结 【三】SpringSecurity过滤器【1】SpringSecurity中常见的过滤器【2】…...

【HarmonyOS Next】鸿蒙应用公钥和证书MD5指纹的获取

【HarmonyOS Next】鸿蒙应用公钥和证书MD5指纹的获取 一、问题背景 政府的icp备案时,或者某些三方SDK以来的管理后台,都需要配置鸿蒙应用的公钥和证书MD5指纹 二、解决方案 专有名词解释: 华为AppGallery Connect简称 AGC平台&#xff0…...

40_终极落地Checklist:你的公司Agent是否真的会干活了

核心价值:可打印、可传播的检查表 更新频率:季度/半年重磅很多团队的 Agent 能跑起来、能演示、能交付,但真正到生产环境里能不能稳定地"干活",是两回事。这篇文章提供一个结构化的评估框架,帮你从五个维度判…...

玻璃拟态设计指南:如何用CSS3打造现代UI效果(附完整代码)

玻璃拟态设计指南:如何用CSS3打造现代UI效果(附完整代码) 当苹果在macOS Big Sur中大面积采用半透明磨砂玻璃效果时,整个设计界都为这种被称为"玻璃拟态"(Glassmorphism)的风格所惊艳。这种设计语…...

宝塔面板+CentOS 7.X:新手小白的第一个前端网站部署全流程(含安全组配置避坑)

宝塔面板CentOS 7.X:零基础前端部署实战指南 第一次将前端项目部署到线上服务器,对很多转行前端或在校学生来说既兴奋又忐忑。兴奋的是终于能让自己的作品被更多人看到,忐忑的是面对陌生的服务器环境和复杂的配置流程。本文将带你用最直观的方…...

解锁专业音效:ViPER4Windows在Windows 10/11的完美运行方案

解锁专业音效:ViPER4Windows在Windows 10/11的完美运行方案 【免费下载链接】ViPER4Windows-Patcher Patches for fix ViPER4Windows issues on Windows-10/11. 项目地址: https://gitcode.com/gh_mirrors/vi/ViPER4Windows-Patcher 厌倦了ViPER4Windows在最…...

轻流无代码如何重构质量管理体系?这 3 个价值必须了解

轻流无代码如何重构质量管理体系?这 3 个价值必须了解如果用一句话概括轻流 AI 无代码平台在质量管理场景的价值,那就是:让业务人员自主搭建管理系统,无需编写代码,1-2 周即可上线核心功能,总体拥有成本降低…...

别再烧芯片了!手把手教你搞懂STM32 GPIO的过压保护二极管(附实测数据)

STM32 GPIO保护二极管实战指南:从原理到实测的完整避坑手册 刚拿到STM32开发板的新手们,总会遇到这样的灵魂拷问:为什么我的芯片又冒烟了?上周实验室里,小王同学用5V的超声波模块直接接到STM32的GPIO上,结果…...

手把手教你用MFRC522射频模块实现门禁系统(附完整代码)

手把手教你用MFRC522射频模块实现门禁系统(附完整代码) 在智能家居和安防领域,射频识别(RFID)技术因其非接触式交互特性而广受欢迎。MFRC522作为一款高性价比的13.56MHz射频模块,配合Arduino或STM32等开发板…...

3个策略如何让Path of Building中文版成为你的流放之路“第二大脑“?

3个策略如何让Path of Building中文版成为你的流放之路"第二大脑"? 【免费下载链接】PoeCharm Path of Building Chinese version 项目地址: https://gitcode.com/gh_mirrors/po/PoeCharm 你是否曾在《流放之路》那浩瀚的天赋树前感到迷茫&#xf…...

企业安全架构革新:零信任架构(Zero Trust)核心概念与企业落地实施方法(超详细图解)

企业安全架构革新:零信任架构(Zero Trust)核心概念与企业落地实施方法(超详细图解)前言一、零信任架构(Zero Trust):基本概念1.1 官方定义1.2 通俗理解1.3 零信任三大核心原则二、零…...

【2026奇点大会独家解码】:AIAgent对话管理的5大认知拐点与企业落地避坑指南

第一章:【2026奇点大会独家解码】:AIAgent对话管理的5大认知拐点与企业落地避坑指南 2026奇点智能技术大会(https://ml-summit.org) 在2026奇点大会上,来自DeepMind、阿里通义实验室与MIT CSAIL的联合白皮书首次系统揭示:当前83…...