The Controller Command API must be implemented by a device-specific part of a NAND controller. The Controller Command API is specified in include file cyg/io/flash_nand_ctl_cmd.h. It essentially consists of a function dispatch table with pointers to device-specific functions.
struct CYG_NAND_CTL_FUNS { int (*init)(cyg_nand_ctl_t *ctl); /** invoked from cyg_nand_ctl_chip_select() */ int (*chip_select)(cyg_nand_ctl_t *ctl, int chip, int on); int (*cmd)(cyg_nand_ctl_t *ctl, cyg_uint8 cmd); /** writes the appropriate bytes of (col, page); col in words */ int (*page_addr)(cyg_nand_ctl_t *ctl, size_t column, size_t page); /** writes at most 4 bytes, either col (words) or page */ int (*addr)(cyg_nand_ctl_t *ctl, cyg_uint32 addr, size_t bytes); int (*data_write)(cyg_nand_ctl_t *ctl, const void *data, size_t bytes, cyg_uint8 *device_ecc); /** read a byte at a time, even with x16 chips. Some commands * require this. */ int (*data_read_8)(cyg_nand_ctl_t *ctl, void *data, size_t len); int (*data_read)(cyg_nand_ctl_t *ctl, void *data, size_t bytes, cyg_uint8 *device_ecc); /** Wait until RnB (a.k.a. SR[6]) has had a rising flank */ int (*await_ready)(cyg_nand_ctl_t *ctl); int (*ecc_calc)(cyg_nand_ctl_t *ctl, const cyg_uint8 *data, cyg_uint8 *ecc); int (*ecc_repair)(cyg_nand_ctl_t *ctl, cyg_uint8 *data, cyg_uint8 *stored_ecc, cyg_uint8 *calc_ecc); }; |
The init()
function must initialize the controller.
Besides doing the physical initialization, it must set the
info.flags
field of the device driver to indicate
whether the device has hardware ECC support.
A controller can be used to manage multiple chips. This chip is not a
parameter of the functions; the chip is explicitly (de)selected by the ANC
library with cyg_nand_ctl_chip_select(ctl, chipno, on/off)
calls around a group of calls to the controller. If a chip is selected,
the Command API function chip_select()
is invoked. It
should manipulate the nCE lines to physically (de)select the chip. As
a side effect, the controller common library sets the field
controller->current_chip
of the controller device
struct to point to the currently selected chip.
The function cmd()
has the controller write a (wire)
command.
There are two functions to have the controller write an address. Function
page_addr()
takes a column address (in words) and
a row address, and writes the address (column, row)
in the format that is specified by the chip. The number of bytes written may
exceed 4. Function addr()
services those commands that
require a column or a row address only, by having the controller write at most
4 bytes.
Functions data_write()
and
data_read()
have the controller program/read data on
the nand chip. These functions program/read their data a word at a time,
so for x16 chips, the implementation must perform one program/read cycle
per two bytes. If the controller supports hardware ECC calculation, the
implementation of these functions should also fill out the ECC bytes that are
calculated by the controller in argument device_ecc
.
The expectation is that there are 3 ECC bytes per 256 bytes of data. Whether
ECC calculation is done in hardware by the controller or in software, the
controller common library applies ECC correction to data read by invoking
functions ecc_repair()
and
ecc_calc()
.
There is another function to read data from the controller. Some commands are
specified to use only 8 bits of the chip's data bus, even in the case of x16
chips. For those commands, data_read_8()
is invoked by the
controller common library. Note that those commands never read application
data, so ECC handling is unnecessary.
The wire specification uses a rising flank of the nR/B wire as a signal that
an operation has completed. Function await_ready()
must
be implemented to return after occurrence of a rising flank (or timeout).
Hardware NFCs often have a status bit that indicates occurrence of a rising
flank. If the NFC is implemented through GPIOs, the safe way to monitor that
wire is to attach an interrupt handler to it that fires on a rising flank,
then performs condition synchronization with the implementation of
await_ready()
.
Functions ecc_calc()
and ecc_repair()
are invoked by the controller common library to perform ECC calculation and
repair respectively. They may be set to one of the bundled ECC functions, see
below. If the controller has ECC hardware, ecc_calc()
is
only invoked for debugging or verification. If the ECC calculation by the
controller hardware is incompatible with the bundled ECC functions, (at least)
ecc_repair()
must be implemented to match the hardware
functionality.
An example implementation of what the cmd()
function in
terms of GPIO pins might look like:
static int nfc_gpio_cmd(cyg_nand_ctl_t *ctl, cyg_uint8 cmd) { time t_start; cyg_gpio_set(GPIO_nCLE, 1); *reg_DATA = cmd; /* the data bus is memory-mapped to reg_DATA */ cyg_gpio_set(GPIO_nWE, 1); t_start = current_time(); while (current_time() - t_start < ctl->current_chip->info.t_write_pulse) { /* await the write pulse width */ } cyg_gpio_set(GPIO_nWE, 0); cyg_gpio_set(GPIO_nCLE, 0); return CYG_NAND_ERR_OK; /* Success */ } |
The NAND Flash Controller library bundles two algorithms for ECC error detection/correction: the "Toshiba" algorithm and the "Samsung" algorithm. If ECC is enabled, application data that is written to the flash has its ECC calculated and then written to the spare area by the controller common library, according to the spare layout descriptor for the chip. Application data that is read from the chip has its ECC calculated and compared to the ECC in the spare area. If there is at most one bit error per 256 bytes, the data can be corrected.
The ECC functions are defined in file cyg/io/flash_nand_ctl_ecc.h:
/** * @param ctl controller * @param data 256 bytes of data * @param ecc 3 bytes of ECC for 256 bytes of data */ __externC int cyg_nand_ctl_ecc_toshiba_calc(cyg_nand_ctl_t *ctl, const cyg_uint8 *data, cyg_uint8 *ecc); /** * @param ctl controller * @param data 256 bytes of data * @param ecc 3 bytes of ECC for 256 bytes of data */ __externC int cyg_nand_ctl_ecc_toshiba_repair(cyg_nand_ctl_t *ctl, cyg_uint8 *data, cyg_uint8 *stored_ecc, cyg_uint8 *calc_ecc); /** * @param ctl controller * @param data 256 bytes of data * @param ecc 3 bytes of ECC for 256 bytes of data */ __externC int cyg_nand_ctl_ecc_samsung_calc(cyg_nand_ctl_t *ctl, const cyg_uint8 *data, cyg_uint8 *ecc); /** * @param ctl controller * @param data 256 bytes of data * @param ecc 3 bytes of ECC for 256 bytes of data */ __externC int cyg_nand_ctl_ecc_samsung_repair(cyg_nand_ctl_t *ctl, cyg_uint8 *data, cyg_uint8 *stored_ecc, cyg_uint8 *calc_ecc); |
Flash controllers can have hardware support for ECC calculation. While the data flows through their data path, ECC information is gathered. When the application data has been written or read, the calculated ECC values can be retrieved from the Flash controller. It is not unusual that the ECC generation can be configured to match one of the bundled ECC algorithms, so that a bundled repair function can be used.