Programming the EEPROM

I'm looking to program the eeprom with certain values as my program is being downloaded. I know this is possible and works in CCS compiler for pic along with pickit2 programmer. I can write something like

#rom 0x212A={0,0}

and this would be written to the eeprom directly when programming the ic. Does anyone know of anything equivalent in arduino / avr to achieve this? or should i use PROGMEM ? I need to write a list of values to the eeprom based on which my program will work. Now these values will be changed once on the first execution based on sensor values and these set of values will be stored as reference for all future executions of the program.

All help is welcome.

Cheers, Pracas

Don’t know if it can be done the way you want but there are several workarounds.

One way to do it is to make a small sketch that places the needed values in EEPROM. Then load your intended sketch and it can read/modify the values.

Another way to do is to check if eeprom has valid values and if not initialize them and read/modify them. To do this there should be some kind of signature (magic cookie) in EEPROM.

The advantage of the first approach is that your intended sketch may be a bit smaller. I used this “trick” to decrease the size of a sketch that approached the 30KB limit with a few dozen bytes. Furthermore by having a separate application to write the eeprom one is able to add things like serial number (or device ID) in a more controlled way.

#include <EEPROM.h>

struct config_t
{
  char vers[8];                 // version
  byte mac[8];
  byte ip[6];
  byte gw[6];
  byte sn[6];
  byte server[6];               // remote server
  unsigned int port;            // port
  unsigned long id;             
  unsigned int precision;     
  unsigned int sec_per_sample;  // Frequency 
} config = {
  "0.04",
  { 0xDE, 0xAD, 0x00, 0x00, 0x00, 0x12 },
  { 192, 168, 1, 123},
  { 192, 168, 1, 1 },
  { 255, 255, 255, 0 },
  { 192,168,1,240 },
  8888,
  19,
  11,
  1
};


template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
    const byte* p = (const byte*)(const void*)&value;
    int i;
    for (i = 0; i < sizeof(value); i++)
        EEPROM.write(ee++, *p++);
    return i;
}

template <class T> int EEPROM_readAnything(int ee, T& value)
{
    byte* p = (byte*)(void*)&value;
    int i;
    for (i = 0; i < sizeof(value); i++)
        *p++ = EEPROM.read(ee++);
    return i;
}

void readEEPROM()
{
  EEPROM_readAnything(0, config);
}

void writeEEPROM()
{
  EEPROM_writeAnything(0, config);
}

void dumpConfig()
{
  readEEPROM();
  byte* p = (byte*)(void*)&config;
  for (int i = 0; i < sizeof(config); i++)
  {
    Serial.print(*p++, HEX);
    Serial.print(" ");
  }
  Serial.println();
}

///////////////////////////////////////////////////////////////////

void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);  
}

void loop()
{
  digitalWrite(13, HIGH);
  Serial.println("Start writing EEPROM");
  delay(1000);           
  writeEEPROM();
  delay(1000);
  
  dumpConfig();

  Serial.println("Ready writing EEPROM");

  while(true)                // blink to indicate ready
  {
    digitalWrite(13, HIGH);
    delay(50);                  
    digitalWrite(13, LOW);
    delay(50);               
  }
}

How about having your first values in flash, the EEPROM will be 00s so you can tell this is the first time. Then when you have new values write them into EEPROM.


Rob

How about having your first values in flash, the EEPROM will be 00s so you can tell this is the first time.

are you sure they will be 00's ? is there a way to program the eeprom using avr-dude?

are you sure they will be 00's

Not 100%, they could be FF or random (I doubt random but you never know).

The only issue is knowing the first time the code runs right?

So if your EEPROM has

value,value,value,value,value,checksum

as a "signature" then there's no way that will occur naturally.

Check the signature values and the checksum, if it fails it's the first run of the code.

As for programming the EEPROM with dude, sorry I don't know.


Rob

is there a way to program the eeprom using avr-dude?

