A simple question about using EEPROM in Atmega MCU

The answer to this question is probably quite obvious to everyone except me, yet I don't know how to find an answer.

Writing to EEPROM has a significant, several msec, latency. In the Arduino examples I've seen, Delay is used, but that stops everything. My question is: is it really necessary to stop the sketch or just avoid another write until the last EEPROM action is done?

I don't need instructions in how to avoid Delay; I do know how to do that. I just need to know whether other non-EEPROM actions can continue during the write time.

Just in case it might affect your answer, here's an outline of what I want to do. I have just one byte that I need to store in non-volatile memory. In the worst case, that number will be read as much as 100 times a day, and written to perhaps <=20 times a day. If I always use the same address, this will give a minimum life-time of 2.28 years, which is not enough for this application. Hence I intend to use a ring of 20 addresses, giving something like 45 years. Use of this number is not "real-time", hence the slow nature of EEPROM is of no concern, but other things I will be doing should not be delayed for that time. If Delay is actually required, I will use an external FRAM chip even for just this one number, but that seems pretty silly.

Ciao,
Lenny

In the Arduino examples I've seen, Delay is used, but that stops everything.

Not sure what these examples are. I have used the EEPROM read and write with no delays in many projects.

Thanks Grumpy for the quick reply. Clearly your programs ARE doing other things during the EEPROM write time, so there's no need for the delay. In my application EEPROM reads and writes will never be closely spaced - the data will be coming at multi-minute intervals from a CAN bus network - so I don't even have to check a timer within the sketch and I'm all set. Ciao, Lenny

Check the EEPE bit.

Another way is to have a FIFO queue and a timed loop to decide whether to write a byte at a correct interval.

Check if it is time to write another byte
YES - Check if there is anything in the FIFO queue - then write one byte and update the FIFO queue
NO - do other stuff

Thanks for the suggestions, but they really won't be necessary in this case. The byte that I have to save in EEPROM will change no more often than once every few minutes and it will only be written then. It will only be read once, when the sketch resets. There is no chance of EEPROM commands crashing into each other.
Ciao,
Lenny

I don't understand why you mention delay in relation to eeprom access.

No need for any delay at all. This is a small section of code that I use for storing an RFID token into EPROM, as you can see there are just one write after the other. I have no problems with this:-

 void saveToken(int point){ // saves the token in EEprom memory at point
    EEPROM.write(point, (tokensOnBoard[0] >> 24) & 0xff);
    EEPROM.write(point+1, (tokensOnBoard[0] >> 16) & 0xff);
    EEPROM.write(point+2, (tokensOnBoard[0] >> 8) & 0xff);
    EEPROM.write(point+3, tokensOnBoard[0] & 0xff);
    EEPROM.write(point+4,value[6]);
    EEPROM.write(point+5,value[7]);
    EEPROM.write(point+6,value[8]);
 }

