Translation Layer Configuration

The configuration of the NAND translation layer (fs_dev_nand.*) must be done through two mechanisms. First, you need to specify driver-wide configuration options in the configuration file (fs_dev_nand_cfg.h). Then, you need to configure the device-specific options passed to the function FSDev_Open() through a structure pointer. You need to call FSDev_Open() for each device you want to access and provide a proper device-specific configuration for each of them.

Driver configuration file

The driver configuration file for the NAND translation layer is fs_dev_nand_cfg.h. A template for this file is located in the following path:

\Micrium\Software\uC-FS\Dev\NAND\Cfg\Template\

The driver configuration #defines available in the configuration file are listed below.

FS_NAND_CFG_AUTO_SYNC_EN

This #define determines if, for each operation on the device (i.e. each call to the device’s API), the metadata should be synchronized. Synchronizing at the end of each operation is safer; it ensures the device can be remounted and appear exactly as it should. Disabling automatic synchronization can result in a large write speed increase, as the metadata won't be committed automatically, unless triggered by the application. If a power down occurs between a device operation and a sync operation, the device will appear as it was in a prior state when remounted. Device synchronization can be forced with a call to FSDev_Sync().

Note that using large write buffers will reduce the metadata synchronization performance hit, as fewer calls to the device API will be needed.

FS_NAND_CFG_UPDATE_BLK_META_CACHE_EN

This #define determines if, for each update block, the metadata will be cached. Enabling this will allow searching for a specific updated sector through data in RAM instead of accessing the device, which would require additional read page operations.

More RAM will be consumed if this option is enabled, but write/read speed will be improved.

RAM usage =
    <Nbr update blks> x
    (log2(<Max associativity>) + log2(<Nbr secs per blk>)) /
    8 octets.

The result should be rounded up.

FS_NAND_CFG_DIRTY_MAP_CACHE_EN

This #define determines if the dirty blocks map will be cached. With this feature enabled, a copy of the dirty blocks map on the device is cached. It is possible then to determine if the state “dirty” of a block is committed on the device without the need to actually read the device.

With this feature enabled, overall write and read speed should be improved. Also, robustness will be improved for specific cases. However, more RAM will be consumed.

RAM usage =
    <Nbr of blks on device> / 8 octets

The result should be rounded up.

FS_NAND_CFG_UPDATE_BLK_TBL_SUBSET_SIZE

This #define controls the size of the subsets of sectors pointed by each entry of the update block tables. The value must be a power of 2 (or 0).

If, for example, the value is 4, each time a specific updated sector is requested, the NAND translation layer must search the sector in a group of four sectors. Thus, if the update block metadata cache (FS_NAND_CFG_UPDATE_BLK_META_CACHE_EN) is disabled, four sectors must be read from the device to find the requested sector. The four entries will instead be read from the cache, if it is enabled. If the value is set to 0, the table will be disabled completely, meaning that all sectors of the block might have to be read before the specified sector is found. If the value is 1, the table completely specifies the location of the sector, and thus no search must be performed. In that case, enabling the update block metadata cache will yield no performance benefit.

