Multiple byte EEPROM write with respect to power down

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Haven't been here for a while, but have searched and can't find much....

 

So I'm updating an EEPROM variable in my Codevision CV-AVR code eg.

 

eeprom uint32_t x;
...
...
x++;

 

CV-AVR is clever in that it does read-before-write on EEPROM updates to avoid re-writing EEPROM locations with the same value and improve speed.

...but when say x is 65535, the increment gives 63536 and the low 3 bytes of the uint32_t change so 3 EEPROM bytes are updated.

 

My device has a on/off switch, so some day someone will turn it off and when the brownout eventually kicks in and puts the AVR in reset, the code will be somewhere in the middle of the EEPROM updates and the EEPROM will end up in an inconsistent state.

 

Is there a way of protecting from this?

 

TIA, Martin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If a new multi-byte value was corrupted, could your system use the old value?  I'm thinking that you could write new MB values into a separate data block and toggle between the two blocks.  Write all the new data and as the last action, set an EEPROM flag marking the new block as the active block.  Then, if anything prevents the full updating of the new block and setting of the active block flag, your code would read that the old block was still the active block.

 

Another option could be to write an EEPROM flag with a value indicating the beginning of a data update, and at the end of the update, set the flag to a value indicating the new data is valid.  If your code ever reads this flag as being in update-begin state, you know the update was never completed and you'd have to execute some corrupt data action.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm sure there are many ways around this, include the two below, which, of course be combned:

 

Depending upon the hardware, one can power the micro and the EEPROM through a diode into the V+ rail, and hang a big cap on the V+ rail.

Now when the power supply falls, the diode isolates the V+ rail from the power supply and other circuitry, and the cap powers the chip long enough for the EEPROM writes to take place.

One typically uses a pin to monitor the power supply, (before the diode), to see when one is losing power.

When the lost power signal interrupt fires, you immediately save the important data to the EEPROM.

 

Next, you can, of course write the identical data to several EEPROM locations.

If you write it to three locations, for example, on a good day, all three data values will match.

If one of the writes was trashed, then the data will differ between the three saved values.

 

Three copies is an interesting case, by the way.

One could update value one with new data, trash the second value, and have old data in the third value...

 

Having more savings of the identical data helps with this case.

Adding a CheckSum or CRC to validate the integrity of the stored data also helps, (a lot).

 

Obviously, the above additions increase the time the micro and the EEPROM need to remain powered post power failure, so life is full of trade offs!

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MartinM57 wrote:
My device has a on/off switch, so some day someone will turn it off and when the brownout eventually kicks in and puts the AVR in reset, the code will be somewhere in the middle of the EEPROM updates and the EEPROM will end up in an inconsistent state. Is there a way of protecting from this?

You want early warning of power loss.  You want to monitor as high up the power chain as practical.  When you detect impending power loss, you go into a shutdown mode.  You need to experiment to find "the number" -- how many EEPROM bytes can you save.  It is usually 100ms+ and some dozens of actual writes.

 

One description here: http://www.avrfreaks.net/comment... The thread has a lot of discussion on power monitoring, as well.

 

Another: http://www.avrfreaks.net/comment... See the end about "waiting to die" -- if a false trip you have to decide whether to resume, or force a reset.  I generally do the latter but not in all apps.

 

This thread http://www.avrfreaks.net/comment... perhaps isn't as totally on-topic for you as the first link above.  But still, follow the links about finding "the number"...

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Tue. Sep 26, 2017 - 04:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Perhaps you might detect when the input power is gone so you have some milliseconds before the brownout detector trips?

 

Perhaps you know when the eeprom update needs to take place and do it sometime when somebody won't be fiddling with the power switch?

 

Perhaps you could store multiple sets of parameters, each with a "complete" flag, setting the complete flag for a set after writing that set. Then always use the most recent set with the complete flag set?

274,207,281-1 The largest known Mersenne Prime

Measure twice, cry, go back to the hardware store

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

One description here: http://www.avrfreaks.net/comment... The thread has a lot of discussion on power monitoring, as well.

..yes, and I was on that thread as well, but I was less experienced than (I hope) I am now :)

 

I'd like to think i'm pretty much up on monitoring "high up the power supply chain" i.e. it's not a new thing to me, but I see two things amongst the above (very rapid - thanks!) replies

 

1. I have quite a few EEPROM slow/rarely moving variables that I use throughout the code, relying on the EEPROM aspect of them to make them still at their same values after a power cycle  - so "writing data to EEPROM in anticipation of a imminent power fail" or "having multiple copies of the data" isn't something that fits with the application design 

 

2. Say I used the Analog Comparator interrupt to detect a "soon to occur" power fail, and just go into a loop to stop more code running, unless I surround every potential EEPROM variable update with a CLI/SEI pair, the interrupt might still occur half way through the multi-byte EEPROM update of the uint32_t, resulting in a corrupt value 

 

EDIT: light bulb moment? At the end of my main loop when all EEPROM variables are "quiet" (a <10ms loop at last measurement, and no interrupt code uses EEPROM variables) I test the upstream supply/look at the analog comparator flags (will have to read up on them) and if going down/gone I just stop in a loop/do the WDR trick to protect from a transient supply interruption that quickly returns??? 

Last Edited: Tue. Sep 26, 2017 - 05:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Store  a validity cookie alongside the variable:

typedef struct {
    uint32_t x;
    uint8_t valid;
} eevars_t;

eeprom eevars_t ee_vars;

ee_vars.valid = 0;
ee_vars.x++;
ee_vars.valid = 0x5A;

Only make use of ee_vars.x later if ee_vars.valid == 0x5A. If the power fails during the ++ the valid byte won't get set active again.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Another option:

 

Don't have the power button actually switch the power - just use it as an input to the micro meaning, "start to shut down now, please"

 

(which is, of course, what the power button on your phone does)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How often does x++ execute anyway? You are only just going to get to bit 17 of your 32 bit variable when the bottom byte will have had its 100,000 writes

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For a "validity byte", I would use something like a checksum or CRC.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@awneil - interesting idea, I will consider that

@cliff - x++ is just an easily understood description of the issue. Of course I wouldn't count to several hundred thousand in an EEPROM variable (although I would probably be fine) - think something like an alarm clock where the alarm time is set randomly in a 24 hour period by the user but it's defined and stored as 1/10ths of seconds into the day (so 0 to 864,000). Don't ask why/offer alternative ideas please, as that's not exactly what it is either :) ..suffice to say, I do need uint32_t EEPROM variables

Last Edited: Tue. Sep 26, 2017 - 07:37 PM