安全存储和访问EEPROM

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

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

广泛的谷歌搜索只发表了一篇文章, 通过固件更新保持您的EEPROM数据有效 。 有没有人使用过该文章中讨论的方法? 有更好的替代方法吗?

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

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

以下是其中一个表格的示例:

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并支持列出的表版本,它会将数据加载到表的主体之外(当然,在validation校验和之后)。 如果ID,版本或校验和未签出,则只会跳过该表。 length字段用于定位链中的下一个表。 当固件看到长度为零的表时,它知道它已到达数据的末尾并且没有更多的表要处理。

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

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

Nigel Jones介绍了一些基础知识。 有很多选择。

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

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

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