The functions described below are declared in the header file cyg/io/nand_flash.h which users of the NAND Flash library should include.
The NAND Flash library needs to be initialized before other NAND Flash operations can be performed. There is a global initialization call. Then, the initialization of an ANC is a two-step process. In between, the application can configure some properties of the ANC.
typedef int cyg_nand_printf(const char *fmt, ...); __externC int cyg_nand_init(cyg_nand_printf *pf, void *(*alloc)(size_t size), void (*free)(void *ptr)); |
Global initalization for the NAND Flash module.
The parameter pf
is a pointer to a function
which is to be used for diagnostic output. Typically the function
diag_printf()
will be passed. Normally this
function is not used by the higher layer of the library unless
CYGSEM_IO_NAND_CHATTER is enabled. Passing a
NULL
is not recommended, even when
CYGSEM_IO_NAND_CHATTER is disabled. The lower layers of the library
may unconditionally call this function, especially when errors occur,
probably resulting in a more serious error/crash!
Parameters alloc
and free
must
be function pointers to a memory allocator. The NAND Flash library needs
to allocate memory for two types of use:
its internal BBT (Bad Block Table). The amount that is needed is: 2 bits per block of NAND chip. The number of blocks that should be counted is the physical number of blocks, not the abstract number of blocks used by the ANC, which can be very different;
a cyg_nand_err
per thread, to support thread-local
error reports.
The application can statically allocate a buffer and provide an
alloc()
function to hand out chunks from it, or it can
use C's standard malloc() and free(). The implementation must protect against
concurrent use.
The device driver chain for the ANC library and its underlying controller and chip libraries must be 'looked up' or mounted before they can be used. Looking up the ANC driver automatically initializes and mounts the NAND flash controllers and chips that are specified in the target CDL.
typedef struct CYG_NAND cyg_nand_t; __externC int cyg_nand_dev_lookup(cyg_uint32 devno, cyg_nand_t **nand); |
This provides the user with a pointer to the ANC nand
given its device number (usually 0, as specified in the target cdl).
The opaque pointer cyg_nand_t *nand
is used in all other
accesses to the ANC API. After this lookup, the ANC configuration can be
inspected and tuned.
typedef struct CYG_NAND_INFO { size_t page_size; /* bytes */ size_t spare_size; /* bytes per page */ size_t block_size; /* bytes */ int n_blocks; int max_programs_per_page; ... } cyg_nand_info_t; __externC const cyg_nand_info_t *cyg_nand_get_info(const cyg_nand_t *nand); |
cyg_nand_get_info()
returns the layout of the ANC. If the
ANC has not initialized successfully, NULL is returned.
The layout of the ANC must be used by a client application (e.g. a NAND Flash
filesystem) that is layered on top of the ANC.
nand_info->max_programs_per_page
reflects a
peculiarity of NAND flash. A page can be programmed only a (small) number of
times before it needs to be erased; then it can be programmed again.
Before the second initialization stage, some properties of the ANC can be configured. These are en/disabling of ECC generation, en/disabling of a Bad Block Table (BBT), and specification of the layout of the spare area. By default, ECC and BBT are enabled, and a suitable spare layout is chosen.
The eCos NAND flash implementation attempts to offer on-chip compatibility with the metadata used by the Linux NAND flash layer MTD. The parts that attempt to be compatible with MTD are:
the layout of the spare areas. The spare area of a page commonly has slots for a bad block marker, for ECC values, for data that is available to the application (like filesystem meta-data), and possibly more. These slots are scattered into the page's spare area according to a spare layout. MTD specifies a layout for different spare sizes;
the bad block table (BBT). At its first usage (by either MTD or the eCos NAND Flash library), a NAND chip is scanned for factory-bad blocks. This information is stored on-chip, with a recognizable (and hopefully completely distinctive) marker pattern in the spare area that belongs to the block/page for the BBT. The blocks that contain the BBT are marked unusable for ANC applications. Besides that, the Bad Block Table is transparent to users of the ANC API.
Suitable defaults that follow the MTD automatic layout are provided when an application has no need for a custom spare layout. If a custom spare layout is required, a scatter table for the placement of ECC bytes and application bytes must be provided.
typedef enum CYG_NAND_FLAGS { CYG_NAND_FLAGS_HAS_ECC = (0x1 << 0), CYG_NAND_FLAGS_HAS_BBT = (0x1 << 1), CYG_NAND_FLAGS_ECC_ERROR_ON_ERASED = (0x1 << 2), } cyg_nand_flags_t; /** * Spare area layouts that follow the MTD autoplacement schemes */ typedef struct CYG_NAND_SCATTER_ELT { size_t start; size_t size; } cyg_nand_scatter_elt_t; typedef struct CYG_NAND_CHIP_SCATTER { size_t size; const cyg_nand_scatter_elt_t *scatter; } cyg_nand_scatter_t; /** Utility function */ __externC size_t cyg_nand_scatter_size(const cyg_nand_scatter_t *scatter); typedef struct CYG_NAND_CHIP_SPARE_LAYOUT_T { cyg_nand_scatter_t ecc; cyg_nand_scatter_t user; int bad_block_index; size_t size; /* size of spare info */ size_t ecc_size; /* cache ECC size */ } cyg_nand_chip_spare_layout_t; typedef struct CYG_NAND_APP_INFO { /** Specify whether * - the NAND Flash library should calculate ECCs and attempt to * repair corrupted data * - the NAND Flash library should maintain a BBT */ cyg_nand_flags_t flags; /** Optionally set to a pointer to your custom spare layout. * By default, an MTD auto layout is chosen that fits the ANC spare * size. If this pointer is overwritten, no copy is made. The * application must ensure that the data it points to stays * alive. */ const cyg_nand_chip_spare_layout_t *spare_layout; } cyg_nand_app_info_t; __externC cyg_nand_app_info_t *cyg_nand_app_info(cyg_nand_t *nand); |
The interface here intends to allow the use of statically allocated
data structures. The ANC publishes a pointer to its internal structure
cyg_nand_app_info_t *app_info
. An application can
overwrite the fields of that structure. If
app_info->spare_layout
is overwritten, it must point
to a persistent structure: ANC does not make a copy of it.
__externC int cyg_nand_start(cyg_nand_t *nand); |
Blocks of NAND Flash can be erased using the following function:
__externC int cyg_nand_block_erase(cyg_nand_t *nand, size_t page); |
page
is a row address of a page in the block to be
erased.
It should be noted that NAND Flash devices are block-oriented when erasing. It
is not possible to erase a few bytes within a block, the whole block
will be erased.
Programming of the flash is achieved using the following function.
__externC int cyg_nand_page_program(cyg_nand_t *nand, const void *data, size_t column, size_t page, size_t len, const void *spare, size_t spare_len, int use_cache); |
data
is the application buffer to read data from.
(column, page)
is the address within the NAND device to
be programmed. column
is in bytes (even if the chips
under the ANC are of x16 organisation). len
is the
number of bytes to be program into the page. A program operation cannot
address more than one page at a time, so column + len
must not exceed the page size. spare
is the application buffer to read spare_len
bytes of spare information from. use_cache
is a
boolean that specifies whether this program operation will be immediately
followed by more programs. In that case, the ANC can use the CACHED_PROGRAM
optimization if its chips support that. data
and
spare
may be NULL
if no data
should be read from them.
__externC int cyg_nand_page_read(cyg_nand_t *nand, void *data, size_t column, size_t page, size_t len, void *spare, size_t spare_len, int use_cache); |
data
is the application buffer to read data into.
(column, page)
is the address within the NAND device.
column
is in bytes (even if the chips under the
ANC are of x16 organisation). len
is the number of
bytes to be read from the page. A read operation cannot address more than
one page at a time, so column + len
must not exceed
the page size. spare
is the application buffer
to read spare_len
bytes of spare information into.
use_cache
is a boolean that specifies whether this read
will be immediately followed by more reads. In that case, the ANC can use the
CACHED_READ optimization if its chips support that. data
and spare
may be NULL
if no
data should be read into them.
typedef enum CYG_NAND_BLOCK_STATE { CYG_NAND_BLOCK_STATE_GOOD = 0x00, CYG_NAND_BLOCK_STATE_WORN_BAD = 0x01, CYG_NAND_BLOCK_STATE_RESERVED_BAD = 0x02, CYG_NAND_BLOCK_STATE_FACTORY_BAD = 0x03, } cyg_nand_block_state_t; __externC int cyg_nand_block_query(cyg_nand_t *nand, size_t page, cyg_nand_block_state_t *state); |
Checks the BBT (Bad Block Table) if the block that containts this page is good, worn bad, reserved, or factory-bad. If no BBT is used, attempts to check the chip for factory-bad marks.