千家信息网

SylixOS下基于NUC970的NAND驱动

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,开发环境开发环境宿主机: Windows7 64bits 系统开发板: 安米MDK972软件环境: RealEvo-IDE3.0NAND Flash: S34ML02G100TF100S34ML02G
千家信息网最后更新 2025年01月23日SylixOS下基于NUC970的NAND驱动

开发环境

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

2-1 NUC970 NAND控制器

技术实现

  1. 驱动框架

    SylixOS中NAND Flsh的驱动框架如图 3-1所示。NAND通用驱动主要在fs/mtd/nand/nand_base.c中,该文件包含了NAND的通用操作。驱动工程师需要在NAND通用驱动的基础上实现与硬件相关的驱动层的结构体(nand_chip),该结构体包含了对具体硬件相关的控制和操作函数,以及相关硬件参数和配置信息。MTD层与文件系统,SylixOS已经完全实现,不需要驱动工程师实现。

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

参考资料

无。

函数 程序 清单 控制 硬件 数据 驱动 芯片 控制器 代码 系统 文件 传输 功能 寄存器 框架 结构 配置 命令 布局 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 北京国际服务器公司虚拟主机 为啥手机号显示无服务器 济南天狐网络技术有限公司6 网络技术发展的作文 前端开发 软件软件开发 数据库查询女生的总人数 亿元级别的数据库 数据库技术可以从事哪些行业 网络安全知识竞赛服务器失误 数据库配置选择 软件开发 新生代农民工 网络安全保护知识产权的知识 学习什么网络技术可以自己开店 数据库表格原料 阿里巴巴网络安全谁管 山西网络安全屏障图 ug怎么导入加工数据库 数据库图文设计软件 厦门千浩网络技术有限公司 王者荣耀科技服务器推荐 方舟线上服务器加入超时 市教育局网络安全周活动方案 宝山区专业性软件开发经验丰富 长沙财务软件开发流程 大话西游2豪华服务器 戴尔r620服务器回收 鄞州敏捷软件开发流程 互联网科技行业类别 我的世界联机非服务器ip 苏州通用软件开发技术指导
0