I have an application that keeps several large, changeable configuration structures in EEPROM. I then have a class that provides setters and getters for accessing individual fields within the struct, based on the offset of the field from the base of the struct, and the size of the field. Problem is, the only way I've found to generate those offsets is using an instance of the struct. I would like to avoid having to have this "dummy" structure in RAM, since I am short of RAM.
Below is the basic situation, greatly simplified. My only question is how to generate the individual offsets of the struct fields WITHOUT having to have the "dummy" struct in RAM, but rather working from the struct definition itself.
struct SomeStruct
{
uint32_t x;
uint8_t y;
}
SomeStruct dummy;
...
uint8_t getx()
{
uint8_t *offset = (uint8_t *)((uint16_t)(&dummy.x) - (uint16_t)&dummy);
return eeprom_read_word(offset);
}
Surely there is a way to do this WITHOUT having to use the struct instance, but I have not been able to come up with anything that works.
Also, just curious - I assume EEPROM are not unreasonable slow, like single-digit microseconds worst case? Write time is not a concern.
Regards,
Ray L.
Surely there is a way to do this WITHOUT having to use the struct instance, but I have not been able to come up with anything that works.
Have a look at the standard macro offsetof.
Like this:
struct SomeStruct
{
uint32_t x;
uint8_t y;
}
...
uint32_t getx()
{
return eeprom_read_dword(offsetof(SomeStruct,x));
}
Just some notes:
eeprom_read_word() returns an uint16_t and the x member is uint32_t, so the correct is eeprom_read_dword().
And the getx() return type also should be uint32_t.
Also, just curious - I assume EEPROM are not unreasonable slow, like single-digit microseconds worst case? Write time is not a concern.
Looking at the ATmega2560 Datasheet - page 35:
Erase and Write in one operation (Atomic Operation) -> 3.4ms
Erase only -> 1.8ms
Write only -> 1.8ms
For me, it is a considerable time and I don't dealing with offsets, so I usually load all of the EEPROM variables into struct in RAM at setup().
Then my program write to and read from this struct.
At important moments (user presses "save", for example) I save the whole struct into the EEPROM.
Something like this (untested):
#include <EEPROM.h>
struct MyConfigs {
uint8_t data[512]{ };
uint32_t integer{ 123 };
float money{ 1.23 };
uint16_t moreData[256]{ };
}
MyConfigs configs{ };
setup(){
const uint8_t firstInitialization{ EEPROM.read(0) };
if( firstInitialization == 0xFF ){ // EEPROM default is 0xFF
EEPROM.write(0, 0x00); // Next time wont be the first
EEPROM.put(1,configs);
}
else {
EEPROM.get(1,configs);
}
// Now configs is initialized
Serial.begin(115200);
Serial.println("start");
}
void loop(){
Serial.print("configs.integer = ");
Serial.println(configs.integer);
Serial.print("configs.money = ");
Serial.println(configs.money);
delay(2000);
configs.integer += 1;
configs.money += 1.23;
EEPROM.put(1,configs);
}
offsetof is perfect! Thanks!
I was asking about EEPROM READ times, not write. I don't care about writes, since nothing else needs to be going on when I do the writes.
Regards,
Ray L.
RayLivingston:
Also, just curious - I assume EEPROM are not unreasonable slow, like single-digit microseconds worst case?
Roughly the same as accessing SRAM through a pointer. (I assume you're using an AVR processor.)