Eeprom EEMEM attribute address

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All

I am using the EEMEM attribute to read and write to about 10 sets of variables. How do I ensure that eeprom address assigned to those eeprom variable would not change on future revisions of my firmware?

I am to update my device remotely, therefore it is updating the flash only. Can there be a chance that on compilation 'A' eeprom variable address could be 1 for example and then on another compile this address could change?

Regards

DJ

Thanks

Regards

DJ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All

I have just read placing all eeprom in a global struct would ensure they all start at 0 and kept in the same order.

Is this correct?

Thanks

Regards

DJ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes that is exactly the way to guarantee a fixed layout. In later versions just add things to the end.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Clawson

 

Thanks

 

I presume it will always start at 0. I i will place an 32-bit variable at the start of the struct for any eeprom corruption problems due to location 0. 

 

Is there anything else that can be done to insure the eeprom does not get corrupted?

 

 

Thanks

Regards

DJ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have added a check byte.

When I make a change to the eeprom structure I change the check byte...

Also I have defined default fail save values in flash. So when the check bytes do not match I fall back tot he fail safe values.

You could also add a CRC and make sure that is correct...

then you should be at least always falling back to the defaults when things go wrong.

 

keeping the eeprom from getting corrupted is something you never can rule out.

There is something with writing to the eeprom and a power fail that happens at x time after write started, that can corrupt, so you have to make sure the power supply is OK before you start a write and then also make sure that when you remove power the capacitance on the board is large enough to keep the processor powered for at least that time. Also thus detecting a power fail before you start writing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


djoshi wrote:
Is there anything else that can be done to insure the eeprom does not get corrupted?
Typical datasheet has:

 

I assume you are also following that advice?

 

(but it probably doesn't hurt to put a "dummy" at the start of the struct{} just to be sure)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks i will add the suggested and i am using brownout at 2.7V.

 

Regards

 

 

 

Thanks

Regards

DJ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

djoshi wrote:

I have just read placing all eeprom in a global struct would ensure they all start at 0 and kept in the same order.

Is this correct?

clawson wrote:
Yes that is exactly the way to guarantee a fixed layout. In later versions just add things to the end.

It would seem as though we ar4e trying to make a decision without all the information.  While I certainly wouldn't disagree with any of the responses in this thread I see a couple possible gotchas.

 

1)  Language and toolchain.  I guess Cliff inferred C language (a good guess from the mention of struct, right?).  And inferred using the infinite-value toolchain? (GCC)  Depending on the toolchain and version, the "struct starting at 0" may not apply. 

 

djoshi wrote:
Thanks i will add the suggested and i am using brownout at 2.7V.

Now, again, one cannot diss Mom and apple pie without being subjected to a rousing round of boos.

 

2)  Which AVR model is under consideration?

3)  What clock speed?

4)  What supply voltage level?

 

So, let's consider a Mega32A operating at 16MHz and 5V.  2.7V brownout still a recommended "solution"?

In other words, give necessary basic information when posing a question.

 

[edit]  My apologies; any idiot seeing EEMEM would know AVR/C/GCC

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Mon. May 18, 2020 - 05:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

djoshi wrote:
I presume it will always start at 0

No:

 

theusch wrote:
Depending on the toolchain and version, the "struct starting at 0" may not apply. 

 

Placing things in a struct guarantees that they will be contiguous (subject to padding), and in order - but says nothing about where they will be located.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using ATMEGA1284P at 8Mhx 3.3V and ATmega128RFA1 at 16mhz at 3.3V. 

 

I believe both are within the limits.

 

Yes i have kept a 32-bit dummy variable at the start of the struct.

 

I am using AVR studio 7, i am not sure about my compiler version.

 

The idea of checking a eeprom check sum sounds good,for certain settings, whereby once its goes back to the default settings the user can set it back to the preference,

 

But i am also setting something called board type. I have various system version, but all share the same PCB, but with some components not assembled or a variation. How can i ensure that eeprom ID is that original set it always intact?

 

The main core of my firmware will be identical, therefore i do not want to make multiple version of the firmware. At production, i can flash the eeprom with the correct version value. But when it comes to remote updates, i would prefer to generate one files for all board types, therefore would need to ensure eeprom variable for board type is always intact.  Or is there a better way to do this?

 

 

Thanks

Regards

DJ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

