All of the functions described here are declared in the header file
<cyg/nand/nand.h>, which should be included
by all users of the NAND library.
Note: Most of the functions in the library are declared
as returning int. Unless otherwise stated,
all functions return 0 for success, or a negative eCos error code if
something went wrong.
NAND devices are identified to the library by name. In many cases
there will be only one, commonly named onboard,
but this flexibility allows for easy expansion later without cross-device
confusion.
Note: The naming of NAND devices is set up by the code that
instantiates their drivers. Normally this is done by the platform HAL
port.
__externC int cyg_nand_lookup(const char *devname, cyg_nand_device **dev_o);
On success, *dev_o will be set up to point to a
cyg_nand_device struct. On failure, it will not; a return
code of -ENOENT signifies that the requested device
name was not found.
Applications will hardly, if ever, need to access the
cyg_nand_device structs directly. The following members
and convenience macros are most likely to be of relevance:
struct _cyg_nand_device_t {
...
cyg_nand_printf pf; // Diagnostic printf-like function for this device to use. May be changed at runtime.
...
size_t page_bits; // log2 of no of regular bytes per page
size_t spare_per_page; // OOB area size in bytes
size_t block_page_bits; // log2 of no of pages per eraseblock
size_t blockcount_bits; // log2 of number of blocks
size_t chipsize_log; // log2 of total chip size in BYTES.
...
};
#define CYG_NAND_BYTES_PER_PAGE(dev) (1<<(dev)->page_bits)
#define CYG_NAND_SPARE_PER_PAGE(dev) ((dev)->spare_per_page)
#define CYG_NAND_PAGES_PER_BLOCK(dev) (1<<(dev)->block_page_bits)
#define CYG_NAND_BLOCKCOUNT(dev) (1<<(dev)->blockcount_bits)
#define CYG_NAND_PAGECOUNT(dev) (NAND_BLOCKCOUNT(dev) * NAND_PAGES_PER_BLOCK(dev))
#define CYG_NAND_CHIPSIZE(dev) (1<<(dev)->chipsize_log)
#define CYG_NAND_APPSPARE_PER_PAGE(dev) ((dev)->oob->app_size)
NAND devices are arranged as a series of pages
and eraseblocks. The eCos NAND library numbers
pages and eraseblocks sequentially, both starting at 0 and continuing
until the end of the chip. For example, eraseblock 0 might contain pages
0 through 63; eraseblock 1, pages 64 through 127; and so on.
Caution
This numbering scheme is independent of the device's
addressing scheme. Take care, particularly when erasing blocks; some
devices and some applications effectively express the location to erase as
a page number (or, in NAND-speak, as the row address
to erase from).
Warning
Most NAND chip manufacturers document restrictions on
the order in which pages may be written to their device. Typically,
individual pages within an eraseblock must be written in sequential
order starting from the first, and random-order writes are prohibited
or unspecified. The eCos NAND library does not attempt to police such
restrictions; if at all unsure, check the spec sheet for the part. You
have been warned!
NAND devices are widely considered to be arranged as one or
more partitions, and the eCos NAND library
supports this. However, there is no universal scheme for partition
sizes to be supplied to the driver, unlike hard drives which encode
a partition table into their first sector. Partition arrangements are
often implicitly hardcoded, such as by byte address within the device,
though they could be encoded in a "partition table", user-set, or even
variable under software control by some esoteric rules. Therefore, every
device driver is responsible for configuring its partition information
as appropriate for the device, and this might for example appear as CDL
options.
Tip: Be sure to read the notes associated with the device driver
to understand how partitions are set up; if no notes are provided,
look in its devinit code.
After a NAND device has been initialised, its device struct contains
a list of partitions. These are numbered from 0 and may go up to
CYGNUM_NAND_MAX_PARTITIONS-1. Before an
application can use the NAND device, it must obtain a partition
context (pointer) with the following call:
Every page on the NAND array has a small number of "spare" bytes
associated with it. These are used by the NAND library to store the
page's ECC; whatever is left over may be used by the application for
whatever purposes may suit it.
Every page has CYG_NAND_APPSPARE_PER_PAGE(dev)
bytes of spare area available to the application. (This amount is implicit
from the driver configuration and cannot change during the lifetime of
a device.)
Note: Application spare bytes are not subject to the ECC. When
reading the spare area data, you must be prepared to cope with the
consequences of the (unlikely) event of a bit drop-out or other
failure.
Reads a single page and its spare area. The data read from the chip
will be automatically ECC-checked and repaired if necessary. Parameters
are as follows:
ctx
The
partition that data is to be read from.
page
The page to be read, numbered from the start of the partition.. As a double-check, the library will refuse the
operation with -ENOENT if this address is not within
partition ctx.
Note: This was changed in application interface v2; earlier page
and block addresses were device-relative.
dest
Where to put the data. May be NULL, in which case the page data is not
read.
size
The maximum amount of data to read. (In any event, no more than a single
page will be read, but if your application knows it doesn't need the
whole page, you can place a cap here.)
spare
Where to store the application data read from the spare area. This may
be NULL if spare data is not required.
spare_size
The maximum number of bytes to read from the spare area. This will
not be more than CYG_NAND_APPSPARE_PER_PAGE(dev)
bytes.
An error response of -EIO means that a
multiple-bit I/O error has occurred in the page data, which the ECC
could not repair. The library stores the data read from the device in
*dest and *spare on a
best-effort basis; it should not be relied upon. The application should
take steps to salvage what it can and erase the block as soon as possible.
Writes a single page and its spare area. The ECC will be computed
and stored automatically. Parameters are as follows:
ctx
The
partition that data is to be written to.
page
The page to be written, numbered from the start of
the partition. As a double-check, the
library will refuse the operation with -ENOENT
if this address is not within partition ctx.
src
Where to read the data from. May be NULL, in which case the page data
is not written.
size
The amount of data to write. (In any event, no more than a single page
will be written.)
spare
Where to read the data to go into the spare area; it will automatically
be packed around the ECC as necessary. Again, this may be NULL if spare
data is not required.
spare_size
The number of bytes to write to the spare area. This should not be
larger than CYG_NAND_APPSPARE_PER_PAGE(dev); if it is,
only that many bytes will be stored.
An error response of -EIO means that
the page write failed. The application should copy out any data
it wishes to keep from the rest of the eraseblock, then call
cyg_nand_bbt_markbad() to put the block beyond use.
__externC int cyg_nand_erase_block(cyg_nand_partition *ctx, cyg_nand_block_addr blk);
ctx
The
partition that data is to be erased from.
blk
The block to be erased, numbered from the start of
the partition. As a double-check, the
library will refuse the operation with -ENOENT
if this address is not within partition ctx.
An error response of -EIO means that the
block erase failed. In this case, the library automatically marks the
block as bad, and the application need take no further action.
The following common error returns may be encountered when
manipulating the NAND array using the above functions:
-EIO
The operation could not be completed due to an I/O error. This may require
the application to take further action; check the details provided above
for the call you have just made.
-ENOENT
The page or block address was not valid for the given
partition.
-EINVAL
The page (block) address was (within) a block that is marked
bad.
To determine the status of an eraseblock, use
cyg_nand_bbt_query; this returns an enum from
cyg_nand_bbt_status_t or a negative eCos error code. All
blocks which return a non-0 enum value are considered inaccessible by
applications.
Occasionally, it is necessary for applications to mark a block
as bad. This most commonly happens when a write operation fails
(see the Section called Writing data above). To do this, call
cyg_nand_bbt_markbad; the return is 0 for success,
or a negative eCos error code. As with other calls, blocks
are numbered from 0 at the start of the partition, and internally
translated for the device as appropriate.
Both of these calls may foreseeably return
-ENOENT if the given block address was not valid,
or -EIO if something awful happened with the on-chip
bad block table.