![]() |
1
8
就我个人而言,我更喜欢“标记表”格式。 在这种格式中,您的数据被拆分为一系列“表”。每个表都有一个遵循可预测格式的标题和一个可以根据需要更改的正文。 下面是其中一张表的示例:
我没有存储太多的数据,所以我对头中的每个字段使用了一个字节。你可以用你需要的任何尺寸,只要你不改变它。数据表一个接一个地写入EEPROM。 当您的固件需要从EEPROM读取数据时,它会从第一个表开始读取。如果固件识别出表ID并支持列出的表版本,那么它将从表的主体中加载数据(当然是在验证校验和之后)。如果ID、version或checksum没有签出,则跳过该表。长度字段用于定位链中的下一个表。当固件看到一个长度为零的表时,它知道它已经到达了数据的末尾,并且没有更多的表要处理。 我发现这种格式灵活(我可以将任何类型的数据添加到表体中)而且健壮(保持头格式不变,数据表将同时向前和向后兼容)。 有几个注意事项,尽管它们不太麻烦。首先,您需要确保固件能够处理重要数据不在表中或使用不受支持的格式版本的情况。您还需要将EEPROM存储区的第一个字节初始化为零(这样,在第一次引导时,您就不会认为它是数据而开始在垃圾中加载)。因为每个表都知道它的长度,所以可以扩展或收缩一个表;但是,您必须移动表存储区域的其余部分,以确保没有“洞”(如果整个表链无法放入设备内存,那么这个过程可能会很烦人)。就我个人而言,我不觉得这些都是一个大问题,这是值得的麻烦,我节省了一些其他方法的数据存储。 |
![]() |
2
3
奈杰尔·琼斯在你的参考资料中介绍了一些基本知识。有很多选择。 另一种方法是存储键值对,而不是存储结构。然后您可以更新一个值(通过附加它),而不必删除所有内容。这在擦除周期数有限的设备中最有用。读取例程需要从头开始扫描,每次遇到键时更新值。当然,您的更新例程需要有一个“垃圾收集器”,在内存满时启动。 为了在更新过程中处理设备错误和断电,我们通常存储多个数据副本。最简单的方法是使用序列号在两到两个设备之间进行乒乓球,以确定哪个较新。每个部分上的CRC用于验证它。这也解决了未初始化的数据问题。
|
![]() |
conopizda2 · 为什么我的静态数组没有被memset清除? 3 年前 |
![]() |
jhe4x · C按位OR返回的值不正确 3 年前 |
![]() |
Tim · 如何用c语言打印程序的执行流程# 7 年前 |
![]() |
jatinBatra · 关于嵌入式固件开发[已关闭] 7 年前 |
![]() |
Will · 嵌入链接器脚本-是否正确放置“堆栈”和“堆”区域? 7 年前 |
![]() |
K. Crow · 不等于PIC32上启用中断时操作员不工作[关闭] 7 年前 |
![]() |
spiff42 · 清除位时唯一的最大不同字节值集 7 年前 |