基于MTD的NANDFLASH设备驱动底层实现原理分析(三) .

发布时间:2017-2-24 21:10:19 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"基于MTD的NANDFLASH设备驱动底层实现原理分析(三) .",主要涉及到基于MTD的NANDFLASH设备驱动底层实现原理分析(三) .方面的内容,对于基于MTD的NANDFLASH设备驱动底层实现原理分析(三) .感兴趣的同学可以参考一下。

非常的说:我突然发现在写这些关于NAND驱动的文章的时候,原来我一直是在改写别人的博客。。。。。其实这并不要紧的,我也觉得这不仅仅是一种比较好的学习方法了,为什么呢,因为当我在看他的博客的时候,我明白了一点,然后当我自己要写的时候。。对这个东东又进一步了解一点了。。呵呵Copy也分档次了 五、硬件时序到软件代码的演变过程对nand_base.c部分代码的分析 该文件位于</linux2.6.35/dricer/mtd/nand/nand_base.c> 还是把那个读NAND的硬件时序图给贴上,如下图:     ①:此阶段,是读命令第一个周期,发送的命令为0x00。 ②:此阶段,依次发送列地址,关于这些行地址,列地址等是如何计算出来的,后面的内容 会有详细解释。  ③:此阶段是发送对应的行地址  ④:此阶段是发送读命令第二周期 2nd cycle所对应的命令,0x30  ⑤:此阶段是等待时间,等待 Nand Flash硬件上准备好对应的数据,以便后续读出。  ⑥:此阶段,就是一点点地把所需要的数据读出来。  MTD 读取数据的入口是 nand_read,然后调用 nand_do_read_ops,此函数主体如下: static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,                 struct mtd_oob_ops *ops) {     /***此处省略部分代码**/     。。。。。。。。。。。。。。     while(1) {            /******省略****/           .。。。。。。。。。。。。。。。             if (likely(sndcmd)) {/*#define NAND_CMD_READ0 0*/                 /*1)***读取数据前肯定要先发送对应的读页命令******/                 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);                 sndcmd = 0;             }             /* Now read the page into the buffer */             if (unlikely(ops->mode == MTD_OOB_RAW))                 ret = chip->ecc.read_page_raw(mtd, chip,                                   bufpoi, page);             else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)                 ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);             else              /******执行到这里read_page函数读取对应的数据了******/                 ret = chip->ecc.read_page(mtd, chip, bufpoi,                               page);             if (ret < 0)                 break;             /* Transfer not aligned data */             if (!aligned) {                 if (!NAND_SUBPAGE_READ(chip) && !oob)                     chip->pagebuf = realpage;                 memcpy(buf, chip->buffers->databuf + col, bytes);             }             buf += bytes;           。。。。。。。。。。。。。。。。。。     if (mtd->ecc_stats.failed - stats.failed)         return -EBADMSG;     return  mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; } 上面这些代码都不需要我们去实现的,使用MTD层的自定义代码就行。。。 nand_command_lp的分析 static void nand_command_lp(struct mtd_info *mtd, unsigned int command,                 int column, int page_addr) {     register struct nand_chip *chip = mtd->priv;     /* Emulate NAND_CMD_READOOB */     if (command == NAND_CMD_READOOB) {         column += mtd->writesize;         command = NAND_CMD_READ0;     }     /* Command latch cycle */    /* 此处就是就是发送读命令的第一个周期1st Cycle的命令,即0x00,对应着上述步骤中的① */     chip->cmd_ctrl(mtd, command & 0xff,                NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);     if (column != -1 || page_addr != -1) {         int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;         /* Serially input address */         if (column != -1) {             /* Adjust columns for 16 bit buswidth */             if (chip->options & NAND_BUSWIDTH_16)                 column >>= 1;           /* 发送两个column列地址,对应着上述步骤中的② */             chip->cmd_ctrl(mtd, column, ctrl);/*发送列地址1*/             ctrl &= ~NAND_CTRL_CHANGE;             chip->cmd_ctrl(mtd, column >> 8, ctrl);/*发送列地址2*/         }         if (page_addr != -1) {           /* 接下来是发送三个Row,行地址,对应着上述步骤中的② */             chip->cmd_ctrl(mtd, page_addr, ctrl);/*发送行地址1*/             chip->cmd_ctrl(mtd, page_addr >> 8,/*发送行地址2*/                        NAND_NCE | NAND_ALE);             /* One more address cycle for devices > 128MiB */             if (chip->chipsize > (128 << 20))                 chip->cmd_ctrl(mtd, page_addr >> 16,/*发送行地址3*/                            NAND_NCE | NAND_ALE);         }     }     chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);     /*      * program and erase have their own busy handlers      * status, sequential in, and deplete1 need no delay      */     switch (command) { 。。。。。。。。。。。。。         return;    /***复位**/     case NAND_CMD_RESET:         if (chip->dev_ready)             break;         udelay(chip->chip_delay);         chip->cmd_ctrl(mtd, NAND_CMD_STATUS,                    NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);         chip->cmd_ctrl(mtd, NAND_CMD_NONE,                    NAND_NCE | NAND_CTRL_CHANGE);         while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;         return;     /*读忙信号*/     case NAND_CMD_RNDOUT:         /* No ready / busy check necessary */         chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,                    NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);         chip->cmd_ctrl(mtd, NAND_CMD_NONE,                    NAND_NCE | NAND_CTRL_CHANGE);         return; /* 接下来发送读命令的第二个周期2nd Cycle的命令,即0x30,对应着上述步骤 中的④ */      case NAND_CMD_READ0:         chip->cmd_ctrl(mtd, NAND_CMD_READSTART,                    NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);         chip->cmd_ctrl(mtd, NAND_CMD_NONE,                    NAND_NCE | NAND_CTRL_CHANGE);         /* This applies to read commands */     default:         /*          * If we don't have access to the busy pin, we apply the given          * command delay          */         if (!chip->dev_ready) {             udelay(chip->chip_delay);             return;         }     }     /* Apply this short delay always to ensure that we do wait tWB in      * any case on any machine. */ /* 此处是对应着④中的tWB的等待时间*/     ndelay(100); /* 接下来就是要等待一定的时间,使得Nand Flash硬件上准备好数据,以供你之 后读取,即对应着步骤⑤ */      nand_wait_ready(mtd); } 还有一个步骤没有实现那就是步骤⑥了一点一点的把数据读出来  nand_read_page_hwecc分析 static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,                 uint8_t *buf, int page) {    。。。。。。。。。。。。。。。。。。。。。。     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {         chip->ecc.hwctl(mtd, NAND_ECC_READ);          /**这个最重要了这才是真正的从NAND的缓冲区中把数据给读出来****/         chip->read_buf(mtd, p, eccsize);         chip->ecc.calculate(mtd, p, &ecc_calc[i]);     }     。。。。。。。。。。     return 0; } 上面的 read_buf,就是真正的去读取数据的函数了,由于不同的Nand Flash controller 控制器所实现的方式不同,所以这个函数必须在你的 Nand Flash驱动中实现,即MTD 层,能帮我们实现的都实现了,不能实现的,那肯定是我们自己的事情了。。。接下来的工作是什么?MTD原始设备和硬件驱动层的交互了.这个才是我们要去真正实现的。。

上一篇:1077 - The Sky is the Limit
下一篇:基于MTD的NANDFLASH设备驱动底层实现原理分析(二) .

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。