2

I have a problem with storing data in an EEPROM on a Fujitsu 16-bit microcontroller. Writing bytes to the EEPROM is not the problem, I can write and read data bytewise with no problem.

We are using an enum of dwords to store different variables in the EEPROM and they are all 4 bytes long. For each variable we want to store up to those 4 bytes of space. This is pretty much not good, because when I only want to store a flag (one bit) or a variable which is only one byte long, it still uses up four bytes.

The reason we use this four byte technique is so we know on which adress the variable is stored that I want to access. This works OK, but it has quite some downsides.

One is the wasted space, and another one is the problem which arises when I'm working with structs.

For example I have a struct like

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;

and initializing it like:

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

With the code we are using right now, we would need to save every value individually. Hence breaking the structure apart. I would really want to store that structure as it is. (and a couple more we have in the code).

From my understanding I would need a filesystem for that. A Google search gave me some examples like the microFAT and so. This is, in my opinion, overkill.

Storing the struct with sizeof and iterate through all the bytes would be just fine, but then, how do I handle the problem of knowing where the structures are in the EEPROM? So some sort of file system is probably needed. Isn't there anything smaller? Or some trick? The variables are with a fixed length anyway. So that's why I was wondering if there is some nice and simple way to store those structs.

I hope I could elaborate on my problem enouph.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fritjof
  • 21
  • 1
  • 2
  • 1
    I think I just found the answer. While choosing the TAGs I discovered this: http://stackoverflow.com/questions/3551824/safely-storing-and-accessing-eeprom That might just work well for me. I'll try it out. – Fritjof Aug 25 '11 at 12:50
  • A file system is going to be very wasteful if you are concerned about turning 4 bytes into 1,a file system is likely going to want to burn 2048 or 4096 or more bytes per block in a file, rarely do you not have tens to thousands of unused bytes. Using structs across compile domains is also a bad idea (pointing a struct at memory/file, etc). fixed 4 byte entities is good, breaking the structs into individual 4 byte entities is good, and then adding that tagged thing around it that you found is good. – old_timer Aug 27 '11 at 15:09
  • using an eeprom or flash as a file system is bad they wear out (yep, current commercial products are disposable, you have to keep re-purchasing them as you wear them out, mp3 players, thumb drives, etc). Ideally you want to program them one time and then read forever, occasionally adding stuff perhaps. Do your system engineering so that you know what the life of the product will be. As you wear them out the write times get longer, so do your system engineering there as well. – old_timer Aug 27 '11 at 15:12

2 Answers2

1

From my understanding I would need a filesystem for that. A Google search gave me some examples like the microFAT and so. This is, in my opinion, overkill.

No, a file system is unrelated to the task you describe. A file system defines a mapping between file names and files which may be arbitrarily created, accessed, deleted, and resized. You have not mentioned names or requirements for modification at runtime. It seems like overkill because the essential services that define a filesystem are things you don't need.

We are using an enum of dwords to store different variables in the EEPROM and they are all 4 bytes long.

I think you mean an array of dwords.

If this is causing a problem, why not look into changing it?

It sounds like you only know how to initialize the EEPROM with a definition of the form

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

There is no technical limitation of the EEPROM which requires it to be done so. A struct is a sequence of bytes, just like an array. Most embedded compilers also allow you to treat a sequence of struct, array, and miscellaneous definitions as a sequence of bytes, by surrounding them with an appropriate #pragma.

Knowing nothing about the EEPROM, or whether constinfo changes after you build the program, I can't tell you how to write to it. But it really looks like you want to map a bunch of named variables to a sequence of bytes. That might require a file format, but not a file system.

If the EEPROM is memory mapped, then you can just compile pointers into it:

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;
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
1

If you have an array of structures, you should be able to write the data to an EEPROM and read it out later fairly easily. The key here is knowing exactly where in the EEPROM that the data is stored.

You can do this in a number of ways. For simple projects, you can simply define a constant representing the starting address of the memory range where your table is stored:

#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);

The above assumes that the EEPROM is mapped into memory and the constant EEPROM_START represents the memory address mapped to EEPROM offset zero. If your project doesn't have EEPROM mapped into memory then your procedure will be slightly different, but the general idea is the same.

If you don't want to store the table at a fixed offset, an alternative is to record the table's offset in the EEPROM as well. The process is generally the same:

// 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));

This method allows for more flexibility as the table can be located anywhere in the EEPROM, but still requires a known location to store the table information.

If you aren't able to store anything at a pre-determined offset, you can create a header/footer signature to wrap the data structure with. Most memory devices default to 0x00 or 0xFF for bytes that are unused. You could write 32 bytes of the pattern 0xBE (for "before") immediately in front of your table, and then write 32 bytes of the pattern 0xAF (for "after") immediately following your table. That will allow you to scan through the EEPROM's memory and locate the start and end of your table, wherever it might be. The drawback is that you risk seeking to the wrong location if that memory pattern appears anywhere else in the EEPROM, so choose your header/footer patterns and sizes wisely.

bta
  • 43,959
  • 6
  • 69
  • 99