Wear leveling

dovoto
Posts: 27
Joined: Tue Apr 20, 2021 3:51 pm

Wear leveling

Postby dovoto » Wed Feb 23, 2022 6:05 pm

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 ?

ESP_Sprite
Posts: 9746
Joined: Thu Nov 26, 2015 4:08 am

Re: Wear leveling

Postby ESP_Sprite » Thu Feb 24, 2022 1:26 am

That is a valid approach.

vanBassum
Posts: 68
Joined: Sun Jan 17, 2021 11:59 am

Re: Wear leveling

Postby vanBassum » Thu Feb 24, 2022 1:58 pm

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.

ESP_Sprite
Posts: 9746
Joined: Thu Nov 26, 2015 4:08 am

Re: Wear leveling

Postby ESP_Sprite » Fri Feb 25, 2022 1:42 am

Either that, or assume that the 'least full' block is the last one.

vanBassum
Posts: 68
Joined: Sun Jan 17, 2021 11:59 am

Re: Wear leveling

Postby vanBassum » Fri Feb 25, 2022 8:02 am

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.

Who is online

Users browsing this forum: No registered users and 98 guests