Page 1 of 1

Wear leveling

Posted: Wed Feb 23, 2022 6:05 pm
by dovoto
I have a 64 bit value I need to write to flash every 15 minutes and I need to do this over a 15 year product lifetime. This value will never be zero or all FFs.

What is the best way to wear level?

My plan is to use the spi flash api, erase a block (say 64k) write sequentially for 1000 writes, then erase and repeat. Which should give me (with a nominal 100,000 write cycle lifetime) 100,000,000 writes (which at 15 minutes gives me like a 3000 year lifetime).

Is this a valid approach or am I missing something ?

Re: Wear leveling

Posted: Thu Feb 24, 2022 1:26 am
by ESP_Sprite
That is a valid approach.

Re: Wear leveling

Posted: Thu Feb 24, 2022 1:58 pm
by vanBassum
Also depends if you want to know the beginning and end of the circlebuffer. You may need to start each block with a few flags to indicate where you are in the buffer.

Re: Wear leveling

Posted: Fri Feb 25, 2022 1:42 am
by ESP_Sprite
Either that, or assume that the 'least full' block is the last one.

Re: Wear leveling

Posted: Fri Feb 25, 2022 8:02 am
by vanBassum
Although not likely to happen, but what if all blocks are completely full? What is the oldest one that should be discarded? Besides, you may want to store a read pointer to indicate if the logentry has been submitted to a server of some kind. I assume you want to copy this log to some database through a wifi connection? I didn't search, but doens't the ESP-IDF contain a NVS logging system? If not, I wouln't be supprised if you can find something that does this for you online.

Just an idea:
- A block is 4k
- An entry is 8bytes
- A block starts with a header containing a pointer to the next block. This would allow you to determine the first and last block. By only reading these pointers in the header.
- The header contains 2 bits for each entry stating whether the entry is empty and if its written to the server.
11 = Empty
01 = Written not read
00 = Written and read

Block: (4096 bytes per block)
- Header (128 bytes)
- List of entries (3968 bytes)

Block header
- Pointer = 2 bytes
- Entry status bits = 124 bytes (allows for 496 entries)
- 2 bytes unused.

Block list of entries
- 3968 / 8 = 496 entries

Yes this has some overhead, because of the status bits.
- The written bit isn't nessesary, you could simply search for the next entry containing only 0xFF. Altough an entry with only 0xFF wouldn't be possible.
- The read bit can also be omitted.
- I would leave the pointer in the header, this overhead is negligible of 1 entry per block.