It is known that there are limited read and write cycles for EEPROM. Suppose I keep writing some important information in EEPROM and read it after power off to ON. Suppose at some point of time the EEPROM fails, how to know this condition? What are the checks I can put? Another question is checking one byte of EEPROM memory like writing known value and reading the same value is equivalent to checking the complete EEPROM memory say 4K.
There are various strategies to detect such failures.
A simple one works and even catches cases where your device gets powered off during a write:
Let's say you have a n byte block that you want to write:
[ xx xx xx xx xx xx ]
Instead of just writing that block you encapsulate it with two counters an a checksum (crc for example) like this:
[ counter1 xx xx xx xx xx xx checksum counter2]
Before you write data, first read out the old value of counter1:
a = eeprom_read_read (counter1_offset)
Now you overwrite the data with incremented counters and a checksum:
eeprom_write(counter1_offset, a+1); eeprom_write(data_offset, data); eeprom_write(checksum_offset, calc_checksum...); eeprom_write(counter2_offset, a+1);
If you want to access your data in the eeprom, always read the counters and the checksum along with the data. If counter1 differs from counter2 you likely had a power failure during the write operation. If the counters are the same but the checksum does not match you have a bad eeprom cell.
For years I have implemented the storage of small data sets in EEPROM (most often the serial type with a SPI or I2C interface) by storing two copies of the data. Each copy has a 16-bit CRC attached. The two copies are stored in the EEPROM sequentially such that if the storage update process is disrupted (power loss or accidental/unexpected reset) then only one of the two copies is affected.
At power up you read both copies of the data and check the CRCs. If the CRC of the first copy is OK then use that as the most recent data. If the CRC of the first copy is bad then resort to using the second copy if its CRC is OK. This will in almost all cases be the previously stored copy of the data set. If the CRC of the second data set is bad then you have to resort to setting the parameters in the data set all to default values.
Writing serial EEPROM can take a long time so you are more exposed to the possibility of disruption. Thus I take the above algorithm one step farther and if both copies of the data set have good CRC's and if the contents of both are the same I then keep a copy of the data set on RAM of the processor. At time of coming to update the data set when changes have been made I compare the new image against the stored copy in RAM byte by byte and only store those bytes that are actually changing. This significantly speeds up the process because typically only a few bytes at a time are changing when the data set is something like a parameter store.
If operating on serial EEPROM it is a good idea to also update the data carefully on the chip's internal "page size boundaries" because you can eliminate the typical 10msec write time for every byte by spreading that time across multiple bytes up to the page size. I recent years I have changed over to using the serial FRAM technology instead of serial EEPROMs because this technology does not have the the wear out property like EEPROM. FRAM also has the beautiful property in that writing and reading operate at full serial interface speed without needing to have that long 10msec write time penalty. Of course the parts cost more but this can be a huge advantage.
Three more things to consider regarding data set storage in EEPROM (or FRAM).
- It is a fact of life that embedded software is continually changing and parameters may be added to the data set and taken away. Since the data set stored is packed binary it may appear to have the correct CRC even though a different software version may have been used to write the parameters than the current updated software version that is reading out the parameter set. This problem is solved by adding a software version number to your code and storing that number in the data set along with the other parameters. At time of reading in the data the stored version number is compared with the current software version number. If different then the software knows to apply defaults to all the data set members to create a fresh and valid data set rather than use the faulty data.
- It is a wise idea to compare parameters read from a stored data set against an expected set of criteria. For numerical data types check the range of each value to make sure they are good. For strings check the lengths and that stored string characters are each in range of the code set being used. If some parameters are invalid it is wise to declare the dataset read as invalid and apply defaults to everything.
- It can be a good idea to keep one parameter in the data set that counts the number of times that one or the other of the data set copies reads out with a CRC error. If this number rises to a certain level you will want to alert the user that the EEPROM may be wearing out and needs replacement. Alternatively you can arrange to move the data set storage to another part of the EEPROM so that you start on a new unused set of cells. Note that FRAM does not need this since it does not wear out the same way as EEPROM. Also if you avoid writing to the EEPROM too often, say like limiting writes to once in 15 minutes or so then the EEPROM lifetime specs will allow you to use the storage device for 15 to 20 years without worry of having to worry about the wear out phenomenon. Most electronic devices are not applicable after that number of years anyway.