如何在断电时防止“部分写入”数据损坏?

时间:2014-01-10 18:23:32

标签: memory embedded msp430 non-volatile

在嵌入式环境中(使用MSP430),我看到了部分写入非易失性存储器导致的数据损坏。这似乎是由写入期间的功率损耗(对FRAM或信息段)造成的。

我正在使用CRC验证存储在这些位置的数据。

我的问题是,防止这种“部分写入”腐败的正确方法是什么?目前,我已修改我的代码以写入两个单独的FRAM位置。因此,如果一个写入被中断导致CRC无效,则另一个位置应保持有效。这是一种常见做法吗?我是否需要为任何非易失性存储器实现这种双写行为?

4 个答案:

答案 0 :(得分:7)

一个简单的解决方案是维护两个版本的数据(在闪存的单独页面中),当前版本和以前的版本。每个版本都有一个包含序列号的标题和一个验证序列号的单词 - 只是序列号的1的补码,例如:

---------
|  seq  |
---------
| ~seq  |
---------
|       |
| data  |
|       |
---------

关键是在写入数据时,seq~seq字会写成 last

在启动时,您读取具有最高有效序列编号的数据(可能会考虑环绕 - 特别是对于短序列字)。编写数据时,会覆盖并验证最旧的块。

只要最后写入CRC,您已经使用的解决方案就是有效的,但它缺乏简单性并且会产生可能不必要或不可取的CRC计算开销。

在FRAM上你不关心耐力,但这是闪存和EEPROM的问题。在这种情况下我使用了回写高速缓存方法,其中该数据被保持在RAM中,并且改性当定时器启动或重新启动,如果它已经在运行 - 当定时器期满时,数据被写入 - 这可以防止突发写入从打破内存开始,甚至在FRAM上也很有用,因为它可以最大限度地减少数据写入的软件开销。

答案 1 :(得分:5)

我们的工程团队对这些问题采取双管齐下的方法:在硬件和软件中解决它!

第一种是二极管和电容器布置,在欠压期间提供几毫秒的功率。如果我们发现我们已经失去了外部电源,我们会阻止代码输入任何非违规写入。

其次,我们的数据对于操作特别重要,它经常更新,我们不想磨损我们的非违规闪存(它只支持如此多的写入。)所以我们实际上将数据存储在闪存中16次并使用CRC代码保护每条记录。在启动时,我们找到最新的有效写入,然后开始我们的擦除/写入循环。

自从实施我们坦诚的偏执系统以来,我们从未见过数据损坏。

<强>更新

我应该注意,我们的闪存在CPU外部,因此如果CPU和闪存芯片之间存在通信故障,CRC有助于验证数据。此外,如果我们连续遇到几个毛刺,多次写入可防止数据丢失。

答案 2 :(得分:4)

我们使用了与Clifford的答案类似的东西,但写在一个写操作中。您需要两份数据副本并在它们之间交替。使用递增序列号,以便有效地一个位置具有偶数序列号而一个具有奇数。

写这样的数据(如果可以的话,在一个写命令中):

---------
|  seq  |
---------
|       |
| data  |
|       |
---------
| seq   |
---------

当你回读它时,确保两个序列号都相同 - 如果它们不相同则数据无效。在启动时读取两个位置并确定哪个位置更新(考虑到滚动的序列号)。

答案 3 :(得分:0)

始终将数据存储在某种协议中,例如START_BYTE,要写入的总字节数,数据,END BYTE。 在写入外部/内部存储器之前,请务必检查POWER Moniter寄存器/ ADC。 如果无论如何数据损坏,END字节也会损坏。因此,在验证整个协议之后,该条目不会发生变化。 校验和不是一个好主意,如果你想在你的协议中包含CRC,你可以选择CRC16而不是CRC16。