Extending EEPROM life

I'm working on some software using an UNO (atmega328p). I have a stage byte that can be 1 of 5 values (0-4) in my code and it will increase by 1 every 2.5 hours. If I lose power I need to ensure that on wake up the stage is the same as it was at the time of power loss, so each time the stage is updated I save it to EEPROM.

To ensure the EEPROM lasts as long as possible I want to write some code that uses more than a single byte which I continually erase and write to. I was wondering if there is any library to do this or if my idea below would work?

I currently don't need to use the EEPROM for anything else so to extend the EEPROM life I was going to section of 1 quarter of it (0-255 bytes) for saving this value. Each time I change the stage I will write 3 bytes to EEPROM which will be,

  • An index byte (used to shift addresses I write to)
  • A stage byte (the stage I need to store)
  • A count byte (the amount of times I have wrote the stage at the current index)

To begin with the index will be written to byte 0 in the EEPROM, the stage to byte 1 and the count to byte 2.

My plan is to allow the stage to be written to byte 1 250 times, then clear the count and shift the index to 3. This will in turn move the bytes that the stage and count are being written to to 4 and 5. I will do this until the index reaches the end of the 255 bytes and then return the index to 0. So in total I should be able to shift 85 times.

Each byte has 100,000 erase/write cycles so this means I can pass through bytes 0-255 400 times, writing the stage 250 times each pass. So instead of having 100K writes I would have about 8.5 million writes.

This is my first Idea and I realize there is also some waste in the way I do it. I haven't worked with EEPROM much and I was just hoping for some advice as I'm sure I could be going at this completely wrong.

So you're writing it once every 2.5 hours?

If you used a single byte, and rewrote it every time, that would mean 250,000 hours.

At approx 25 hrs per day, that's 10,000 days, or 30 years. So I feel like you may be solving a problem that doesn't exist.

Why not increase the bytes one by one and check which address you needed to update?

For example, you have 5 EEPROM bytes:
20 20 19 19 19
Next to increase is the third (address 2) so you know the setting now. Next update you make it
20 20 20 19 19
to index to 4 etc.

This way you only change 1 byte at a time. Aka you have 100k5 = 10 yotta cycles = 2,85 zetta years :smiley:

But indeed, with a single byte you already have 30 year.

Also posted at: https://arduino.stackexchange.com/q/48872 If you're going to do that then please be considerate enough to add links to the other places you cross posted. This will let us avoid wasting time due to duplicate effort and also help others who have the same questions and find your post to discover all the relevant information. When you post links please always use the chain links icon on the toolbar to make them clickable.

If you can afford an analog input pin, check the supply voltage before the regulator, and save the eeprom when you see it going down (or any other time you want).

This way, if you only save the eeprom when power is crashing or other time for ‘maintenance’ or critical event… the eeprom will live longer than your children,