The latest bootloader (optiboot; the one on Unos) does not support writing the EEPROM. You could do it with a "real device programmer." (but it wouldn't be significantly easier than downloading a sketch that wrote the eeprom.)

value,value,value,value,value,checksum

Great idea... that will work...

but it wouldn't be significantly easier than downloading a sketch that wrote the eeprom.

I'm ok with avrdude command line... thats how i put the bootloaders... only what is the file format for the eeprom?

(Just had my first experience with avrdude so certainly not an expert)
You can read the EEPROM with avrdude -U option and you have choice of different formats. I expect that these formats can be written back - although some are explicit only for input/output. Read the section in the dude manual to be sure.

Raw binary and an hexeditor could do miracles I think.

Rob

value,value,value,value,value,checksum

Great idea... that will work...

sure: 0, 0, 0, 0, 0, 0 ;)

True, checksums don't normally work with all 0s, although I did a modified BSD checksum once that did.

Still you can use a CRC.

If the "checksum" is really say the inversion of the last byte + N it would probably work.

If the first 5 bytes in EEPROM are some identifiable pattern placed after the first execution, there's no way that would appear normally.

If we could verify that the EEPROM is always 00s then the whole thing is moot as long as 00s is not a valid combination of the data.

So there has to be a heap of ways to tell if this is the first time a program has run.


Rob

Still you can use a CRC.

Sure. I didn't want to imply that you could not. There was a smiley ;)

It was more like a joke, but a little bit meant to show a hidden gotcha.

Sorry if I came across a bit strong, not my intention.

The modified BSD algorithm I referred to did catch all 0s, but tripped up on some combinations where in two seperate byte streams, identical except one byte was incremented, it sometimes produced the same CS. I never did figure it out, just went back to standard BSD.


Rob

is there a way to program the eeprom using avr-dude?

Just found out yesterday with an Arduino 2009.

Reading the EEPROM to a file called eeprom.bin

avrdude -C "C:\Program Files (x86)\arduino-0021\hardware\tools\avr\etc\avrdude.conf" -p atmega328p -c stk500 -U eeprom:[glow]r[/glow]:"c:/eeprom.bin":r -P\\.\COM5 -b57600

Writing the EEPROM with the file eeprom.bin

avrdude -C "C:\Program Files (x86)\arduino-0021\hardware\tools\avr\etc\avrdude.conf" -p atmega328p -c stk500 -U eeprom:[glow]w[/glow]:"c:/eeprom.bin":r -P\\.\COM5 -b57600

Looking at the binary file the not used part of my EEPROM is filled with 0xFF

Please read the avr-dude.pdf file to understand the options used.

Rob

Just found out yesterday with an Arduino 2009.

Thanks rob... i was about to try this today... why read it to a .bin file? why not a .hex file?

.bin and .hex are just filename extentions, it about what's in the file. I choose the raw dataformat (r flag) because after downloading it from the arduino, it can be modified with a hex-editor and uploaded again. If you read the avrdude manual you see that the -U option states the following about some output formats:

d    decimal; [glow]this and the following formats are only valid on output.[/glow]
They generate one line of output for the respective memory section,
forming a comma-separated list of the values. This can be particularly
useful for subsequent processing, like for fuse bit settings.
h    hexadecimal; each value will get the string 0x prepended.
o    octal; each value will get a 0 prepended unless it is less than 8 in
which case it gets no prefix.
b    binary; each value will get the string 0b prepended.

Of course you could make a binary file of 1024 bytes yourself and just upload this to EEPROM. It is not necessary to download one first. The reason I used a separate sketch (see previous post) is that I keep better control about the semantics of the variables in the EEPROM.

I have even thought about a bit more elaborate sketch with an Ethernet shield. A dialog would ask which image (name) to put in EEPROM and the Arduino would fetch it from a webserver. If it doesn't exist (BEEP) otherwise the 1024 bytes are fetched and written into the EEPROM. The webserver could add unique id's, ethernet adresses to the image to provide unique images every time an image is asked for. Handy when scaling up production someday.