Eeprom read and write of a structure

Discussion in 'Programmer's Corner' started by electronicsLearner77, Mar 19, 2018.

  1. electronicsLearner77

    Thread Starter Active Member

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

    Active Member

    Dec 12, 2012
    418
    106
    I would change the struct to a union... Create an array in the union and use that
    Code (C):
    1.  
    2. union
    3.    {
    4.     struct{
    5.     element 1;
    6.     element 2;
    7.     element 3;
    8.     }
    9.     char array[size of the elements];
    10. }
    11.  
    12.  
     
    electronicsLearner77 likes this.
  3. miniwinwm

    Member

    Feb 2, 2018
    67
    25
    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 (Text):
    1.  
    2. typedef struct
    3. {
    4.   int a;
    5.   char b;
    6.   int c;
    7. } s_t;
    8.  
    9. union u
    10. {
    11.   s_t s;
    12.   char array[sizeof(s_t)];
    13. };
    14.  
     
    Last edited: Mar 20, 2018
    electronicsLearner77 likes this.
  4. Ian Rogers

    Active Member

    Dec 12, 2012
    418
    106
    LOL...I didn't test it... But I was hoping the TS got the gist!!
     
  5. electronicsLearner77

    Thread Starter Active Member

    May 26, 2012
    115
    1
    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.
     
  6. Ian Rogers

    Active Member

    Dec 12, 2012
    418
    106
    Huge... How huge.. If it is bigger than the buffer on the external EEPROM, you'll have to write in stages..

    Which EEPROM have you got.

    Most EEPROMs have paged writes..
     
  7. electronicsLearner77

    Thread Starter Active Member

    May 26, 2012
    115
    1
    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.
     
  8. Ian Rogers

    Active Member

    Dec 12, 2012
    418
    106
    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..
     
  9. miniwinwm

    Member

    Feb 2, 2018
    67
    25
    sizeof() works for structs that contain structs, as long as there are no pointers to anything external to the struct. You'll get the size of the pointer then, and not the data it points to.
     
  10. electronicsLearner77

    Thread Starter Active Member

    May 26, 2012
    115
    1
    You want me to convert the struct data into array and write it or write the structure as it is? Please advise.
     
  11. electronicsLearner77

    Thread Starter Active Member

    May 26, 2012
    115
    1
    But it includes padding bytes or not?
     
  12. miniwinwm

    Member

    Feb 2, 2018
    67
    25
    Either.
     
  13. miniwinwm

    Member

    Feb 2, 2018
    67
    25
    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!
     
  14. electronicsLearner77

    Thread Starter Active Member

    May 26, 2012
    115
    1
    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 (Text):
    1.  
    2. void eeprom_data(uint8_t *p, uint8_t size);
    3. typedef struct log_tag
    4. {
    5.   unsigned int number1[10];
    6. }log;
    7.  
    8.  
    9. typedef struct dtc_data_tag
    10. {
    11.    struct log data_log;
    12.    unsigned int number;
    13. }dtc_data;
    14. dtc_data test_data[10];
    15.  
    16. int main(void)
    17. {
    18.   eeprom_data(test_data[0],sizeof(dtc_data));
    19. return 0;
    20. }
    21.  
     
  15. miniwinwm

    Member

    Feb 2, 2018
    67
    25
    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.
     
  16. MrSoftware

    Senior Member

    Oct 29, 2013
    1,082
    309
    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.
     
    JohnInTX likes this.
  17. MrSoftware

    Senior Member

    Oct 29, 2013
    1,082
    309
    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.
     
Loading...