2

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

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

4

2 回答 2

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

于 2012-07-18T22:03:14.610 回答
1

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

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

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

我想你的意思是一个s数组dword

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

听起来您只知道如何使用表单的定义来初始化 EEPROM

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

没有要求这样做的 EEPROM 的技术限制。Astruct是一个字节序列,就像一个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;
于 2012-05-26T03:48:43.243 回答