9 Dec 2013
Dhara is a small flash translation layer designed to be used in resource-constrained systems for managing NAND flash. It provides a mutable block interface with standard read and write operations. It has the following additional features:
Perfect wear-levelling: the erase count of any two blocks will differ by at most 1.
Trim: logical sectors can be deleted to improve performance if their content is not required.
trim()) of logical sectors are atomic. If the power fails, the state rolls back to the last synchronization point. Synchronization points occur at regular intervals, but can also be reached on demand.
Real-time performance: all operations, including startup, are O(log n) worst case in the size of the chip, if bad blocks are uniformly distributed.
The implementation makes minimal assumptions regarding the underlying NAND chip. It can be used with almost any chip available, and can take advantage of extra hardware features where available. In particular:
No OOB data is consumed. All available OOB bytes can be spent on ECC.
It can take advantage of internally buffered copy operations, if the NAND chip supports these.
It can make use of NAND chip's on-board ECC, if available. If software ECC is required, implementations of Hamming and BCH codes are provided in the source distribution (see the
It does not require partial page programmability. However, if the functionality is present, then it can be taken advantage of by presenting a smaller pseudo-page size by dividing the real page size by the number of allowed reprogram operations. The only restriction is that partial writes must contain complete ECC information.
It will take advantage of the ability to do partial reads if this is possible. Reads must be error checked and corrected (this can usually be done in units smaller than the page size).
The implementation consists of the files in the
dhara/ subdirectory, plus the NAND layer implementation, which you must provide. The top-level interface is the set of functions described in
map.h (see the comments in the header file for more details):
- init: initialize a map layer instance
- resume: scan the map and recover the saved state
- clear: delete all data
- capacity, size: obtain usage statistics
- find: obtain the physical location of a logical sector
- read: read a logical sector
- write: write a logical sector
- copy_page: copy a raw flash page to a logical sector
- copy_sector: copy one logical sector to another
- trim: remove a logical sector from the map
- sync: ensure that changes to the map are committed
- gc: manually trigger garbage collection
To provide the NAND layer, implement the set of functions described in
nand.h (see comments for details). In summary, you must provide the following operations:
- is_bad: determine whether a block is bad
- mark_bad: mark a NAND block as bad
- erase: erase a NAND block
- prog: program a NAND page, including ECC and checksums
- is_free: determine whether a page is erased (unprogrammed)
- read: read a (possibly partial) NAND page, and attempt ECC if necessary
- copy: copy one page to another, using internal buffers if possible
Check the datasheet for your chip for information on these operations. In most cases, the manufacturer will specify a preferred layout scheme for the ECC and bad block markers in the OOB region. Pay particular attention to the marker used for factory-marked bad blocks!
Note that bad blocks need only be queried one at a time. It's not necessary to maintain a bad-block table -- just the standard OOB marking scheme is fine, and preserves the performance guarantees of the map layer.
Also note that when implementing partial read, you must read enough of the page that you're able to apply ECC and check for uncorrectable errors. Uncorrectable errors must be detected in order for the data integrity guarantees to be valid. This may require the use of a checksum in addition to ECC. If this is done, ensure that the checksum bytes are also protected by ECC!
Implementations of two popular ECC mechanisms (Hamming and BCH) can be found in the
ecc/ subdirectory. Each implements ECC over variable-sized chunks (256 or 512 bytes are typical sizes). Multiple ECC chunks may be required per page.
Obtain the source from Github:
git clone https://github.com/dlbeer/dhara.git
Copyright (C) Daniel Beer 2013 <>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.