This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Redundant persistent storage

Lets say I have 200 bytes of data that I want to store in flash. So, I request a 200-byte block.

In order to store, the area has to be cleared first. As far as I understand the implementation limitations, pstorage_clear() has to clear the entire page even though it takes in a size argument.

I want to guard against power loss during a clear/store cycle that would corrupt the data, say the power was lost right after the clear. My first thought was to request two 200-byte blocks and sequentially store the same data to both blocks. I.e. clear/store to block one and once it finishes successfully, clear/store to block two. This would guarantee that one of the blocks always has valid data. Another way would be to alternate which block to use. But since the entire page is erased every time, this wont work.

So, my next thought was to request two separate pages by making the block size 1024 bytes, then in theory this should work, right? Though that would be huge waste of space.

Am I overthinking this?

Don't mind the required header data/crc checks (I've already implemented that).

Parents
  • Funnily, this is exaclty what I was thinking a few days ago: devzone.nordicsemi.com/.../

    The flash memory is broken up into 256 pages and the memory controller can only erase a full page from the memory, not individual cells. What you can do, however is to write individual words to this page, but only the memory cells that have been erased previously (means they've been toggeld to '1'). So as soon as a bit has been flipped to 0 in one page, you'll only be able to set it to 1 with a page erase. That means that you'll have to use two pages for storage because at some time your page will be filled completely and you'll have a timeframe where you need to clear this page. Of course you could use the other page only temporarily, but then, this doesn't really help you much if you do not need it for something else.

    How far is your implementation? If you are implementing a reliable storage class under the right licence I'd be interested in incorporating that into my open source mesh ;-)

    A further idea: If you want to store data often and you do not need much space, the best thing would be to first fill up a page with new revisions of that data and only then migrate the data to the second page.

    I am wondering if something like this would work:

    • Use the first bytes of the page to save the size of your required storage block:
    • Use the third byte e.g. and toggle the first bit to 0
    • On subsequent memory updates, toggle the second, third,... bit of that word to denote the position of your latest revision.

    I am not sure if that would work. Nordic says that you can only write to erase cells, but maybe it's possible to update bits that have not yet been set to 0?

  • My implementation is nowhere close, everything is just in the planning stage.

    Your idea of putting multiple revisions on a page is a good one that I didn't even think about - would surely help with wear leveling. I would not even need to keep a persistent counter. I can just loop through the two pages and figure out the 'latest' block at bootup. Assume you have two pages with eight 128-byte blocks each. Each block has a header/crc (or you could check against 0xFFFF since you're starting with 'erased' cells). Start storing at block0. When you store into block7 (last block of 1st page), clear page two. Continue storing into block8 and when you reach block15 (last block of 2nd page), clear page one. Now loop back to block0, etc. At bootup, iterate through the blocks and find the last valid block that's before an invalid block or is block15. Makes sense in my head...

Reply
  • My implementation is nowhere close, everything is just in the planning stage.

    Your idea of putting multiple revisions on a page is a good one that I didn't even think about - would surely help with wear leveling. I would not even need to keep a persistent counter. I can just loop through the two pages and figure out the 'latest' block at bootup. Assume you have two pages with eight 128-byte blocks each. Each block has a header/crc (or you could check against 0xFFFF since you're starting with 'erased' cells). Start storing at block0. When you store into block7 (last block of 1st page), clear page two. Continue storing into block8 and when you reach block15 (last block of 2nd page), clear page one. Now loop back to block0, etc. At bootup, iterate through the blocks and find the last valid block that's before an invalid block or is block15. Makes sense in my head...

Children
No Data
Related