真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

SylixOS下基于NUC970的NAND驅(qū)動(dòng)

開(kāi)發(fā)環(huán)境

  1. 開(kāi)發(fā)環(huán)境

    宿主機(jī): Windows7 64bits 系統(tǒng)

    創(chuàng)新互聯(lián)是專業(yè)的大余網(wǎng)站建設(shè)公司,大余接單;提供網(wǎng)站制作、網(wǎng)站設(shè)計(jì),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行大余網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!

    開(kāi)發(fā)板: 安米MDK972

    軟件環(huán)境: RealEvo-IDE3.0

    NAND Flash: S34ML02G100TF100

  2. S34ML02G100TF100芯片參數(shù)

  • Density:2 Gbit

  • Input / Output Bus Width: 8-bits

  • Page Size:2112 (2048 + 64) bytes; 64 bytes is spare area

  • Block Size: 64 Pages;128k + 4k bytes

  • Plane Size: 1024 Blocks per Plane;128M + 4M bytes

  • Device Size: 2 Planes per Device or 256 Mbyte

NAND控制器結(jié)構(gòu)

NUC970的NAND控制器包含在FMI中。FMI分為DMA單元和FMI單元。對(duì)于NAND,支持單一DMA通道和硬件ECC,如圖 2-1所示。

SylixOS下基于NUC970的NAND驅(qū)動(dòng)

圖 2-1   NUC970 NAND控制器

 

