4
\$\begingroup\$

I'm working on some code to manage a NAND flash and I need to erase single pages, given that the smallest erasable unit is a block, the only solution I could think of is to:

  1. Erase a reserved block
  2. Copy the entire block to the reserved one
  3. Erase the block
  4. Copy the reserved block back and skip that page.

While this works fine (haven't tested it much but it should work in theory) it's obviously very slow, I was wondering how flash controllers, for example in USB sticks, handle erasing a single page efficiently ?

\$\endgroup\$
3
  • \$\begingroup\$ Why do you need to erase the page rather than just marking it discarded in the metadata - or is this a secure deletion requirement? \$\endgroup\$
    – pjc50
    Feb 1, 2013 at 9:45
  • \$\begingroup\$ @pjc50 because I need to write the page, and I have to erase it first. \$\endgroup\$
    – mux
    Feb 1, 2013 at 9:47
  • \$\begingroup\$ Unnecessary erase and write cycles add wear to the flash - especially if you beat on one poor little reserved block all the time! PJC's answer is right - remapping will both spread the wear and eliminate unnecessary erase ops. \$\endgroup\$
    – user16324
    Feb 1, 2013 at 10:23

2 Answers 2

4
\$\begingroup\$

Have a look at this paper from Micron : use a mapping of logical block to physical block. Maintain a supply of pre-blanked pages and write into the next available one (or one chosen by your wear-levelling algorithm).

Eventually almost all your blocks are full, with some holes where pages within the block have been marked "deleted" but not actually erased. Then you do your algorithm: find block(s) with most deleted pages, copy to new location, erase old location, put old location on the "free" list.

This then raises the question of how to store the mapping data itself; one common approach is to extend the blocks slightly and put the mapping data on the block itself (as a "tag"). At bootup the controller can cache some or all of the mapping in RAM. Another approach is to use the NOR flash of the controller itself to store the mapping data.

\$\endgroup\$
2
\$\begingroup\$

As noted by pjc50, the general concept is that one avoids having a fixed relationship between logical addresses and physical addresses. Each time a request is made to write a page, simply use another page that's known to be blank, and make a note that the block is now stored at the new location.

Conceptually, this is nice and easy. Depending upon how many independently-mapped pages you have to deal with, it might be relatively easy in practice too (particularly if the number of mapped pages is small enough that you can afford to keep the entire table of actual page locations in RAM, and can afford the time to scan for all live pages and note their locations in the table). If the number of pages is large, however, it may be necessary to keep some tables in the flash which are organized in such fashion as to quickly find the particular physical block associated with a logical address. Trying to the hold locations of all the 512-byte pages in a 32GB flash, for example, would require about 256MB of memory, and even if one could process a million pages per second, loading that memory would take over a minute.

One could, in theory, have pages that hold the locations of 128 other pages, have pages that hold the location of 128 of those (indirectly holding the location of 16,384 pages), have pages that hold 128 of those (2,097,152 pages), and have a page that holds about 32 of those (which would manage 67,108,864 pages of data). To find a page page N, use bits 21-25 of the page number to select one of 32 page addresses in that last-mentioned page, then bits 14-20 to select one of 128 page addresses in that one, then bits 7-14 to select one of the 128 page addresses in that one, and finally bits 0-6 to select a page in that one. Voila--one now has the address of the page one needs.

Unfortunately, this approach means that reading each page of memory requires reading five pages from the flash chip, and even worse--writing each page of memory will require rewriting the page that holds its address, which will in turn require rewriting the page that holds that page's address, which will in turn require rewriting the page that holds that page's address, etc. Five pages total. Ick.

One may improve things considerably if one allows for the possibility that the data in the page maps need not be kept absolutely current if, every time a page gets replaced, the address of the new page is written in a previously-blank spot in the tag memory of the old page. Such allowance may degrade read performance since a pointer that's supposed to go to a page may point to an old version, which may point to another old version, etc. before finally reaching the right page. On the other hand, such an allowance may enormously improve write performance.

For example, even if one only allows a single extra level of redirection (meaning that if a page has been moved once without updating the parent pointer, the parent pointer must be updated on the next move), half the writes to a page would only require writing a page plus a tag, a quarter would require writing two pages plus a tag, an eight would require three pages plus a tag, etc. A pretty big improvement compared with every addressed page-write requiring that six pages get rewritten. If one allows up to three extra levels of indirection (every fourth write at a given level requires a parent update), then 3/4 of updates will be one write plus a tag, 3/16 will be two, 3/64 will be three, and only 1/64 will require more than that.

Note that while allowing multiple levels of redirection may slow down read performance, this may be more than offset by caching in RAM the addresses of recently-used blocks. If the contents of a cache entry are lost (whether because power was removed, or because it "expired") the next access to its page will be slower than usual, but use of tags for the updates would mean that correct data would still be found.

Designing good algorithms to manage a flash device is tricky. Although Micron seems to suggest having the entire chip be a unified "zone", I don't think that's quite practical. At minimum, there must be a means of locating the master indexing page. My recommendation would be that at any given time, the master indexing page be confined to one of a fairly small number of blocks. The locations of those blocks should be kept in one of a few super-master blocks which are devoted to that purpose. Every few hundred times the master indexing page has cycled through its allocated blocks, a new set of blocks should be chosen for it and the super-master blocks updated to reflect that. The number of super-master blocks would be small enough that the system could examine all of them on startup, and the number of master blocks listed in the active super-master block would be small enough that the system could examine all of those. Since there could be thousands of changes to the master block for each each to the super-master block, there should be no problem with the latter wearing out.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.