This might help you, however (as stated in reply #1) IMO I don't see the interest:

http://www.digikey.kr/en/pdf/a/atmel/avr101-high-endurance-eeprom-storage

CyberOddity:
To ensure the EEPROM lasts as long as possible…

As DrAzzy said, the eeprom will last a lot longer than you could ever need.

BUT, if you insist, then how about this idea?

First, initialize all of eeprom to 0xFF (i.e. all erased). Then, have your code (when running properly and saving restart points) do this (pseudo code):

S = eeprom_size (2048, 4096, whatever your board has)
for (x = 0; x < S; x++) {
if eeprom_read == 0xFF {
break;
}
}
now, X has the address of the first unused location
eeprom_write (X, your_data);

To recover from a crash, do the same thing (find the first unused eeprom location) then back up one and grab that data (which is the last valid one you saved).

Hope this helps.

DrAzzy:
So you’re writing it once every 2.5 hours?

If you used a single byte, and rewrote it every time, that would mean 250,000 hours.

At approx 25 hrs per day, that’s 10,000 days, or 30 years. So I feel like you may be solving a problem that doesn’t exist.

This makes an assumption that may not be true. The 100,000 write cycles is the manufactures guarantee regarding how many times you can write. Now, if I was making EEPROM chips, or anything else, and was going to guarantee that it would last for 100,000 cycles, I would make damned sure that it would last at least twice, and more likely 10 times that long before I guaranteed any number.

The EEPROM isn’t really likely to up and die at 100,001 writes.

It is likely that your device will last 60 to 600 years, writing once every 2 and a half hours.

The AVR will not die when you power it with 5,6V (or 6,1V even) but for a good and stable design you're not going to take that bed. Same for write cycles, it will probably last at least 10 times as long but a good design doesn't take that risk and solves it.

but a good design doesn’t take that risk and solves it.

No. A good design evaluates the risk, and decides whether there is a need to address a problem, or not. If the risk is that there is a one in a million chance that 1000 people will die, then the risk needs to be addressed. If the risk is that there is a one in a million chance that a flea will die, then the flea might have an opinion about whether or not you should mitigate that risk, but I don’t expect you to.

True, but if he decides it should last the 30 year it's a must. And based on the assumptions he made in the first post I think that's the case. But that is something completely different then you said in reply #7. That's just extending the spec to, yeahh, after 100k cycles the change is still small so you could say it's not "one in a million chance that 1000 people will die" but it's probably "one in ten million chance that 1000 people will die" and that might be fine.

septillion: True, but if he decides it should last the 30 year it's a must. And based on the assumptions he made in the first post I think that's the case. But that is something completely different then you said in reply #7. That's just extending the spec to, yeahh, after 100k cycles the change is still small so you could say it's not "one in a million chance that 1000 people will die" but it's probably "one in ten million chance that 1000 people will die" and that might be fine.

If the Arduino is being used in a project where people might die, then it is the wrong hardware for the project, whether the chance is 1 in million or 1 in 10 million.

But, I understand your point. As you say, it's all about managing risk. My impression is that the risk of wearing out one cell in EEPROM, at the rate that OP is writing to it, in the amount of time that the project is likely to be used, is extremely small. Not very many projects running today are running the same way they were 30 years ago. Those that are are usually because it isn't worth the trouble to upgrade the process, because it isn't that important.

septillion: The AVR will not die when you power it with 5,6V (or 6,1V even) but for a good and stable design you're not going to take that bed. Same for write cycles, it will probably last at least 10 times as long but a good design doesn't take that risk and solves it.

A thing that I do..... whenever I write eeprom, I first get the value of OSCCAL, then set the register to zero, then write eeprom, then reset OSCCAL back to what it should be.

Since eeprom and flash writes are timed with the internal r/c oscillator, setting OSCCAL to zero "cooks" the memory a bit longer.

Don't know if this shortens the life of the cells, but I had good luck "overcooking" eeprom cells in Motorola 68HC11 parts...

May I ask what the benefit of cooking the cells longer is? Is it like sous-vide? :D

CyberOddity: To ensure the EEPROM lasts as long as possible I want to write some code...

Or, you could spend $6 then spend the time you save doing things that are much more interesting...

https://www.adafruit.com/product/1897

To ensure you know what you are up against: Reliably extended the life of non-volatile storage using wear leveling requires a two-phase commit (with a carefully crafted write order), two extra bytes for flags per record, two (or more) extra bytes for error detection per record, splitting erase from write, error detection (CRC), and N * (sizeof(record)+4) bytes of storage where N >= 3. Anything less will have a hole that prevents either failure recovery, failure detection, or both.

Last bit might be true but that's as true for the linked EEPROM... You just have more cycles which is easy to do on a AVR as well by sacrificing more bytes.

septillion:
May I ask what the benefit of cooking the cells longer is? Is it like sous-vide? :smiley:

Well, in my experience with the Motorola 68HC11, I consistently found that the factory recommended programming time of 10 milliseconds was too short (it resulted - sometimes - in incomplete programming… a few bits were still high that were supposed to be low) and that “cooking” the eeprom with 20 milliseconds resulted in 100% reliable programming.

And, thinking about it, programming a byte involved placing the bit pattern into the register, then enabling the “high voltage” to allow electrons to tunnel through the insulated gates of the individual cells. Once the charge had been transferred, I assume that no more programming current flows.

As an analogy, think of applying a voltage to a discharged capacitor. Initially, current will flow as the capacitor is charged, but ultimately the current flow will drop to zero (ignoring the real world factors such as leakage, etc). Leaving the voltage source connected to the capacitor for a longer period will not result in any change. However, remove the voltage source BEFORE the capacitor is fully charged and you end up with an unreliable programming (thinking of the capacitor as an EEPROM cell)…

I know that leaving the programming voltage on too long degrades the insulating layer and ultimately results in shortening the integrity (storage lifetime) of the eeprom data (indeed this is the wearout mechanism that causes eeprom to be rated for “X” number of programming cycles), but the effects are so small as to be non-existent.

Once years ago I took a “sacrificial” 68HC11 and wrote a small loop that erased a cell, then programmed it to 0x00, then erased it again ad-infinitum. I let it run for several months and when I couldn’t stand waiting any longer, I tested it. The eeprom location programmed fine (although I don’t know if it would STAY programmed for the factory specified 10 years)… :slight_smile:

krupski: Well, in my experience with the Motorola 68HC11, I consistently found that the factory recommended programming time of 10 milliseconds was too short (it resulted - sometimes - in incomplete programming... a few bits were still high that were supposed to be low)

Maybe your particular programming hardware was flawed.

aarg: Maybe your particular programming hardware was flawed.

There was no "hardware" (as in some kind of programming box). To program an EEPROM byte, this is what was done:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; erase eeprom byte
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ee.clr  pshb                            ;save b
        ldab    #eelat|byte|erase       ;eelatch, byte erase mode
        bsr     ee.main                 ;erase eeprom byte
        pulb                            ;restore b

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; program eeprom byte (data for byte is in ACCA)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ee.wrt  pshb                            ;save b
        ldab    #eelat                  ;eelatch, byte write mode
        bsr     ee.main                 ;write eeprom byte
        pulb                            ;restore b

        rts                             ;return

ee.main stab    pprog                   ;write control bits
        staa    0,x                     ;write data to ee latch
        orab    #eepgm                  ;set vpp bit
        stab    pprog                   ;turn on vpp charge pump (program ee)

        ldy     #(eclk/7)*20            ;double Motorola's spec for reliability
        dey                             ;[4~] count down
        bne     *-2                     ;[3~] do rest

        clrb                            ;all bits off
        stab    pprog                   ;set ee to normal mode

        rts                             ;return

The programming "high voltage" was generated on-chip with a charge pump and programming a byte was all done in software (no "programmer" involved).

Did anyone else report this problem? I had the EVB board which runs code from ROM, not EEPROM so I didn't test it, but I'm still surprised. I just never heard anything about it. I played with HC11 for several years, but it was a while back.