技術(shù)實(shí)現(xiàn)

  1. 驅(qū)動(dòng)框架

    SylixOS中NAND Flsh的驅(qū)動(dòng)框架如圖 3-1所示。NAND通用驅(qū)動(dòng)主要在fs/mtd/nand/nand_base.c中,該文件包含了NAND的通用操作。驅(qū)動(dòng)工程師需要在NAND通用驅(qū)動(dòng)的基礎(chǔ)上實(shí)現(xiàn)與硬件相關(guān)的驅(qū)動(dòng)層的結(jié)構(gòu)體(nand_chip),該結(jié)構(gòu)體包含了對(duì)具體硬件相關(guān)的控制和操作函數(shù),以及相關(guān)硬件參數(shù)和配置信息。MTD層與文件系統(tǒng),SylixOS已經(jīng)完全實(shí)現(xiàn),不需要驅(qū)動(dòng)工程師實(shí)現(xiàn)。

    SylixOS下基于NUC970的NAND驅(qū)動(dòng)

    圖 3-1   NAND驅(qū)動(dòng)框架

  2. 框架實(shí)現(xiàn)

    NAND驅(qū)動(dòng)需要完成NAND控制器、ECC的配置以及NAND的相關(guān)操作函數(shù)及文件系統(tǒng)掛載,如果使用硬件ECC一般自己定義OOB布局。NUC970驅(qū)動(dòng)實(shí)現(xiàn)的操作如程序清單 3-1所示。

    程序清單 3-1   NAND實(shí)現(xiàn)框架

        nandchipNand->cmd_ctrl        = hwControl;
        nandchipNand->cmdfunc         = nandCommand;
        nandchipNand->dev_ready       = devReady;
        nandchipNand->select_chip     = chipSelect;
        nandchipNand->read_byte       = nandReadByte;
        nandchipNand->write_buf       = nandWriteBuf;
        nandchipNand->read_buf        = nandReadBuf;
        nandchipNand->chip_delay      = 50;
        nandchipNand->ecc.mode        = NAND_ECC_HW_OOB_FIRST;
        nandchipNand->ecc.hwctl       = nandEnableHwEcc;
        nandchipNand->ecc.calculate   = nandCalculateEcc;
        nandchipNand->ecc.correct     = nandCorrectData;
        nandchipNand->ecc.write_page  = nandWritePageHwEcc;
        nandchipNand->ecc.read_page   = nandReadPageHwEccOobFirst;
        nandchipNand->ecc.read_oob    = nandReadoobHwEcc;
    nandchipNand->ecc.layout      = &__Gpnuc970nandoob;

     

  3. 控制器初始化

    控制器初始化主要實(shí)現(xiàn)了模塊時(shí)鐘使能、管腳復(fù)用、時(shí)序設(shè)置、片選、解除寫(xiě)保護(hù)、頁(yè)大小、軟件復(fù)位等操作。

  4. ECC配置

    ECC配置主要設(shè)置冗余區(qū)大小,保護(hù)前3字節(jié),自動(dòng)寫(xiě)校驗(yàn)值到NAND,設(shè)置算法等級(jí),ECC使能等操作。

  5. 函數(shù)cmd_ctrl

    該函數(shù)主要實(shí)現(xiàn)對(duì)ALE/CLE/nCE的控制,同時(shí)用來(lái)寫(xiě)命令和地址。

    程序清單 3-2  命令控制函數(shù)

     

    static VOID hwControl (struct mtd_info  *pMtd, INT  iCmd, UINT  uiCtrl)
    {
        struct nand_chip *pChip = pMtd->priv;
    
        if (uiCtrl & NAND_CTRL_CHANGE) {
            ULONG IO_ADDR_W = (ULONG)REG_NANDDATA;
    
            if ((uiCtrl & NAND_CLE)) {
                IO_ADDR_W = REG_NANDCMD;
            }
            if ((uiCtrl & NAND_ALE)) {
                IO_ADDR_W = REG_NANDADDR;
            }
    
            pChip->IO_ADDR_W = (VOID *)IO_ADDR_W;
        }
    
        if (iCmd != NAND_CMD_NONE) {
            writeb(iCmd, pChip->IO_ADDR_W);
        }
    }
  6. 函數(shù)cmdfunc

    該函數(shù)主要實(shí)現(xiàn)向芯片中寫(xiě)命令的功能,在系統(tǒng)提供的默認(rèn)函數(shù)中通過(guò)調(diào)用cmd_ctrl函數(shù)來(lái)實(shí)現(xiàn)具體寫(xiě)操作。由于NUC970的控制器需在最后一個(gè)地址周期手動(dòng)設(shè)置EOA位,無(wú)法使用默認(rèn)函數(shù),差異代碼如程序清單 3-3所示:

    程序清單 3-3   命令功能函數(shù)差異代碼

    writel((iColumn >> BUS_WIDTH) | NANDADDR_EOA, REG_NANDADDR);

     

  7. 函數(shù)dev_ready

    該函數(shù)主要用來(lái)獲得設(shè)備ready/busy引腳狀態(tài)。如果該函數(shù)指針設(shè)置為NULL無(wú)法獲得ready/busy引腳狀態(tài),則ready/busy信息需要通過(guò)讀取NAND芯片的狀態(tài)寄存器。代碼實(shí)現(xiàn)如程序清單 3-4所示。

    程序清單 3-4  獲得NAND狀態(tài)

        return ((readl(REG_NANDINTSTS) & NANDINTSTS_RB0_Status) ? 1 : 0);

     

  8. 函數(shù)read_byte

    該函數(shù)功能為從NAND芯片讀取一個(gè)字節(jié),代碼如程序清單 3-5所示。

    程序清單 3-5  從NAND讀一個(gè)字節(jié)

     

        return ((UCHAR)readl(REG_NANDDATA));

     

  9. 函數(shù)write_buf

    該函數(shù)功能為從一個(gè)緩沖區(qū)寫(xiě)數(shù)數(shù)據(jù)到NAND芯片。代碼實(shí)現(xiàn)如程序清單 3-6。

    程序清單 3-6  寫(xiě)緩沖區(qū)數(shù)據(jù)到NAND

     

        for (i = 0; i < iLen; i++) {
            writel(pucbuf[i], REG_NANDDATA);
        }

     

  10. 函數(shù)read_buf

    該函數(shù)功能為從NAND芯片讀數(shù)據(jù)到一個(gè)緩沖區(qū)。代碼實(shí)現(xiàn)如程序清單 3-7所示。

    程序清單 3-7  讀數(shù)據(jù)到緩沖區(qū)

     

        for (i = 0; i < iLen; i++) {
            writel(pucbuf[i], REG_NANDDATA);
        }

     

  11. 函數(shù)ecc.hwctl

    該函數(shù)用于控制硬件ECC發(fā)生器,只有在使用硬件ECC時(shí)實(shí)現(xiàn)。本例的硬件校驗(yàn)在傳輸中實(shí)現(xiàn),因此該函數(shù)為空實(shí)現(xiàn)。

  12. 函數(shù)ecc.calculate

    該函數(shù)用于ECC計(jì)算,或從ECC硬件中讀回。本例的硬件校驗(yàn)在傳輸中實(shí)現(xiàn),因此該函數(shù)為空實(shí)現(xiàn)。

  13. 函數(shù)ecc.correct

    該函數(shù)用于ECC校正。本例的硬件校驗(yàn)在傳輸中實(shí)現(xiàn),因此該函數(shù)為空實(shí)現(xiàn)。

  14. 函數(shù)ecc.write_page

    該函數(shù)主要實(shí)現(xiàn)帶ECC的寫(xiě)一頁(yè)數(shù)據(jù)到NAND芯片。在傳輸?shù)倪^(guò)程中,ECC電路會(huì)自動(dòng)計(jì)算ECC校驗(yàn)值,并存儲(chǔ)到控制器分配的寄存器組中。完成傳輸后寄存器組中的OOB數(shù)據(jù)會(huì)根據(jù)設(shè)置自動(dòng)寫(xiě)進(jìn)NAND芯片。實(shí)現(xiàn)流程如程序清單 3-8所示。

    程序清單 3-8  帶硬件ECC的寫(xiě)頁(yè)

    static INT nandWritePageHwEcc (struct mtd_info   *pMtd,
                                   struct nand_chip  *pChip,
                                   const UCHAR       *pucBuf,
                                   INT                iOobRequired)
    {
        UCHAR          *pucEccCalc   = pChip->buffers->ecccalc;
        UINT             uiEccBytes  = pChip->ecc.layout->eccbytes;
        register CHAR     *pcPtr     = (CHAR *)REG_NANDRA0;
    
        memset((VOID *)pcPtr, 0xFF, pMtd->oobsize);
        memcpy((VOID *)pcPtr, (VOID *)pChip->oob_poi,  pMtd->oobsize - pChip->ecc.total);
    
        nandDmaTransfer(pMtd, pucBuf, pMtd->writesize , 0x1);
    
        /*
         *  Copy parity code in SMRA to calc
         */
        memcpy((VOID *)pucEccCalc,
               (VOID *)(REG_NANDRA0 + (pMtd->oobsize - pChip->ecc.total)),
               pChip->ecc.total);
    
        /*
         *  Copy parity code in calc to oob_poi
         */
        memcpy((VOID *)(pChip->oob_poi + uiEccBytes),
                (VOID *)pucEccCalc,
                pChip->ecc.total);
    
        return 0;
    }

     

  15. 函數(shù)ecc.read_page

    該函數(shù)主要實(shí)現(xiàn)帶ECC校驗(yàn)的從NAND芯片讀出一頁(yè)數(shù)據(jù)。本例為硬件ECC,需要先讀出OOB區(qū)數(shù)據(jù)到控制器分配的寄存器組中。在數(shù)據(jù)傳輸?shù)倪^(guò)程中,ECC電路會(huì)計(jì)算ECC校驗(yàn)值,并與寄存器組中的值比較,檢查是否產(chǎn)生錯(cuò)誤,以及定位和計(jì)算校錯(cuò)值。若產(chǎn)生錯(cuò)誤,程序需要根據(jù)錯(cuò)誤位置和錯(cuò)誤值進(jìn)行校錯(cuò)。具體流程如程序清單 3-9所示:

    程序清單 3-9  帶ECC的讀頁(yè)

     

    static INT nandReadPageHwEccOobFirst (struct mtd_info   *pMtd,
                                          struct nand_chip  *pChip,
                                          UCHAR             *ucBuf,
                                          INT                iOobRequired,
                                          INT                iPage)
    {
        INT      iEccSize = pChip->ecc.size;
        CHAR    *pcPtr    = (CHAR *)REG_NANDRA0;
    
        /*
         *  At first, read the OOB area
         */
        nandCommand(pMtd, NAND_CMD_READOOB, 0, iPage);
        nandReadBuf(pMtd, pChip->oob_poi, pMtd->oobsize);
    
        /*
         *  Second, copy OOB data to SMRA for page read
         */
        memcpy((VOID *)pcPtr, (VOID *)pChip->oob_poi, pMtd->oobsize);
    
        /*
         *  Third, read data from nand
         */
        nandCommand(pMtd, NAND_CMD_READ0, 0, iPage);
        nandDmaTransfer(pMtd, ucBuf, iEccSize, 0x0);
    
        /*
         *  Fouth, restore OOB data from SMRA
         */
        memcpy((VOID *)pChip->oob_poi, (VOID *)pcPtr, pMtd->oobsize);
    
        return 0;
    }

     

  16. 函數(shù)ecc.read_oob

    該函數(shù)主要實(shí)現(xiàn)從芯片中讀取OOB數(shù)據(jù)。實(shí)現(xiàn)流程如程序清單 3-10所示。

    程序清單 3-10  帶硬件ECC的讀OOB區(qū)數(shù)據(jù)

     

    static INT nandReadoobHwEcc(struct mtd_info  *pMtd, struct nand_chip  *pChip, INT  iPage)
    {
        CHAR *cPtr = (char *)REG_NANDRA0;
    
        /*
         *  At first, read the OOB area
         */
        nandCommand(pMtd, NAND_CMD_READOOB, 0, iPage);
        nandReadBuf(pMtd, pChip->oob_poi, pMtd->oobsize);
    
        /*
         *  Second, copy OOB data to SMRA for page read
         */
        memcpy ((VOID *)cPtr, (VOID *)pChip->oob_poi, pMtd->oobsize);
    
        return 0;
    }

     

  17. ecc.layout

    nand_ecc為ECC布局控制結(jié)構(gòu)體。通過(guò)該結(jié)構(gòu)體配置OOB區(qū)中ECC的位數(shù)和位置,可用位數(shù)和空閑位數(shù)。本例通過(guò)調(diào)用程序清單 3-11代碼實(shí)現(xiàn)OOB區(qū)的布局控制。

    程序清單 3-11   OOB區(qū)布局

     

    static VOID oobTableLayout ( struct nand_ecclayout  *pNandOOBTbl, INT  iOobSize , INT  iEccBytes)
    {
        pNandOOBTbl->eccbytes     = iEccBytes;
    
        pNandOOBTbl->oobavail     = iOobSize - DEF_RESERVER_OOB_SIZE_FOR_MARKER - iEccBytes ;
    
        pNandOOBTbl->oobfree[0].offset = DEF_RESERVER_OOB_SIZE_FOR_MARKER;     /*  Bad block marker size    */
    
        pNandOOBTbl->oobfree[0].length = iOobSize - iEccBytes - pNandOOBTbl->oobfree[0].offset ;
    }

     

  18. 文件系統(tǒng)掛載

    在SylixOS下NAND Flash通常掛載YAFFS文件系統(tǒng),并分為n0和n1分區(qū),其中n0分區(qū)用作啟動(dòng)分區(qū),n1作為應(yīng)用分區(qū)。掛載流程如程序清單 3-12所示。

    程序清單 3-12  文件系統(tǒng)掛掛載

     

        yaffs_mtd_drv_install(&__GyaffsdevBootDev);
        yaffs_mtd_drv_install(&__GyaffsdevCommDev);
    
        yaffs_add_device(&__GyaffsdevBootDev);                              /* add to yaffs device table    */
        yaffs_add_device(&__GyaffsdevCommDev);                              /* add to yaffs device table    */
    
        yaffs_mount(cBootDevName);
        yaffs_mount(cCommDevName);

     

參考資料

無(wú)。


網(wǎng)頁(yè)題目:SylixOS下基于NUC970的NAND驅(qū)動(dòng)
網(wǎng)站URL:http://weahome.cn/article/pspjhc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部