UFFSファイルシステムとNandFlash


1.ハードウェアチップ駆動下位駆動関数では、特定のチップ特性に対して、上位UFFSシステム呼び出しに提供する6つの基礎関数を作成する必要がある.
ReadID()                    ID
EraseBlock()                
ReadPage()                  
ReadPageSpare()             
WritePage()                 
WritePageSpare()            

そして異なるチップに対して特定のnandチップのパラメータをまとめ、
    typedef struct SNandInitInfo
    {
        rt_uint16_t uNandID     ; /* Nand Chip ID */
        rt_uint16_t uNandNbBlocks   ;     
        rt_uint32_t   uNandBlockSize    ; 
        rt_uint16_t uNandSectorSize;       ; ( )
        rt_uint8_t  uNandSpareSize  ; 
        rt_uint8_t  uNandBusWidth   ; 
        rt_uint8_t  uNandBadOffset  ; 
        char           name[16]     ; /* Nand Name */
    } SNandInitInfo, *PSNandInitInfo;

nandプロファイルでは、複数のNandFlashの情報を含む構造を定義できます.他のモデルのNandFlashを移植すると、NandFlash_InitInfoでは対応する情報が見つかり、コードは基本的に修正されず、移植性が強い:nand.cでは、一般的なnandチップに関する情報が定義されています.
const struct SNandInitInfo NandFlash_InitInfo[] = {
        /*
        {0xecda, 0x800, 0x20000, 0x800, 0x40, 0x0,0x0, "K9F2G08U0M\0"},
        {0xecaa, 0x800, 0x20000, 0x800, 0x40, 0x0,0x0, "K9F2G08R0A\0"},
        */
        {0xec75, 0x800, 0x4000, 0x200, 0x10, 0x0,0x04, "k9f5608\0"}, /*add by misswhile*/
        {0xecf1, 0x400, 0x20000, 0x800, 0x40, 0x0,0x0, "K9F1G08U0M\0"}, /*add by misswhile*/
        {0xec76, 0x1000, 0x4000, 0x200, 0x10, 0x0,0x04, "K9F12808u0b\0"}, /*add by misswhile*/
        {0xeca5, 0x800, 0x4000, 0x200, 0x10, 0x0,0x0, "K9F1G08U0A\0"}, /*add by misswhile*/
        /*
        {0x20aa, 0x800, 0x20000, 0x800, 0x40, 0x0,0x0, "STMNAND02GR3B\0"},  
        {0x2caa, 0x800, 0x20000, 0x800, 0x40, 0x0,0x0, "MT29F2G08ABD\0"}, */
        {0,}
    };

2.チップを交換した後、変更するプロファイルが必要です.既存のハブプロジェクトでは、「nandflash-interface.c」というファイルが最下位のnandドライバと上位UFFSとの直接的な互換構成をしています.目的は、ドライバ層にリストされているチップにあります.どちらのチップもコードを変更せずに使用できます.
この層の動作構想:まず標準関数ReadID()を介してそのブロックnandのID番号を読み出す.ID番号でNandFlash_InitInfoで比較します.そして,このブロックnandの基礎情報を調べ,SNandInitInfoに記録した.
uffs初期化時にこれらの基礎情報をuffsに構成する
static void setup_flash_storage(struct uffs_StorageAttrSt *attr ,PSNandInitInfo info)
    {
        attr->page_data_size  = info->uNandSectorSize;//NAND_PAGE_DATA_SIZE;        /* page data size */
        attr->pages_per_block  = info->uNandBlockSize/info->uNandSectorSize;//NAND_PAGES_PER_BLOCK; /* pages per block */
        attr->spare_size = info->uNandSpareSize;//NAND_PAGE_SPARE_SIZE;         /* page spare size */
        attr->block_status_offs = 4;//info->uNandBadOffset;//4;             /* block status offset is 5th u8 in spare */
        attr->ecc_opt = UFFS_ECC_SOFT;              /* ecc option */
        //attr->layout_opt = UFFS_LAYOUT_UFFS;        /* let UFFS do the spare layout */    
        //attr->ecc_opt = UFFS_ECC_HW_AUTO;//UFFS_ECC_NONE;//UFFS_ECC_SOFT;              /* ecc option */
        attr->layout_opt = UFFS_LAYOUT_UFFS;//UFFS_LAYOUT_UFFS;        /* let UFFS do the spare layout */    
    }

さらにこの層では,読み書き関数も1層カプセル化する.異なるリーフサイズの読み書きを互換化することを目的としています.nandを具体的に読み書きすると、nandのリーフサイズに基づいて、比較的一致する関数が具体的に呼び出されます.(nandが書かれているページは2 kも512もあるので互換性のある処理が必要です)
static int nand_read_page(uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 *ecc,
                            u8 *spare, int spare_len)
    {
        u8 val = 0;
        int ret = UFFS_FLASH_NO_ERR;
        if (data && data_len > 0) {
            nand_read_page_data(dev, block, page, data, data_len, ecc);
        }

        if (spare && spare_len > 0) {
            nand_read_page_spare(dev,  block,  page, spare, 0, spare_len);
        }

        if (data == NULL && spare == NULL) {
            nand_read_page_spare(dev,  block,  page, &val, dev->attr->block_status_offs, 1);

            ret = (val == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK);
        }

        return ret;
    }

この層は最終的に上層UFFSの3つの関数に提供され,残りの関数は使用されなかった.
const  struct uffs_FlashOpsSt my_nand_driver_ops = {
        NULL,
        NULL,
        nand_read_page,        //ReadPageData
        NULL,                             //ReadPageSpareWithLayout
        nand_write_page,       //WritePageData
        NULL,
        NULL,                             //spi_isbad_block,    //IsBadBlock
        NULL,                             //MarkBadBlock
        nand_erase_block,      //EraseBlock
    };

他の関数は、一部のチップの高度な機能にインタフェースを提供するべきであり、例えば、一部のeccの検証はハードウェアで完了し、ソフトウェア計算を必要としない.