Controller Layer Development Guide
To fully take advantage of advanced peripherals (for example, NAND flash controllers), you might decide to provide your own implementation of the controller layer. The controller layer is one level above the BSP layer. Its interface is more flexible, but is also more complex to implement. If you choose that route, it is strongly recommended to use the provided implementations as an example. Listing - Controller API type definition describes the API that must be implemented for the controller layer.
typedef struct fs_nand_ctrlr_api { void *(*Open) (FS_NAND_PART_API *p_part_api, void *p_bsp_api, void *p_ctrlr_cfg, FS_ERR *p_err); void (*Close) (void *p_ctrlr_data); FS_NAND_PART_DATA *(*PartDataGet) (void *p_ctrlr_data); FS_NAND_PG_SIZE (*Setup) (void *p_ctrlr_data, FS_NAND_PG_SIZE sec_size, FS_ERR *p_err); void (*SecRd) (void *p_ctrlr_data, void *p_dest, void *p_dest_oos, FS_SEC_NBR sec_ix_phy, FS_ERR *p_err); void (*OOSRdRaw) (void *p_ctrlr_data, void *p_dest_oos, FS_SEC_NBR sec_nbr_phy, FS_NAND_PG_SIZE offset, FS_NAND_PG_SIZE length, FS_ERR *p_err); void (*SpareRdRaw) (void *p_ctrlr_data, void *p_dest_oos, FS_SEC_QTY pg_nbr_phy, FS_NAND_PG_SIZE offset, FS_NAND_PG_SIZE length, FS_ERR *p_err); void (*SecWr) (void *p_ctrlr_data, void *p_src, void *p_src_spare, FS_SEC_NBR sec_nbr_phy, FS_ERR *p_err); void (*BlkErase) (void *p_ctrlr_data, CPU_INT32U blk_nbr_phy, FS_ERR *p_err); void (*IO_Ctrl) (void *p_ctrlr_data, CPU_INT08U cmd, void *p_buf, FS_ERR *p_err); } FS_NAND_CTRLR_API;
Open/Close functionsBefore implementing the following functions, it is important to understand the difference between out-of-sector (OOS) data and the spare area. In a NAND device, each page has a spare area, typically used to store metadata and error correction codes (ECC). The spare area also contains a factory defect mark and, optionally, reserved sections. In the implementation of the µC/FS NAND driver, the OOS data is metadata sent to the controller layer by the translation layer. It must be stored in the spare area, wit.hout overwriting the bad block mark and without writing to the reserved section. It must also be protected by ECC. The OOS data is only a part of what is inside the spare area. It doesn’t include the factory defect marks, the reserved sections and the ECC data. Also, if the sector size is not equal to the page size, the OOS data will be associated to a single sector, while the spare area will be associated to a single page. In that case, multiple OOS sections would be fit in a single spare area.
The Open()
and Close()
function will be called respectively by FSDev_Open()
and FSDev_Close()
. Typically, FSDev_Open()
is called during initialization and FSDev_Close()
is never called. When implementing the Open()
function of the controller layer, you should typically add all necessary code for the bus/controller initialization (or call the Open()
function of the BSP layer). You should also allocate the necessary memory and perform all the operations that need to be done a single time only, when opening the device. The Close()
function is typically left empty.
Part data get function
The PartDataGet()
function should return an instance of the type FS_NAND_PART_DATA
associated to a particular device.
Setup function
The Setup()
function is called a single time, after the Open()
function. It must perform the proper calculation to make sure that the out-of-sector data (OOS) and the error correction codes (ECC) can fit in the spare area.
Sector read function
The SectorRd()
function must copy the data found at the physical sector sec_ix_phy
into the p_dest
buffer. It must also copy the out-of-sector data (OOS - the section of the spare area, excluding ECC, bad block marks and unused sections) into the p_dest_oos
buffer. Before returning successfully, the function should check for errors and correct them, if needed (with ECC).
Out-Of-sector (OOS) raw read function
The OOSRdRaw()
function must copy len
octets from the offset
octet in the OOS of the sector sec_ix_phy
into the p_dest_oos
buffer. This function should not perform error correction.
Spare area raw read function
The SpareRdRaw()
function must copy len
octets from the offset
octet in the spare area of the page pg_ix_phy
into the p_dest_spare
buffer. This function should not perform error correction.
Sector write function
The SectorWr()
function must write the data found in the p_src
buffer into the physical sector sec_ix_phy
of the NAND device. It must also write the out-of-sector data (OOS - the section of the spare area, excluding ECC, bad block marks and unused sections) found in the p_src_oos
buffer into the spare area. It should also store error correction codes (ECC) in the spare area.
Block erase function
The BlkErase()
function should erase the block blk_ix_phy
of the device.
IO control function
The IO_Ctrl()
function body can be left empty. It was created to perform device or controller specific commands without the need of a custom API. It can simply return the FS_ERR_DEV_INVALID_IO_CTRL
error code.
Note that the ONFI part layer implementation makes use of the FS_DEV_IO_CTRL_NAND_PARAM_PG_RD
I/O control operation. In order to retain compatibility with the ONFI part layer implementation, your controller implementation must support that operation.