saving to EPPROM wear limit

So i understand that EEPROM memory will eventually wear out after enough writing. i have read that this happens around 100,000 writes.

i have also read about wear-leveling implemented in SD cards that extends there life.

wear leveling is basically writing to different spots on a rom everytime so specifac spots dont wear out.

so my question is...

would this technique of writing at different eeprom indexes every time also extend the life of arduino's epprom?

Yes. The write rating is for each cell of the EEPROM. So if, for example, you did wear leveling by rotating your writes between 10 different locations of EEPROM, you have now increased the maximum number of writes from 100,000 to 1,000,000.

This is a well-known technique so you will find some code demonstrating how it can be done with a little searching. I believe there is an app note from Atmel/Microchip on the subject.

Depending on your application, there are often many reasons to NOT write EEPROM as often as some programs do.

e.g. log record of timed operation ... write at the end of each timed sequence - not every second of operaation.

With a little analysis and addressing the underlying causes - often 100K writes is more than enough.

pert:
I believe there is an app note from Atmel/Microchip on the subject.

There is. It is incomplete (e.g. two-phase commit is not even mentioned) The described technique is unnecessarily complex and wasteful. But, it is a reasonable starting point.

thanks so much for the answer. i just didnt want to waste my coding if the technique wasnt relevant with arduino's eeprom.

anyways im sure there are more advanced libraries but i took a couple hours to write and test some functions myself if anyone is interested.

since 10 bytes is the most i will be using....
my code idea was to break down the eeprom in sections of 11. the first byte of every section represents if the section is the current one and the other 10 is my write space.

so the code scans the epprom at multilples of 11 looking for the current mark (which is simply a byte set to 1) and if writing moves the marker to the next section.

i used a byte array called "rom" that it saves and stores to.

here are my funtions i tested a couple times that seems to be working if anyone is interested.

if you change your size even smaller then 10 then hopefully my eeprom will last through the next ice age or so. LOL

please comment if anything i am doing wrong or anyway this could be improved.

byte rom [10];
int romsize = 10;

//skip cap should be equal to or less than EEPRROM.length()
unsigned int skipcap = 5000;


// find the current spot
unsigned int skipspot (){
  unsigned int spot = 0;
  unsigned int page = 0;
 
  while(page+romsize+1<skipcap){
    if(EEPROM[page]==1){spot=page;break;}
    page+=romsize+1;}
    return spot;
  }




//read ten bytes after the current spot into rom array
void skipread (){
  byte ret [romsize];
  unsigned int spot=skipspot();
  byte i = 0;
  while(i<romsize){
    rom[i]=EEPROM[spot+i+1];
   i++; }
  
  }


//move the spot and write rom array
  bool skipwrite(){
    bool good = true;
     unsigned int oldspot=skipspot();
     unsigned int spot = oldspot+romsize+1;
      if(spot+romsize+1>skipcap){spot=0;}
      
     byte i = 0;
    while(i<romsize){
    EEPROM[spot+i+1]=rom[i];
    i++; }

    //next loop is optional to confirm the write
     i = 0;
    while(i<romsize){
    if(EEPROM[spot+i+1]!=rom[i]){
      good=false;break;
      }
    i++; }
    if(good){
     EEPROM[spot]=1;
     EEPROM[oldspot]=0;}
     return good;
 }

The EEPROM[spot] cells are twice as likely to wear out as the rest of your pool.

EEPROM[spot] is set before the record has been written. A failure while writing the record leaves behind a corrupt record that is flagged as current.

[quote author=Coding Badly link=msg=4248545 date=1563685425]The described technique is unnecessarily complex and wasteful
[/quote]
I'm glad to hear that. I thought I was just dense to understand the reasons for their approach when I read it some years back. I remember thinking "hmm... I'd rather just roll my own than use that".

"coding badly" is correct. the spot markers are written exactly twice as often my data section when overwriting the old "spot" but in a 512k eeprom there would be about 46k sections. so after 46 thousand writes those indexes would be written exactly twice. so this is good enough for me. the only concern would be proccesing time to page through all those sections to find the spot. in reality, before this idea was posted as an official library, the spot should be looked up only once in setup. and possibly there should be a "cap" in place to limit the max amount of sections. cause really 46k writes before a re-write might be a little overkill at the cost of extra lookup time.

as far as "coding badly's" comment about missed reads of failing hardware. it is what it is. the only answer that i know of about responding to failed hardware is to back things up if they are important.

taterking:
as far as "coding badly's" comment about missed reads of failing hardware.

Your code has a nasty but trivial to fix bug. That is the essence of the second paragraph.

Can elaborate on how it is "unnecessarily complex and wasteful"? The only AppNote I know of from Atmel is the attached one, and its ring counter method was very simple for me to understand and implement.

taterking:
"coding badly" is correct. the spot markers are written exactly twice as often my data section when overwriting the old "spot" but in a 512k eeprom there would be about 46k sections. so after 46 thousand writes those indexes would be written exactly twice. so this is good enough for me. the only concern would be proccesing time to page through all those sections to find the spot. in reality, before this idea was posted as an official library, the spot should be looked up only once in setup. and possibly there should be a "cap" in place to limit the max amount of sections. cause really 46k writes before a re-write might be a little overkill at the cost of extra lookup time.

as far as "coding badly's" comment about missed reads of failing hardware. it is what it is. the only answer that i know of about responding to failed hardware is to back things up if they are important.

It's still an improper implementation of the technique, because it's unnecessarily halving the life of your EEPROM. Once the index bytes start to fail, the entire scheme falls apart. The attached application note describes a better way to use that first byte so that it is written to as often as all the others, instead of twice as often.

CB's point isn't as much about hardware failure. Consider the fact that you can't guarantee that the EEPROM will always be successfully written to. What happens if you lose power while writing your data? Only part of your data will have been written to the EEPROM, so it can't be considered a valid update. However, because you are writing the "current" marker first, your data is marked as valid before it actually becomes valid! That's the bug. If the write is interrupted part way though, then the "current" record is corrupted.

The fix is simple. Write the "current" marker last, after all of the data has been written to the new location. That way if the write is interrupted halfway through, the old data is still marked as current so your sketch will use that and ignore the corrupted record (and will overwrite it on the next write).

AVR101 - High Endurance EEPROM Storage.pdf (47.3 KB)

Jiggy-Ninja:
Can elaborate on how it is "unnecessarily complex and wasteful"?

Having two separate ring buffers is unnecessary.

Having two separate ring buffers requires more code.

The additional code wastes Flash.

(I remember them also including an index from Status Buffer to Parameter Buffer which would also be unnecessarily complex and wasteful. They do not. Thank you for the reminder.)

They also require initializing the EEPROM before it can be used. In which case their implementation is flawed. A flaw that introduces three problems.

thanks for the help everyone. writing the current index AFTER the data is written is a good idea and was a simple fix.

I have also included a data confirmation before the index is changed to safeguard against "bad" writes. just in case that your data is important.

I have updated my code above to include these two helpful suggestions!

this topic wouldn't be complete without jiggy-ningas link to a more standard algorithym which i'm sure is different than mine!!! I'm sure there are Librarys for this too that could also be more effective.

my intention was to simply avoid writing to the same few bytes everytime!!!
i just wanted something small as possible and easy for my sketch without importing any librarys or complex algorythms.
i will be using this on an attiny85.

thanks again everyone for the help and info!