91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SylixOS下基于NUC970的NAND驅動

發布時間:2020-04-05 08:03:16 來源:網絡 閱讀:986 作者:huikai309 欄目:系統運維

開發環境

  1. 開發環境

    宿主機: Windows7 64bits 系統

    開發板: 安米MDK972

    軟件環境: RealEvo-IDE3.0

    NAND Flash: S34ML02G100TF100

  2. S34ML02G100TF100芯片參數

  • 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控制器結構

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

SylixOS下基于NUC970的NAND驅動

2-1   NUC970 NAND控制器

 

技術實現

  1. 驅動框架

    SylixOS中NAND Flsh的驅動框架如圖 3-1所示。NAND通用驅動主要在fs/mtd/nand/nand_base.c中,該文件包含了NAND的通用操作。驅動工程師需要在NAND通用驅動的基礎上實現與硬件相關的驅動層的結構體(nand_chip),該結構體包含了對具體硬件相關的控制和操作函數,以及相關硬件參數和配置信息。MTD層與文件系統,SylixOS已經完全實現,不需要驅動工程師實現。

    SylixOS下基于NUC970的NAND驅動

    3-1   NAND驅動框架

  2. 框架實現

    NAND驅動需要完成NAND控制器、ECC的配置以及NAND的相關操作函數及文件系統掛載,如果使用硬件ECC一般自己定義OOB布局。NUC970驅動實現的操作如程序清單 3-1所示。

    程序清單 3-1   NAND實現框架

        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. 控制器初始化

    控制器初始化主要實現了模塊時鐘使能、管腳復用、時序設置、片選、解除寫保護、頁大小、軟件復位等操作。

  4. ECC配置

    ECC配置主要設置冗余區大小,保護前3字節,自動寫校驗值到NAND,設置算法等級,ECC使能等操作。

  5. 函數cmd_ctrl

    該函數主要實現對ALE/CLE/nCE的控制,同時用來寫命令和地址。

    程序清單 3-2  命令控制函數

     

    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. 函數cmdfunc

    該函數主要實現向芯片中寫命令的功能,在系統提供的默認函數中通過調用cmd_ctrl函數來實現具體寫操作。由于NUC970的控制器需在最后一個地址周期手動設置EOA位,無法使用默認函數,差異代碼如程序清單 3-3所示:

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

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

     

  7. 函數dev_ready

    該函數主要用來獲得設備ready/busy引腳狀態。如果該函數指針設置為NULL無法獲得ready/busy引腳狀態,則ready/busy信息需要通過讀取NAND芯片的狀態寄存器。代碼實現如程序清單 3-4所示。

    程序清單 3-4  獲得NAND狀態

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

     

  8. 函數read_byte

    該函數功能為從NAND芯片讀取一個字節,代碼如程序清單 3-5所示。

    程序清單 3-5  NAND讀一個字節

     

        return ((UCHAR)readl(REG_NANDDATA));

     

  9. 函數write_buf

    該函數功能為從一個緩沖區寫數數據到NAND芯片。代碼實現如程序清單 3-6。

    程序清單 3-6  寫緩沖區數據到NAND

     

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

     

  10. 函數read_buf

    該函數功能為從NAND芯片讀數據到一個緩沖區。代碼實現如程序清單 3-7所示。

    程序清單 3-7  讀數據到緩沖區

     

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

     

  11. 函數ecc.hwctl

    該函數用于控制硬件ECC發生器,只有在使用硬件ECC時實現。本例的硬件校驗在傳輸中實現,因此該函數為空實現。

  12. 函數ecc.calculate

    該函數用于ECC計算,或從ECC硬件中讀回。本例的硬件校驗在傳輸中實現,因此該函數為空實現。

  13. 函數ecc.correct

    該函數用于ECC校正。本例的硬件校驗在傳輸中實現,因此該函數為空實現。

  14. 函數ecc.write_page

    該函數主要實現帶ECC的寫一頁數據到NAND芯片。在傳輸的過程中,ECC電路會自動計算ECC校驗值,并存儲到控制器分配的寄存器組中。完成傳輸后寄存器組中的OOB數據會根據設置自動寫進NAND芯片。實現流程如程序清單 3-8所示。

    程序清單 3-8  帶硬件ECC的寫頁

    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. 函數ecc.read_page

    該函數主要實現帶ECC校驗的從NAND芯片讀出一頁數據。本例為硬件ECC,需要先讀出OOB區數據到控制器分配的寄存器組中。在數據傳輸的過程中,ECC電路會計算ECC校驗值,并與寄存器組中的值比較,檢查是否產生錯誤,以及定位和計算校錯值。若產生錯誤,程序需要根據錯誤位置和錯誤值進行校錯。具體流程如程序清單 3-9所示:

    程序清單 3-9  ECC的讀頁

     

    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. 函數ecc.read_oob

    該函數主要實現從芯片中讀取OOB數據。實現流程如程序清單 3-10所示。

    程序清單 3-10  帶硬件ECC的讀OOB區數據

     

    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布局控制結構體。通過該結構體配置OOB區中ECC的位數和位置,可用位數和空閑位數。本例通過調用程序清單 3-11代碼實現OOB區的布局控制。

    程序清單 3-11   OOB區布局

     

    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. 文件系統掛載

    在SylixOS下NAND Flash通常掛載YAFFS文件系統,并分為n0和n1分區,其中n0分區用作啟動分區,n1作為應用分區。掛載流程如程序清單 3-12所示。

    程序清單 3-12  文件系統掛掛載

     

        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);

     

參考資料

無。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

克拉玛依市| 美姑县| 河间市| 墨脱县| 望都县| 常山县| 启东市| 汉阴县| 桓台县| 城固县| 上思县| 扬中市| 碌曲县| 海安县| 金川县| 图们市| 景东| 华安县| 夏河县| 浮梁县| 东方市| 阿巴嘎旗| 淄博市| 自治县| 大城县| 乌拉特中旗| 永新县| 双江| 富宁县| 昌都县| 维西| 鄂温| 巫山县| 龙岩市| 当涂县| 霍邱县| 白银市| 沐川县| 阳东县| 江都市| 玉山县|