使用某种文件分配表在EEPROM中存储结构

时间:2011-08-25 12:33:03

标签: c microcontroller eeprom

我在将数据存储在Fujitsu 16位微控制器的EEPROM中时遇到问题。 将字节写入EEPROM不是问题,我可以按字节顺序写入和读取数据。

我们使用dword的枚举来在EEPROM中存储不同的变量,它们都是4个字节长。对于每个变量,我们要存储最多4个字节的空间。这几乎不好,因为当我只想存储一个标志(一位)或一个只有一个字节长的变量时,它仍然会占用四个字节。

我们使用这种四字节技术的原因是我们知道要在哪个地址存储我想要访问的变量。这样可以,但它有一些缺点。

一个是浪费的空间,另一个是我在使用结构时出现的问题。

例如,我有一个像

这样的结构
typedef struct {
    attenuator_whichone_t attenuator;
    char*                 attenuatorname;
    servo_whichone_t     associated_servo;
    ad_ad7683_whichone_t associated_adconverter;
    word                 item_control;
    word                 item_mode;
    word                 item_position;

} attenuator_info_t;

并将其初始化为:

static attenuator_info_t constinfo[_NUM_ATTENUATOR_WHICHONE_] = {...}

使用我们现在使用的代码,我们需要单独保存每个值。 因此打破了结构。我真的想要保存那个结构。 (以及我们在代码中的更多内容)。

根据我的理解,我需要一个文件系统。谷歌搜索给了我一些例子,如microFAT等。在我看来,这是矫枉过正。

使用sizeof存储结构并遍历所有字节会很好,但是,我如何处理知道EEPROM中结构的位置的问题? 因此可能需要某种文件系统。有什么小的吗?还是一些招数?无论如何,变量具有固定长度。所以这就是为什么我想知道是否有一些很好的和简单的方法来存储这些结构。

我希望我能详细说明我的问题。

2 个答案:

答案 0 :(得分:1)

如果你有一个结构数组,你应该能够将数据写入EEPROM并在以后相当容易地读出来。这里的关键是确切地知道EEPROM中存储数据的

您可以通过多种方式完成此操作。对于简单项目,您只需定义一个常量,表示存储表的内存范围的起始地址:

#define ATTENUATOR_INFO_START 0x0100 // Indicates table starts at address 256
#define ATTENUATOR_INFO_SIZE (sizeof(constinfo)/sizeof(*constinfo))

// Store table in EEPROM
memcpy(EEPROM_START + ATTENUATOR_INFO_START, constinfo, ATTENUATOR_INFO_SIZE);

// Load table from EEPROM
memcpy(constinfo, EEPROM_START + ATTENUATOR_INFO_START, ATTENUATOR_INFO_SIZE);

以上假设EEPROM映射到存储器中,常量EEPROM_START表示映射到EEPROM偏移零的存储器地址。如果你的项目没有将EEPROM映射到内存中,那么你的程序会略有不同,但总体思路是一样的。

如果您不想将表存储在固定的偏移量,则另一种方法是将表的偏移量记录在EEPROM中。这个过程大致相同:

// Offset/length information is stored in the first few bytes of the EEPROM
#define TABLE_INFO_LOCATION 0x0000

struct table_info {
    unsigned int offset;
    unsigned int num_entries;
} table_info;

// Retrieve table offset
memcpy(&table_info, EEPROM_START + TABLE_INFO_LOCATION, sizeof(table_info));

// Load table from EEPROM
memcpy(constinfo,
       EEPROM_START + table_info.offset,
       table_info.num_entries * sizeof(*constinfo));

这种方法可以提供更大的灵活性,因为表可以位于EEPROM中的任何位置,但仍需要一个已知位置来存储表信息。

如果您无法以预先确定的偏移量存储任何,则可以创建页眉/页脚签名以包装数据结构。对于未使用的字节,大多数内存设备默认为0x000xFF。您可以在表的前面立即写入32个字节的模式0xBE(用于“之前”),然后在您的表之后立即写入32个字节的模式0xAF(用于“之后”)。这将允许您扫描EEPROM的内存并找到表的起点和终点,无论它在哪里。缺点是,如果存储器模式出现在EEPROM中的任何其他地方,则冒险寻找错误的位置,因此明智地选择页眉/页脚模式和大小。

答案 1 :(得分:0)

  

根据我的理解,我需要一个文件系统。谷歌搜索给了我一些像microFAT​​等的例子。在我看来,这是矫枉过正。

不,文件系统与您描述的任务无关。文件系统定义文件名称文件之间的映射,可以任意创建,访问,删除和调整大小。您没有在运行时提及修改的名称或要求。这似乎有点过分,因为定义文件系统的基本服务是你不需要的东西。

  

我们使用dword的枚举来在EEPROM中存储不同的变量,它们都是4个字节长。

我认为你的意思是一组dword s。

如果这导致问题,为什么不考虑改变呢?

听起来你只知道如何使用表格

的定义来初始化EEPROM
static attenuator_info_t constinfo[_NUM_ATTENUATOR_WHICHONE_] = {...}

EEPROM没有技术限制,需要这样做。 struct是一个字节序列,就像array一样。大多数嵌入式编译器还允许您将struct,数组和其他定义的序列视为一个字节序列,方法是用适当的#pragma包围它们。

了解EEPROM,或者在构建程序后constinfo是否发生了变化,我无法告诉你如何写入它。但是看起来你想要将一堆命名变量映射到一个字节序列。这可能需要文件格式,但不是文件系统。

如果EEPROM是内存映射的,那么你只需编译指针就可以了:

extern struct foo_info_type foo_info;
extern struct bar_info_type bar_info;

/* EEPROM table of contents */
struct foo_info_type *foo_ptr = & foo_info;
struct bar_info_type *bar_ptr = & bar_info;
/* ... more pointers ... */

/* Actual data in EEPROM, pointers point here */
struct foo_info_type foo_info;
struct bar_info_type bar_info;