【问题标题】:Storing structs in EEPROM using some kind of file allocation table使用某种文件分配表在 EEPROM 中存储结构
【发布时间】:2012-07-19 06:03:14
【问题描述】:

我在富士通 16 位微控制器的 EEPROM 中存储数据时遇到问题。 向 EEPROM 写入字节没有问题,我可以按字节写入和读取数据。

我们使用dwords 的枚举将不同的变量存储在 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 中的位置的问题呢? 所以可能需要某种文件系统。没有更小的东西吗?还是什么诡计?无论如何,变量都是固定长度的。所以这就是为什么我想知道是否有一些好的和简单的方法来存储这些结构。

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

【问题讨论】:

  • 我想我刚刚找到了答案。在选择标签时,我发现了这一点:stackoverflow.com/questions/3551824/… 这可能对我有用。我试试看。
  • 如果您担心将 4 个字节转换为 1 个字节,文件系统将非常浪费,文件系统可能需要在文件中的每个块中刻录 2048 或 4096 或更多字节,您很少没有数万到数千个未使用的字节。跨编译域使用结构也是一个坏主意(将结构指向内存/文件等)。固定的 4 字节实体很好,将结构分解成单独的 4 字节实体很好,然后在它周围添加你发现的标记的东西很好。
  • 使用 eeprom 或闪存作为文件系统很糟糕,它们会磨损(是的,当前的商业产品是一次性的,您必须在磨损时不断重新购买它们、mp3 播放器、拇指驱动器, ETC)。理想情况下,您希望对它们进行一次编程,然后永远阅读,也许偶尔会添加一些东西。进行系统工程,以便了解产品的生命周期。随着它们的磨损,写入时间会变得更长,因此您的系统工程也会在那里。

标签: c microcontroller eeprom


【解决方案1】:

据我了解,我需要一个文件系统。谷歌搜索给了我一些例子,比如 microFAT​​ 等等。在我看来,这太过分了。

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

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

我认为您的意思是dwords 的数组。

如果这引起了问题,为什么不考虑改变它?

听起来你只知道如何用表单的定义来初始化 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;

【讨论】:

    【解决方案2】:

    如果您有一个结构数组,您应该能够将数据写入 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。您可以在表格前面立即写入模式0xBE(用于“之前”)的 32 个字节,然后在表格后面立即写入模式0xAF(用于“之后”)的 32 字节。这将允许您扫描 EEPROM 的内存并找到表格的开头和结尾,无论它可能在哪里。缺点是如果该内存模式出现在 EEPROM 中的任何其他位置,您可能会寻找错误的位置,因此请明智地选择页眉/页脚模式和大小。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多