Eeprom read and write of a structure

Thread Starter

electronicsLearner77

Joined May 26, 2012
127
I have written a eeprom read and write keeping in mind an array
Code:
void EepromWrite(char *data,unsigned char noofbytes, char addr);
Now i want to pass a struct. Can i simply send a struct as below.
Code:
EepromWrite((char *)(&struct), sizeof(struct), addr);
Does it have complications like padding bytes or some other problems? Can the struct have another struct as a member? Please advise.
 

miniwinwm

Joined Feb 2, 2018
68
I have written a eeprom read and write keeping in mind an array
Code:
void EepromWrite(char *data,unsigned char noofbytes, char addr);
Now i want to pass a struct. Can i simply send a struct as below.
Code:
EepromWrite((char *)(&struct), sizeof(struct), addr);
Does it have complications like padding bytes or some other problems? Can the struct have another struct as a member? Please advise.
1) Yes.

2) It will still work if there's padding in your struct, but space in EEPROM will be wasted. You can arrange your struct members to reduce this. You might be able to specify a packed structure - depends on the processor you are using and performance limitations.

3) Yes, but these methods of serializing a struct won't work if the struct (or any sub-structs) contain a pointer.

Or use the union method as specified by Ian Rogers. Here it is in compilable form...

Code:
typedef struct
{
  int a;
  char b; 
  int c;
} s_t;

union u
{
  s_t s;
  char array[sizeof(s_t)];
};
 
Last edited:

Thread Starter

electronicsLearner77

Joined May 26, 2012
127
Really i have a huge structure which i need to write into EEPROM. It has structure within the structure i am really scared to use the sizeof structure. Please suggest me how to proceed. I was thinking of creating one more function before actually giving it to eeprom, i will write this structure data into one another array and pass it for eeprom. I think even the union method will have padding. I do not want to use the bit manipulation as it may not be portable. Please suggest.
 

Thread Starter

electronicsLearner77

Joined May 26, 2012
127
I have got 128KByte of EEPROM. I am trying to write Diagnostic trouble code information. As of now for one DTC it is approximately 30 bytes, it can be more in future. At a time one DTC i am writing. Total EEPROM will be number of dtcs* 30.
 

Ian Rogers

Joined Dec 12, 2012
1,136
Okay!! 128k serial and parallel EEPROMs allow 64 byte page write so you can only write 2 structures at a time.

The buffer (64byte) once filled, needs 10ms (ish) to store the data... So I would recommend storing one structure per write cycle..
 

miniwinwm

Joined Feb 2, 2018
68
But it includes padding bytes or not?
I can't answer. It depends on the processor you are using, whether you have specified packed structures, and the layout of your data in the structure.

If there are no padding bytes then sizeof gives the total size of all the members.
If there are padding bytes added by the compiler then sizeof gives the total size of all the members and all the padding bytes.

The easiest way to tell is to create a few structs of different types with different members of varying layouts, get the size by calling sizeof on an instance of the struct and printf it out. Do some experiments!
 

Thread Starter

electronicsLearner77

Joined May 26, 2012
127
Finally i have decided to write it as a structure to reduce the code size and also in case the structure changes it will benefit. I would lose some padding bytes but that should not be a problem. I am planning something like below.
Code:
void eeprom_data(uint8_t *p, uint8_t size);
typedef struct log_tag
{
  unsigned int number1[10];
}log;


typedef struct dtc_data_tag
{
   struct log data_log;
   unsigned int number;
}dtc_data;
dtc_data test_data[10];

int main(void)
{
  eeprom_data(test_data[0],sizeof(dtc_data));
return 0;
}
 

miniwinwm

Joined Feb 2, 2018
68
As all members of the struct are ints or a struct of ints there won't be any padding anyway.

Your call to eeprom_data is passing a dtc_data whereas you declared it to take a uint8_t*. You need a & operator and a cast in the call to eeprom_data.
 

MrSoftware

Joined Oct 29, 2013
2,188
In regards to variable sizes and padding; if you are writing this data on one device (such as a micro controller), and reading it back on another (such as a PC), then there are several potential pitfalls. Padding might not match, sizeof(whatever) on the writing platform might not match the reading platform, one might be little endian and the other big endian, etc.. If this is the case then you need to write yourself a spec for the data that explicitly specifies every byte. You would specify exactly how big each data type is, the endianness, the size of the total block of memory, and which variables each byte in the block belong to. Now there is no "I wonder if there is padding", because your spec will tell you. Follow your spec when you write to eeprom, and when you read from eeprom, and it will always work.
 

MrSoftware

Joined Oct 29, 2013
2,188
Here is an example; ISO 9660 format. Yours obviously doesn't need to be this complex, but this is a good example of explicitly defining every field:

https://wiki.osdev.org/ISO_9660

Notice that the first thing they do is describe the size of every data type used, and the byte order (endianness). Now scroll down to the structure "The Boot Record" about half way down. Notice that every byte of every field is explicitly defined. They specify the exact byte that each field starts on, the data type, and how long the field is. For example, the "Boot System Identifier" field starts on the 8th byte (byte 7) and is exactly 32 bytes long. There is no "maybe there is padding before this field", it will be on the 8th byte always. Do this same thing for the data you want to store on your EEProm, and as long as you code to the spec, it will always work.
 
Top