RAM usage =
    <Nbr update blks> x
    (log2(<Nbr secs per blk>) - log2(<Subset size>) x
    <Max associativity> /
    8 octets

The result should be rounded up.

FS_NAND_CFG_RSVD_AVAIL_BLK_CNT

This #define indicates the number of blocks in the available blocks table that are reserved for metadata block folding. Since this operation is critical and must be done before adding blocks to the available blocks table, the driver needs enough reserved blocks to make sure at least one of them is not bad so that the metadata can be folded successfully. When set to 3, probability of the metadata folding operation failing is almost null. This value is sufficient for most applications.

FS_NAND_CFG_MAX_RD_RETRIES

This #define indicates the maximum number of retries performed when a read operation fails. It is recommended by most manufacturers to retry reading a page if it fails, as successive read operations might be successful. This number should be at least set to 2 for smooth operation, but might be set higher to improve reliability. Please be aware that a high number of retries will reduce the response time of the system when it tries to read a defective sector.

FS_NAND_CFG_MAX_SUB_PCT

This #define indicates the maximum allowed number of sequential update blocks (SUB). This value is set as a percentage of the total number of update blocks. SUBs will improve the performance for large transactions on the file system (ex: copying multi-MB files). Small files or small iterative changes to large files are best handled by RUBs. It is important to note that the translation layer will automatically determine what type of update block is the best depending on the parameters of the transaction itself. This parameter is only to limit the number of update blocks that can be SUBs.

Advanced configuration OPTIONs

The following configuration #defines should be left at their default values. Advanced understanding of the wear-leveling and block abstraction algorithms is necessary to set these configurations.

FS_NAND_CFG_TH_PCT_MERGE_RUB_START_SUB

This #define indicates the minimum size (in sectors) of the write operation needed to create a sequential update block (SUB) when a random update block (RUB) already exists. SUBs offer a substantial gain in merge speed when a large quantity of sectors are written sequentially (within a single or multiple write operations). However, if many SUBs are created and merged early, the device will wear faster (less sectors written between block erase operations).

This threshold is set as a percentage (relative to the number of sectors per block).

Set higher than default for better overall wear leveling and lower than default for better overall write speed.

FS_NAND_CFG_TH_PCT_CONVERT_SUB_TO_RUB

This #define indicates the minimum size (in sectors) of free space needed in a sequential update block (SUB) to convert it to a random update block (RUB). RUBs have more flexible write rules, at the expense of a longer merge time. If the SUB’s usage is over the threshold, the SUB will be merged and a new RUB will be started, instead of performing the conversion from SUB to RUB.

This threshold is set as a percentage (relative to number of sectors per block).

Set higher than default for better overall write speed and lower than default for better overall wear leveling.

To take advantage of this threshold, it must be set higher than the value of FS_NAND_CFG_TH_PCT_PAD_SUB. Otherwise, this threshold won't have any effect.

FS_NAND_CFG_TH_PCT_PAD_SUB

This #define indicates the maximum size (in sectors) that can be skipped in a sequential update block (SUB). Since each sector of a SUB must be written at a single location (sector physical index == sector logical index), it is possible to allow small gaps in the sequence. Larger gaps are more flexible, and can improve the overall merge speed, at the cost of faster wear, since some sectors are left empty between erase operations.

This threshold is set as a percentage (relative to number of sectors per block).

Set higher than default for better overall write speed and lower than default for better overall wear leveling

FS_NAND_CFG_TH_PCT_MERGE_SUB

This #define indicates the maximum size (in sectors) of free space needed in a sequential update block (SUB) to merge it to allocate another update block. If the threshold is exceeded, a random update block (RUB) will be merged instead. This threshold must be set so that SUBs with a lot of free space are not merged. Merging SUBs early will generate additional wear.

This threshold is set as a percentage (relative to number of sectors per block).

FS_NAND_CFG_TH_SUB_MIN_IDLE_TO_FOLD

This #define indicates the minimum idle time (specified as the number of driver accesses since the last access that has written to the SUB) for a sequential update block (SUB) to be converted to a random update block (RUB). This threshold must be set so that “hot” SUBs are not converted to RUBs.

Device configuration

You must configure the NAND translation layer for each device you use in your project. This configuration is made through a structure of type FS_NAND_CFG. A pointer to this structure is then passed to the function FSDev_Open(). Each NAND device will need to be initialized by calling FSDev_Open() and passing it a unique structure pointer of the type FS_NAND_CFG.

Note that the FS_NAND_DfltCfg constant should be used to initialize the FS_NAND_CFG structure to default values. This will ensure all fields will automatically be set to sane default values.

Listing - NAND translation layer configuration structure
typedef  struct  fs_nand_cfg {
    void                *BSPPtr;                     (1)
    FS_NAND_CTRLR_API   *CtrlrPtr;                   (2)
    void                *CtrlrCfgPtr;                (3)
    FS_NAND_PART_API    *PartPtr;                    (4)
    void                *PartCfgPtr;                 (5)
    FS_SEC_SIZE          SecSize;                    (6)
    FS_NAND_BLK_QTY      BlkCnt;                     (7)
    FS_NAND_BLK_QTY      BlkIxFirst;                 (8)
    FS_NAND_UB_QTY       UB_CntMax;                  (9)
    CPU_INT08U           RUB_MaxAssoc;              (10)
    CPU_INT08U           AvailBlkTblEntryCntMax;    (11)
} FS_NAND_CFG;


(1) This field must be set to a pointer to the controller-specific BSP layer implementation’s API you want the controller layer to use (see Board Support Package). If you use a different controller layer implementation, that field might not be needed.

(2) This field must be set to a pointer to the controller layer implementation’s API you wish to use (see Controller Layer).

(3) This field must be set to a pointer to the configuration structure for the specified controller layer implementation.

(4) This field must be set to a pointer to the part layer implementation’s API you wish to use (see API structure type for generic controller extension)

(5) This field must be set to a pointer to the configuration structure specific to the chosen part layer implementation.

(6) This field must contain the sector size for the device (care must be taken when choosing sector size: see Performance Considerations). The value FS_NAND_CFG_DEFAULT instructs the translation layer to use the page size reported by the part layer as its sector size.

(7) This field must contain the number of blocks you want µC/FS to use. This can be useful if you want to reserve blocks for data to be used outside the file system (by a bootloader, for example). The value FS_NAND_CFG_DEFAULT instructs the translation layer to use the number of blocks reported by the part layer.

(8) This field must contain the index of the first block you want µC/FS to use. This can be useful if you want to reserve blocks for data to be used outside the file system (by a bootloader, for example).

(9) This field must be set to the maximum number of update blocks you want the NAND translation layer to use. A greater number can improve performance but will also reduce available space on the device and consume RAM. You are encouraged to experiment with different values to evaluate which one suits your application best.

(10) This field must be set to the maximum associativity of the random update blocks (RUB). The update blocks temporarily contain sectors from data blocks until they are merged (copied to respective data blocks). The associativity specifies the number of data blocks from which a single RUB can contain sectors. A high setting will usually lead to better overall write and read speeds and will reduce wear. However, a low setting will lower the time of execution of the worst-case write operation.

(11) This field must be set to the size of the available blocks table. Available blocks are ready to be erased and used as update or data blocks. The table must, at least, be large enough to contain the reserved available blocks (see FS_NAND_CFG_RSVD_AVAIL_BLK_CNT) and a few more for general operations. The value FS_NAND_CFG_DEFAULT instructs the translation layer to use 10 or (1 + FS_NAND_CFG_RSVD_AVAIL_BLK_CNT) entries, whichever is larger.