Avrdude: writing to eeprom

I was writting a small software to make my different arduinos talk through some nrf24l01+.
All is fine but I’d like to have the mac adress not inside the software (means building a new for each arduino), but setting it in the eeprom during software write by avrdude.

The max address is an hexa 5 bytes such as : 0xFF1F1F1F00
I’ve been searching for hours to send anything in the eeprom by trying various files formats (intel hex, raw binary, hexadecimal) but failed at all.
My command line looks like this:

avrdude -patmega328p -carduino -v -P/dev/ttyUSB0 -b57600 -e -Uflash:w:${SOFTWARE}:a -Ueeprom:w:eeprom0.hex:h -C$AVRDUDECONF

Is there someone who already faced this question?

Thank you guys :slight_smile:

Avrdude doesn't write to EEPROM. A sketch can. Create a sketch that, in setup(), stores some data to EEPROM. Upload and the sketch will run.

Then, upload a sketch that reads from EEPROM, to get the data that the first sketch stored.


So if I understand: - I've to make one binary with only role to set a mac address inside the EEPROM. - Find a way to patch it by setting the target mac - Burn it inside the arduino - Burn the real software that reads the mac address inside the EEPROM memory

Am I ok?


A baud rate of 57600. Which board are you using?

The optiboot bootloader that is used on Arduino will always read/write from program memory even when avrdude asks it to read/write EEPROM.

The following command is sent by avrdude when attempting to read EEPROM:

avrdude: Send: t [74] . [00] . [04] E [45]   [20]

Notice the "E" indicating that the type of memory it would like to read is EEPROM.

The following snippit is taken from optiboot.c

    /* Write memory, length is big endian and is in bytes */
    else if(ch == STK_PROG_PAGE) {
      // PROGRAM PAGE - we support flash programming only, not EEPROM

It does not check to see if EEPROM or FLASH needs to be read.

I was able to read/write EEPROM with avrdude and my STK500 board connected to the ISP header on my Uno R3 with no problems.

Handy References: optiboot.c https://github.com/arduino/Arduino/blob/master/hardware/arduino/bootloaders/optiboot/optiboot.c

STK500 Communication Protocol (The protocol being used by optiboot) http://www.atmel.com/Images/doc2525.pdf

Arduino nano V3.00 and I’m working under linux. EDIT: it’s a 3.00 not a 1.00 …

So thank you PaulS and jgoulder. It seems that it won’t be so easy than I expected.
I planned to upgrade the bootloader because I don’t know where it comes from and which version I use. And also it is has a bug with watchdog timer (infinite reset loop).
I’ll take a look inside bootladers mechanics to find one that better suits my needs. Do you have one in mind that could be right?

Check out the older bootloader here:

It seems to handle EEPROM:

/* Write memory, length is big endian and is in bytes */
else if(ch=='d') {
length.byte[1] = getch();
length.byte[0] = getch();
flags.eeprom = 0;
if (getch() == 'E') flags.eeprom = 1;
for (w=0;w<length.word;w++) {
buff[w] = getch(); // Store data in buffer, can't keep up with serial data stream whilst programming pages
if (getch() == ' ') {
if (flags.eeprom) { //Write to EEPROM one byte at a time
address.word <<= 1;
for(w=0;w<length.word;w++) {

As far as compatibility with the Nano or the version of the IDE you are using, I will defer to someone else.

jgoulder: As far as compatibility with the Nano or the version of the IDE you are using, I will defer to someone else.

Ok thanx :) I'll take a look at this !

My IDE is eclipse with the freshly made arduino plugin. It may work.

PaulS: Avrdude doesn't write to EEPROM

I beg to differ


So I was searching for hours and eventually found a way to write EEPROM.

I began by downloading the eeprom directly from the atmega328p:

avrdude -patmega328p -carduino -v -P/dev/ttyUSB0 -b57600 -e -Ueeprom:r:eeprom0.hex:i

This gave me an intel Hex file:


Inserted my data in the first line:


Then tried to send it back to the atmega328p:

avrdude -patmega328p -carduino -v -P/dev/ttyUSB0 -b57600 -e -Ueeprom:w:eeprom0.hex:i

avrdude complained about the checksum (last byte of the line), bust it's cool it gave me the correct value :)

avrdude: checksum=0x00, computed checksum=0x9f

So modified the checksum and sent it back and it worked.

It was so obvious that I'm confusing XD