11

我最近确定需要在微控制器的 EEPROM 中存储不经常更新的配置变量。向程序添加状态会立即迫使人们担心

  • 检测 EEPROM 中的未初始化数据(即首次启动),
  • 转换旧固件版本的数据或使数据无效,以及
  • 多个结构的寻址,每个结构都可能在固件更新中增长。

广泛的谷歌搜索只出现了一篇文章,解决了通过固件更新保持 EEPROM 数据有效的问题。有没有人使用过那篇文章中讨论的方法?有没有更好的替代方法?

4

2 回答 2

8

就个人而言,我更喜欢“标记表”格式。

在这种格式中,您的数据被分成一系列“表格”。每个表都有一个遵循可预测格式的标题和一个可以根据需要更改的正文。

以下是其中一张表的示例:

Byte 0: Table Length   (in 16-bit words)
Byte 1: Table ID       (used by firmware to determine what this data is)
Byte 2: Format Version (incremented every time the format of this table changes)
Byte 3: Checksum       (simple sum-to-zero checksum)
Byte 4: Start of body
...
Byte N: End of body

我没有存储大量数据,所以我为标题中的每个字段使用了一个字节。你可以使用任何你需要的尺寸,只要你从不改变它。数据表一个接一个地写入 EEPROM。

当您的固件需要从 EEPROM 中读取数据时,它会从第一个表开始读取。如果固件识别表 ID 并支持列出的表版本,它会从表体中加载数据(当然是在验证校验和之后)。如果 ID、版本或校验和未检出,则简单地跳过该表。长度字段用于定位链中的下一个表。当固件看到一个长度为零的表时,它就知道它已经到达数据的末尾并且没有更多的表要处理。

我发现这种格式很灵活(我可以将任何类型的数据添加到表的主体中)并且健壮(保持标题格式不变,并且数据表将向前和向后兼容)。

有一些警告,尽管它们并不太麻烦。首先,您需要确保您的固件可以处理重要数据不在表中或使用不受支持的格式版本的情况。您还需要将 EEPROM 存储区域的第一个字节初始化为零(这样在第一次启动时,您就不会以为它是数据而开始加载垃圾)。由于每个表都知道它的长度,因此可以扩展或缩小表;但是,您必须移动表格存储区域的其余部分以确保没有“漏洞”(如果整个表格链无法放入设备的内存中,那么此过程可能会很烦人)。就个人而言,我认为这些都不是什么大问题,

于 2010-08-23T21:52:53.337 回答
3

Nigel Jones 在您的参考资料中介绍了一些基础知识。有很多选择。

你们中有很多空间的另一种选择是存储键值对而不是结构。然后您可以更新一个值(通过附加它)而无需删除所有内容。这在擦除周期数有限的设备中最有用。您的读取例程需要从头开始扫描,每次遇到键时更新值。当然,您的更新例程需要有一个“垃圾收集器”,当内存已满时会启动。

为了在更新过程中处理设备错误和断电,我们通常存储多个数据副本。最简单的方法是使用序列号在设备的两半之间进行乒乓操作,以确定哪个更新。每个部分的 CRC 用于验证它。这也解决了未初始化的数据问题。

对于键值版本,您需要在每次写入后附加新的 CRC。

于 2010-08-23T22:01:02.817 回答