I have an application where I need to store an incrementing number in a non-volatile memory. Basically an odometer that keeps track of usage, and persists through power cycles.
I know I can write bytes to EEPROM and later read them. To increment the counter, I could simply read the value from EEPROM, add one to it, and write it back to EEPROM. This would all be fine, except I want to be able to exceed the rated 100,000 erase cycles of the EEPROM. So effectively I'm looking to implement a type of wear-leveling. To be most effective (least chance of any bits failing), I need to understand the deeper functionality of how Arduino writes to the EEPROM.
If I write a single byte to EEPROM, will it only erase and write that specific byte, or does it erase and rewrite a larger section? I assume only one byte.
Does reading from EEPROM have any effect on the longevity of the EEPROM? I assume not.
As I understand, an erased EEPROM byte will have a value of 0xFF (all bits set). Starting with a cleared byte, if I write the value 0xFE to the byte, will it simply write 0 to the least significant bit? Or will it erase the byte (set to 0xFF) and then write the bit to 0? Now what if I want to change the value from 0xFE to 0xF0? Will it erase (0xFF) and then set the four bits 0 (0xF0)? Or will it simply set the three other bits to 0? What if I then want to set the value to 0xF3? Will it erase the whole byte (setting it all back to 0xFF) and then set bits 2 and 3 to 0 (0xF3)?
I'm trying to determine how to achieve maximum lifespan (highest reliability) of my counter. Assuming the byte is only being erased when it needs to set a bit back to 1, I think I could have a series of 32 bytes in EEPROM, with each bit being set to 0 sequentially until all 256 bits are set 0, at which point it could overflow (probably into a 24-bit counter stored in three bytes) and erase all 32 bytes back to 0xFF. This would give me a 32 bit counter, that should be good for at least 25 million increments (256 x 100,000 cycles = 25.4M). The 32 bytes representing the 8 least significant bits of the counter would look something like this (abbreviated to show only 2 bytes for the sake of space):
1111 1111 1111 1111
1111 1111 1111 1110
1111 1111 1111 1100
1111 1111 1111 1000
1111 1111 1111 0000
1111 1111 1110 0000
1111 1111 1100 0000
1111 1111 1000 0000
1111 1111 0000 0000
1111 1110 0000 0000
1111 1100 0000 0000
1111 1000 0000 0000
1111 0000 0000 0000
1110 0000 0000 0000
1100 0000 0000 0000
1000 0000 0000 0000
0000 0000 0000 0000
Basically with each increment a single bit would be written (set to 0). Across 32 bytes (256 bits), that would represent an 8 bit value (actually 8-bit plus 1 I think, so 0-256 theoretically, or even slightly more by erasing 1 byte at a time; maybe about 0-287).
Side question: At the gate level, is there an advantage/disadvantage to bits being in a 0 vs. 1 state when issuing an erase to the byte? Would it be less wearing on the gate to first write all 0 before erasing all the bits to 1? To prevent "over-exposure" as it were, of clearing a bit already set to 1? Or would it be less wearing on the gate to leave any 1s in their state, rather than writing to 0 and then erasing back to 1?