我正在使用具有一些外部非易失性存储器的嵌入式设备(无操作系统)。
我在NV内存中存储单个结构数据的多个副本。我读取并写入内存中的数据作为整个结构和作为单个成员。
目前我有一个有效的实施方案。当处理内存操作的模块被初始化时,它被赋予RAM中的结构的位置,它作为其上下文的一部分存储。这意味着当涉及读取和写入单个成员时,它可以通过从成员的位置减去前面提到的位置来计算成员的偏移量。然后它使用此偏移量来知道在NV存储器中找到副本的位置。
e.g。在伪代码中:
init:
wm_ram = pointer to working memory struct start in RAM;
write to a member from the member in RAM:
offset = working memory member location in RAM - wm_ram;
sector address = address of selected copy of struct in NV to write to;
write data from working memory member location to NV sector @ start +
offset + sector address;
(结构类型有几个嵌套结构,所以我认为offsetof()就在这里)
这为常见操作带来了非常简单和熟悉的感觉功能签名:
int write_or_read(*handle, copyNumber, *data, size);
这很好,直到我还想从RAM存储第二个结构。这意味着RAM中现在有两个地址,内存模块需要跟踪以正确计算偏移量,还有一些额外的决策工作来决定使用哪个
因此,我推断结构RAM起始位置应该在内存操作时传入,而不是作为内存模块上下文的一部分保存。
虽然开始有点笨拙:
int write_or_read(*handle, copyNumber, *data, *data_struct_start, size);
所以我的问题是:是否存在经常或常用于类似或类似情况的任何约定或模式,希望这样也会导致简单熟悉的操作函数签名?
编辑:进一步说明 NV存储器是一个简单的外部器件,类似于EEPROM,具有2KB的存储器。我的结构包含多种数据类型,包括其他结构,每种结构大小约为600B。该设备没有缓冲;它实际上是FRAM,所以它相当快,但是我的开销很小,所以我不想只为一个成员编写整个结构。
图片显示我目前在RAM中有一个结构,在NV内存中有多个副本。如果我想读取或写入特定副本的特定成员,那么我只需要获取成员的地址(&myStruct->member_2
)就可以在RAM中获得该成员的地址,但我应该在NV中使用哪个地址? RAM地址不与NV中的地址对齐(例如,RAM中的地址0x300!NV中的0x300),因此我需要一些其他方法来确定。
如果读取或写入函数被告知在NV中将member_2
myStruct
的{{1}}副本写入struct_1,那么它需要写入哪个字节地址?
也许我试图保持界面这么简单是不正确的?
答案 0 :(得分:1)
不要使用结构进行序列化。
而是在明文数据文件(CSV,JSON,XML,...)中定义设置变量:
ID, TYPE, DEFAULT
Foo, int32, 120
Bar, float, 40.0
然后使用您选择的脚本语言将该数据文件转换为源文件。您可以从类型中确定所需的大小,并自动计算NV内存偏移到表格。
您的脚本吐出的其中一个文件是ID列表:
typedef enum {
ID_Foo,
ID_Bar,
ID_COUNT
} ID_T;
您提供的API很简单:
int32_t ReadInt32(ID_T id);
float ReadFloat(ID_T id);
void WriteInt32(ID_T id, int32_t value);
void WriteFloat(ID_T id, float value);
这有几个好处: