日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SylixOS下基于NUC970的NAND驱动

發布時間:2023/12/20 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SylixOS下基于NUC970的NAND驱动 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

開發環境

  • 開發環境

    宿主機: Windows7 64bits 系統

    開發板: 安米MDK972

    軟件環境: RealEvo-IDE3.0

    NAND Flash: S34ML02G100TF100

  • 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所示。

    2-1 ? NUC970 NAND控制器

    ?

    技術實現

  • 驅動框架

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

    3-1 ? NAND驅動框架

  • 框架實現

    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;

    ?

  • 控制器初始化

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

  • ECC配置

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

  • 函數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);} }
  • 函數cmdfunc

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

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

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

    ?

  • 函數dev_ready

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

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

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

    ?

  • 函數read_byte

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

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

    ?

    ????return?((UCHAR)readl(REG_NANDDATA));

    ?

  • 函數write_buf

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

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

    ?

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

    ?

  • 函數read_buf

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

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

    ?

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

    ?

  • 函數ecc.hwctl

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

  • 函數ecc.calculate

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

  • 函數ecc.correct

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

  • 函數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; }


    ?

  • 函數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; }

    ?

  • 函數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; }

    ?

  • 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?; }

    ?

  • 文件系統掛載

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

    ?

  • 參考資料

    無。

    轉載于:https://blog.51cto.com/12557713/1898029

    總結

    以上是生活随笔為你收集整理的SylixOS下基于NUC970的NAND驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。