djoshi wrote:

The main core of my firmware will be identical, therefore i do not want to make multiple version of the firmware. At production, i can flash the eeprom with the correct version value. But when it comes to remote updates, i would prefer to generate one files for all board types, therefore would need to ensure eeprom variable for board type is always intact.  Or is there a better way to do this?

 

I've had similar issues and can tell you keeping track of which s/w version goes with what h/w version can be a problem.  Since you talk about remote updates, I'll assume you are using some type of bootloader to do your updates.

Create a unique bootloader for each board variation, unique in that it returns the h/w version ID of the board.  Since bootloaders never change once the board leaves the factory, you can query remotely the board ID/version/serial number, etc. that is stored within the bootloader, verify this h/w version supports the new firmware before uploading firmware updates or configures itself for the h/w version reported.

 

Jim

 

 

 

 

Last Edited: Tue. May 19, 2020 - 01:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

djoshi wrote:
I am using AVR (sic)  studio 7, i am not sure about my compiler version.

actually Atmel Studio - it's not just for AVR.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Drop EEPROM and locate the struct with the linker instead of a .c file.

The standard mechanism is an attribute to place the struct in an orphan section

and a linker option to place the section where you want.

 

Edit: Now that I think of it,

unless you have initial data for the EEPROM,

don't bother with the orphan section,

just define the symbol with the linker.

You really do not even need to do that,

just #define a pointer to it:

#define toeeprom ( (struct EEData *)1 )

I picked on one instead of zero because zero represents

a null pointer regardless of its representation.

There is a remote chance that avr-gcc would

do something clever and unpleasant with it.

Iluvatar is the better part of Valar.

Last Edited: Tue. May 19, 2020 - 09:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jim

 

The main difference between the boards are the GPIO pins use for which mosfet device. 

 

My application downloads the update and then jumps to boot sector to update the flash, therefore i would need to check the application layer as the boot loader is already on current boards at various locations.

 

 

Thanks

Regards

DJ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:

Drop EEPROM and locate the struct with the linker instead of a .c file.

The standard mechanism is an attribute to place the struct in an orphan section

and a linker option to place the section where you want.

 

Please can you explain further or show an example?

Thanks

Regards

DJ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

djoshi wrote:
Please can you explain further or show an example?
He means:

typedef struct {
    uint16_t modelType;
    struct {
        int n;
        long l;
        char c;
    } payload;
} info_t;

__attribute__((section(".flashInfo"))) info_t flash_info = {
    0xBABE,
    { 12345, 0xACEBLADE, 'X' }
};

Later something like:

-Wl,-section-start=.flashInfo=0x3C00

Now that block of struct info is built into the code and lies in flash at 0x3C00.

 

If you want to, using SPM, you could have some mechanism where you deliver the 128/256/whatever bytes at 0x3C00 separately so you can build different copies of the 3C00 info and deliver them separately.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are going to have defaults stored in flash, there is probably no need to use EEMEM as its primary purpose is to produce data for the hex file for init values. You will already have the data in flash with a mechanism to init the eeprom if needed so no need for the initial ee hex data.

 

For your board version value, you could store it in the last eeprom location(s). You will most likely never use every byte of eeprom so tuck it away at the end and never write it again. A simple hex record added to the initial firmware hex file would take care of it (one record for each board version, insert the one needed).

 

typedef struct {
    uint32_t a;
    uint16_t b;

    uint8_t c;

} settings_t;

 

PROGMEM //flash, default values for ee
const settings_t default_settings = { 1, 2, 3 };

 

//if want a ram copy of ee, load/verify via eeprom_read_block on boot
settings_t settings;

 

//if want to access individual ee vars instead of ram copy

#define SETTINGS &(*(settings_t*)0) //0 based eeprom
uint32_t a = eeprom_read_dword( SETTINGS.a ); //read a specific ee var

 

You can certainly add more things- checksum in struct to verify data, reload from flash if bad, add a way to upgrade current settings when firmware updated which has more vars (at end of struct), and so on.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks

 

I will give that a go.

 

So writing to the the flash directly at location 0x3C00 , would this mean there is possibility that my boot loader could over write it? As my existing boot loader also pads all remaining pages to 0xFF.

Thanks

Regards

DJ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A bootloader is really just an SPM page writer. It could replace any kind of data in the flash.