【问题标题】:Safely storing and accessing EEPROM安全存储和访问 EEPROM
【发布时间】:2010-08-23 21:24:56
【问题描述】:

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

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

Extensive Googling 只找到了一篇地址为keeping your EEPROM data valid through firmware updates 的文章。有没有人使用过那篇文章中讨论的方法?有没有更好的替代方法?

【问题讨论】:

    标签: c embedded eeprom


    【解决方案1】:

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

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

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

    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 存储区的第一个字节初始化为零(这样在第一次启动时,您就不会以为它是数据而开始加载垃圾)。由于每个表都知道它的长度,因此可以扩展或缩小表;但是,您必须移动表格存储区域的其余部分以确保没有“漏洞”(如果整个表格链无法放入设备的内存中,那么此过程可能会很烦人)。就个人而言,我认为这些都不是什么大问题,与使用其他一些数据存储方法相比,我节省的麻烦是非常值得的。

    【讨论】:

    • 这听起来是一个很好的解决方案来处理固件版本之间表大小的变化。除了复制数据之外,你有什么建议让它能够容忍写入中的断电吗?
    • 用无效的校验和写入整个表,然后(在单独的事务中)返回并写入正确的校验和。如果在写入过程中出现问题,那么当您读入数据时,您的校验和就会出错。
    • 这是一个优雅的解决方案,实施起来很简单:感谢您的跟进。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 理论上我真的很喜欢这种方法的声音,但不幸的是没有足够的 EEPROM 使其可行:在 ATmega328p 上只有 1 kB。感谢您的描述!
    猜你喜欢
    • 2019-10-13
    • 2012-09-11
    • 2017-12-25
    • 1970-01-01
    • 2020-10-10
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 2013-10-03
    相关资源
    最近更新 更多