Pages: [1]   Go Down
Author Topic: EEPROM Compare Before Write  (Read 779 times)
0 Members and 1 Guest are viewing this topic.
Virginia, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have been playing around with a Microchip 24LC515 EEPROM and I found myself wondering if the chip would still perform an erase/write if the data being written were the same as the current contents of the memory.

Since the erase/write time is fairly significant compared to the communication time (I2C), I hypothesized that I could compare the erase/write times for data being the same and data being different and determine what was happening under the hood.

It turns out that the erase/write time is the same no matter what the data is.

Then I got to thinking, what if I read the contents, compared them to the write data, and only performed a write if the contents where different.

Advantages:
Writes to pages with identical data speed up
Unnecessary erase/write cycles are eliminated

Disadvantages:
Writes to pages with all but the last byte being identical (worst case) are about 40% slower

To give you a general idea of my testing here is my sketch:
Code:
#include <MyWire.h>
#include <M24XX515Eeprom.h>

M24XX515Eeprom eeprom;
uint16_t addr = 0;
uint8_t write_data[256];
uint8_t read_data[256];
uint32_t startTime;
uint32_t stopTime;
uint16_t count;

void setup()
{
  Serial.begin(115200);
  Serial.println("\n\n24LC515 EEPROM");
  Serial.println("Press any key to start test.");
  while(!Serial.available())
  {
     continue;
  }
 
  for (int i = 0; i < sizeof(write_data); i++)
  {
    write_data[i] = 255 - i;
  }
 
  Serial.print("Starting read...");
  startTime = micros();
  count = eeprom.read(addr, read_data, sizeof(read_data));
  stopTime = micros();
  Serial.println("done.");
 
  Serial.print(count, DEC);
  Serial.print(" bytes read in ");
  Serial.print((stopTime - startTime) / 1000, DEC);
  Serial.println(" ms");
 
  Serial.print("Starting verify...");
  startTime = micros();
  for (count = 0; count < sizeof(read_data); count++)
  {
    if (read_data[count] != write_data[count])
    {
      break;
    }
  }
  stopTime = micros();
  Serial.println("done.");
 
  Serial.print(count, DEC);
  Serial.print(" bytes verified in ");
  Serial.print((stopTime - startTime), DEC);
  Serial.println(" us"); 
 
  Serial.print("Starting write...");
  startTime = micros();
  count = eeprom.write(addr, write_data, sizeof(write_data));
  stopTime = micros();
  Serial.println("done.");
 
  Serial.print(count, DEC);
  Serial.print(" bytes written in ");
  Serial.print((stopTime - startTime) / 1000, DEC);
  Serial.println(" ms");
}

void loop()
{
}

And here is the serial output:
Code:
24LC515 EEPROM
Starting read...done.
256 bytes read in 33 ms
Starting verify...done.
256 bytes verified in 332 us
Starting write...done.
256 bytes written in 88 ms

What do you think?  Advantages outweigh disadvantages?

Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12465
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


This idea has been proposed earlier on the forum, and is in fact a good idea but has some unwanted effects too as you mention. Less writes also increases the guaranteed lifetime of an EEPROM.

But, (there is always a but) you shuld analyze your applications behaviour.

This optimization only make sense if you expect data to be the same for a certain percentage, otherwise it will (worst case) always do an unneccesary read.
You can make a formula of the total time needed depending on the % sameness, and check if the read before write outperforms the write-always.

If you have RAM to spare you can cache the EEPROM in RAM:

Code:
byte cache[256]; // assume a small EEPROM

byte eepromRead(byte address)
{
   return cache[address];
}

byte eepromWrite(byte address, byte value)
{
  if (eepromRead(address) != value)
  {
     cache[address] = value;
     eepromWriteForREal(address, value);
  }
}

Don't forget to fill the cache during setup(); 

Optionally you can cache a part of the EEPROM, you need a page variable, some statistics to determine the best page to cache, or just cache the last one. In short a nice EEPROM caching class ==> could be a nice project on its own.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Virginia, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the response robtillaart.

That definitely gives me a lot to think about.  I don't know why but I hadn't thought of it in the since of caching until you said it but that is exactly what I was describing.

A caching EEPROM library may be coming in the future...
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12465
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
A caching EEPROM library may be coming in the future...
Sounds good!
keep us informed.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Jump to: