BSP Development Guide - Generic Controller

If you use the generic controller layer implementation, a BSP is required so that it will work for a particular board, micro-controller or application. Other controller layer implementations might require a similar BSP layer.

The BSP must declare an instance of the BSP API type (FS_NAND_CTRLR_GEN_BSP_API) as a global variable within the source code. The API structure is an ordered list of function pointers used by the generic controller layer implementation. The BSP API type is shown in Listing - Example BSP API structure for generic controller.

An example of a BSP API structure definition is shown in the listing below:

Listing - Example BSP API structure for generic controller
const  FS_NAND_CTRLR_GEN_BSP_API  FS_NAND_BSP_Example = {
    Open,                                                  (1)
    Close,                                                 (2)
    ChipSelEn,                                             (3)
    ChipSelDis,                                            (4)
    CmdWr,                                                 (5)
    AddrWr,                                                (6)
    DataWr,                                                (7)
    DataRd,                                                (8)
    WaitWhileBusy                                          (9)
};


A proper BSP should implement all of these functions. The \Micrium\Software\uC-FS\Dev\NAND\BSP\Template\fs_dev_nand_ctrlr_gen_bsp.c file, which contains a definition of API structure along with empty functions, is provided as a template to implement your BSP.

Open/Close functions (1, 2)

The Open() and Close() functions will be called respectively by FSDev_Open() and FSDev_Close(). Typically, FSDev_Open() is called during initialization and FSDev_Close() is never called — closing a fixed device doesn’t make much sense. When implementing the Open() function of the BSP layer, you should add all necessary code for the hardware initialization. That might include setting up the memory controller general settings and timings for the bank associated with the NAND device, configuring the chip select and ready/busy through either the memory controller or GPIO, configuring the memory controller clock, configuring the memory controller I/O pins, etc. The Close() function is typically left empty.

Chip selection functions (3, 4)

The ChipSelEn() and ChipSelDis() are called (in pairs) each time the device must be accessed. In these functions, you should implement any chip selection mechanism needed.

If the bus and/or hardware is shared with more than one task, the chip selection functions should also implement proper locking. If the shared bus and/or hardware must be configured differently when used outside the NAND driver, the configuration changes must be done within the ChipSelEn() and ChipSelDis() functions.

Command write function (5)

The CmdWr() function must write cnt octets on the bus with the CLE (Command Latch Enable) pin asserted.

Address write function (6)

The AddrWr() function must write cnt octets on the bus with the ALE (Address Latch Enable) pin asserted.

Data write function (7)

The DataWr() function must write cnt octets on the bus with both ALE and CLE not asserted. Bus writes must be width bits wide.

Data Read function (8)

The DataRd() function must read cnt octets from the bus and store it, starting from the p_src address. The ALE and CLE signals must not be asserted. Bus reads must be width bits wide.

Wait while busy function (9)

This function should block until the ready pin of the NAND device is in the appropriate state. If for any reason this pin is not accessible, you should call the poll_fcnt() with the poll_fcnt_arg as argument. This poll function will verify if the NAND device is ready by polling the NAND device status instead. Once the poll function returns DEF_YES, the WaitWhileBusy() can return without setting an error code. If the time out limit is reached, the function should return with an error code set to FS_ERR_DEV_TIMEOUT.