Grumpy_Mike's example clearly shows that successive EEPROM operations don't crash and that delay is absolutely not needed. I think that I got confused by looking at a tutorial (I don't recall where) on using an external EEPROM chip in which delay was used.

A similar question was posted today on the Italian board: http://arduino.cc/forum/index.php/topic,133618.0/topicseen.html and it referenced an earlier discussion (also in Italian): http://arduino.cc/forum/index.php/topic,88054.15.html

After reading those I once again had some doubts. EEPROM.write clearly blocks following EEPROM.write commands for the 3.4 or so milliseconds needed, but is it globally blocking (like delay)? Not wanting to immerse myself in Arduino source or ATmega documentation, I decided to just test this. I modified a sketch posted in today's Italian thread. This sketch calls EEPROM.write 256 times, and immediately after each EEPROM.write it calls a bit of do-nothing real math. Commenting out the EEPROM.write call, or the calcSQRT line one finds that:

(1) the 256 successive EEPROM calls alone took (run on a NANO 3) 868 milliseconds; 3.4 milliseconds per write.
(2) 256 successive calls to the calcSQRT function took 125 milliseconds.
(3) 256 EEPROM.write calls with a call to calcSQRT after each of these also took 868 milliseconds. In other words, EEPROM.write is NOT blocking; 1000 sqrt calculations within each 3.4 millisecond delay didn't add any time to the total.

For my purposes, this is perfect behavior.

Here's the sketch in case you want to try it yourself.

#include "EEPROM.h"

double A = 10.0;
double B = 5;
unsigned long startTime = millis();
unsigned long endTime = millis();

void setup() {
  Serial.begin(19200);
}

void loop() {    
  testEeprom();
  while (1);
}

void testEeprom() {
  Serial.println("Avvio...");
  startTime = millis();
// comment out EEPROM.write or calcSQRT lines to get seperate times  
  for (int i = 0; i < 256; i++) {
      EEPROM.write(i, (byte)i);
      calcSQRT ();
  }
  endTime = millis();
  Serial.print (startTime, DEC);
  Serial.print (",    ");
  Serial.print (endTime, DEC);
  Serial.print (",    ");
  Serial.println(endTime - startTime, DEC);
}

void calcSQRT () {
   for (long j = 0; j < 1000; j++) {
       B = sqrt (A);
   }
}

// sqrt for loop only - 125 milliseconds
// EEPROM.write only - 868 milliseconds = 3.39 milliseconds per write
// both - 868 milliseconds = EEPROM.write is nonblocking
//    (except for writes themselves)

Ciao,
Lenny
(2)

but is it globally blocking (like delay)?

Yes and no.

Look at eeprom.h source code (additional comment on the second line is mine)

/** \ingroup avr_eeprom
    Write a byte \a __value to EEPROM address \a __p.
 */
static __inline__ void eeprom_write_byte (uint8_t *__p, uint8_t __value)
{
    do {} while (!eeprom_is_ready ());         // <<<<<<<<<<< delay()-like blocking busy wait

#if	defined(EEPM0) && defined(EEPM1)
    EECR = 0;		/* Set programming mode: erase and write.	*/
#elif	defined(EEPM0) || defined(EEPM1)
# warning "Unknown EECR register, eeprom_write_byte() has become outdated."
#endif

#if	E2END <= 0xFF
    EEARL = (unsigned)__p;
#else
    EEAR = (unsigned)__p;
#endif
    EEDR = __value;

    __asm__ __volatile__ (
        "/* START EEPROM WRITE CRITICAL SECTION */\n\t"
        "in	r0, %[__sreg]		\n\t"
        "cli				\n\t"
        "sbi	%[__eecr], %[__eemwe]	\n\t"
        "sbi	%[__eecr], %[__eewe]	\n\t"
        "out	%[__sreg], r0		\n\t"
        "/* END EEPROM WRITE CRITICAL SECTION */"
        :
        : [__eecr]  "i" (_SFR_IO_ADDR(EECR)),
          [__sreg]  "i" (_SFR_IO_ADDR(SREG)),
          [__eemwe] "i" (EEMWE),
          [__eewe]  "i" (EEWE)
        : "r0"
    );
}

Here's how I think it works...

A single EEPROM.write() call blocks only if there's a previous EEPROM.write() operation which is still not complete.
The act of starting an eeprom write operation is not blocking.

In your example, if you take out the sqrt() call, you just spend all of the 3.4 ms waiting for the eeprom to become ready after the last write().
If you insert the sqrt() call after the EEPROM.write(), you spend part of those 3.4 ms computing the sqrt(), and the rest of them waiting for the eeprom to become ready. So the wall clock time of the for() cycle is roughly the same in both cases.

Thanks Tuxduino. That looks like a good explanation for this very nice behavior. Ciao, Lenny

LROBBINS:
Writing to EEPROM has a significant, several msec, latency. In the Arduino examples I've seen, Delay is used, but that stops everything. My question is: is it really necessary to stop the sketch or just avoid another write until the last EEPROM action is done?

Yes, several msec are required to program the EEPROM, but the library code waits for it to finish.

As a simple test, write a sketch and write all 0 bytes to your EEPROM and notice that it takes several seconds to run. If the library were not waiting (actually polling the MCU for "program complete"), your sketch would run in an instant.

the library code waits for it to finish.

It only waits for the previous eeprom write to finish. This is an important difference. If the program writes one byte to eeprom at a time, no more than once in a few msec (namely 3.4) then as far as the program itself is concerned, the EEPROM.write() call is immediate.