1. 为什么需要Flash模拟EEPROM
在单片机开发中,数据存储是一个绕不开的话题。很多项目都需要保存一些配置参数,比如设备的运行模式、用户的设置选项、或者系统运行时的状态信息。这些数据需要在断电后依然保持,下次上电时还能读取出来。这时候,很多人首先想到的就是EEPROM。
EEPROM确实是个好东西,它可以按字节读写,不需要整个擦除就能修改数据,而且擦写寿命通常能达到10万次以上。但问题来了:不是所有单片机都内置EEPROM!比如STM32F1系列、STM32F4系列这些常用型号,根本就没有内置EEPROM。即使有内置EEPROM的型号,比如STM32L0系列,其擦写次数也就10万次左右,对于一些需要频繁保存数据的应用场景来说,这个次数可能不够用。
这时候,Flash模拟EEPROM的技术就派上用场了。几乎所有单片机都有Flash存储器,用来存储程序代码,我们完全可以利用这部分Flash来模拟EEPROM的功能。但是Flash有个先天不足:它的擦写寿命通常只有1万次左右,比EEPROM少了一个数量级。
我最近在一个项目中就遇到了这个问题。需要保存16字节的配置数据,每次改变其中一个字节就要保存一次,客户要求达到100万次的存储寿命。用真正的EEPROM肯定没问题,但为了降低成本,我决定用Flash来模拟EEPROM,并通过算法优化实现百万次的存储目标。
2. Flash存储的基本原理与挑战
2.1 Flash与EEPROM的根本区别
要理解为什么Flash的擦写次数有限,我们得先了解Flash的物理结构。Flash存储器是由大量的浮栅MOS管组成的,每个MOS管可以存储一个比特的数据。写入数据时,需要通过高压将电子注入浮栅;擦除数据时,又需要施加反向高压将电子拉出来。
这个注入和拉出的过程会对浮栅造成物理损伤,就像反复弯曲一根铁丝最终会断裂一样。EEPROM之所以寿命更长,是因为它的存储单元结构和操作电压与Flash有所不同,能够承受更多次的擦写操作。
Flash还有一个特点:它必须按页擦除,按字编程。以STM32G071为例,它的Flash每页大小是2KB,要修改一个字节,必须先擦除整个页,然后再写入新数据。这就带来了一个严重的问题:如果我们每次只修改16字节的数据,却要擦除整个2KB的页,实在是太浪费了!
2.2 磨损均衡的重要性
既然Flash的擦写次数有限,我们就需要想办法让整个Flash页的磨损尽量均匀。这就好比一条马路,如果所有车辆都走同一个车道,这个车道很快就会损坏;如果让车辆均匀分布在所有车道上,整条路的寿命就会长很多。
磨损均衡算法就是解决这个问题的关键。通过让写操作均匀分布在整个Flash页上,我们可以将实际擦除次数分摊到所有存储单元上,从而大幅提高整体寿命。
在我的项目中,Flash页大小是2KB,每次存储16字节数据。如果不做任何优化,直接反复擦写同一个区域,最多只能达到1万次的寿命,远远达不到100万次的要求。但通过轮询存储算法,我可以让写操作分布在整个页上,理论寿命可以达到128万次!
3. 轮询存储算法的核心思想
3.1 算法基本原理
轮询存储算法的核心思想很简单:不要总是在同一个地方写数据,而是轮流在不同的位置写入。就像吃饭时不要总用同一个碗,而是轮流使用多个碗,这样每个碗的磨损就会均匀很多。
具体来说,我将在Flash页中划分出多个存储槽,每个槽大小正好是16字节。第一次写入时,使用第一个槽;第二次写入时,使用第二个槽;依此类推,直到写满整个页。当页写满后,再擦除整个页,从头开始循环。
STM32G071的Flash页大小是2KB,每个存储槽16字节,那么一页可以划分出128个存储槽(2048 ÷ 16 = 128)。每个槽写一次,写满一页需要128次写入,然后擦除一次。由于Flash的擦写寿命是1万次,所以理论总寿命是128 × 10000 = 128万次,完全满足100万次的要求。
3.2 地址索引管理
实现轮询存储算法的关键是管理好写地址索引。这个索引告诉我们下一次应该在
352



被折叠的 条评论
为什么被折叠?



