文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>pxa310 nand驱动三

pxa310 nand驱动三

时间:2010-06-09  来源:tonyen

1          nand写入

1.1      yaffs2写函数分析

struct mtd_oob_ops ops;

… … …

yaffs_PackedTags2 pt;

… … …

ops.mode = MTD_OOB_AUTO;

ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);

ops.len = dev->totalBytesPerChunk;

ops.ooboffs = 0;

ops.datbuf = (__u8 *)data;

ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;

retval = mtd->write_oob(mtd, addr, &ops);

pt存放OOB数据,调用的是mtd->write_oob。在nand_scan_tail里,mtd->read_oob被初始化为nand_write_oob

1.2      nand_write_oob

如果ops->datbuf不为空,调用nand_do_write_oob,这个函数只写OOB数据。否则,调用nand_do_write_ops。

       if (!ops->datbuf)

              ret = nand_do_write_oob(mtd, to, ops);

       else

              ret = nand_do_write_ops(mtd, to, ops);

在我们的这种情况,ops->datbuf不为空,所以调用nand_do_write_ops。

1.3      nand_do_write_ops

static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,

                          struct mtd_oob_ops *ops)

下图是该函数的流程图,其中调用了nand_fill_oob和write_page。

2          Nand OOB

page大小为2k的nand包含一个64个字节的OOB区域,pxa310在使用yaffs2时,OOB区域是这样分配的:

3          nand坏块管理

3.1      坏块表描述符

坏块表本身也需要存储在nand上,坏块表描述符用来表示该表在nand上的一些信息,pxa310定义了两个坏块表,一个主坏块表和一个映像。

主坏块表:

static struct nand_bbt_descr monahans_bbt_main = {

       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | NAND_BBT_2BIT | NAND_BBT_VERSION,

       .veroffs = 6,

       .maxblocks = 2,

        .offs = 2,

        .len = 4,

        .pattern = scan_main_bbt_pattern,

};

options表示坏块表的参数。NAND_BBT_LASTBLOCK表示该表在该设备上最后一个好的block上,NAND_BBT_CREATE表示如果该坏块表不存在的话,就创建它,NAND_BBT_WRITE表示该表可以写,NAND_BBT_2BIT表示每个block用两个bit表示,NAND_BBT_VERSION表示该表有版本信息,版本信息存储在oob区域,在OOB的偏移为veroffs。offs为pattern在OOB区域的偏移,len则为pattern的长度。

同样,映像表的描述符定义如下:

static struct nand_bbt_descr monahans_bbt_mirror = {

       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE

                     | NAND_BBT_2BIT | NAND_BBT_VERSION,

       .veroffs = 6,

       .maxblocks = 4,

        .offs = 2,

        .len = 4,

        .pattern = scan_mirror_bbt_pattern,

};

具体含义我们就不解释了。

3.2      扫描坏块表

 

3.2.1        nand_scan_bbt

int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)

{

       struct nand_chip *this = mtd->priv;

       int len, res = 0;

       uint8_t *buf;

       struct nand_bbt_descr *td = this->bbt_td;

       struct nand_bbt_descr *md = this->bbt_md;

/* len为需要的bbt长度,每个block两个bit*/

       len = mtd->size >> (this->bbt_erase_shift + 2);

       /* Allocate memory (2bit per block) and clear the memory bad block table */

       this->bbt = kzalloc(len, GFP_KERNEL);

       if (!this->bbt) {

              printk(KERN_ERR "nand_scan_bbt: Out of memory\n");

              return -ENOMEM;

       }

 

… … …

/*这里的len被初始化为一个块的大小,这个大小包含OOB。*/

       /* Allocate a temporary buffer for one eraseblock incl. oob */

       len = (1 << this->bbt_erase_shift);

       len += (len >> this->page_shift) * mtd->oobsize;

       buf = vmalloc(len);

       if (!buf) {

              printk(KERN_ERR "nand_bbt: Out of memory\n");

              kfree(this->bbt);

              this->bbt = NULL;

              return -ENOMEM;

       }

 

res = search_read_bbts(mtd, buf, td, md);

/*search_read_bbts总是会返回1,所以,check_create总是会执行*/

       if (res)

              res = check_create(mtd, buf, bd);

 

       /* Prevent the bbt regions from erasing / writing */

       mark_bbt_region(mtd, td);

       if (md)

              mark_bbt_region(mtd, md);

 

       vfree(buf);

       return res;

}

3.2.2        search_bbt

search_bbt查找在nand上查找匹配特定模式的坏块表,需要匹配的模式存放在参数td中。

static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)

{

       struct nand_chip *this = mtd->priv;

       int i, chips;

       int bits, startblock, block, dir;

       int scanlen = mtd->writesize + mtd->oobsize;

       int bbtblocks;

       int blocktopage = this->bbt_erase_shift - this->page_shift;

/*如果设置了NAND_BBT_LASTBLOCK ,表示重最后一个块开始搜索,搜索的块是存放在td->maxblocks */

       /* Search direction top -> down ? */

       if (td->options & NAND_BBT_LASTBLOCK) {

              startblock = (mtd->size >> this->bbt_erase_shift) - 1;

              dir = -1;

       } else {

              startblock = 0;

              dir = 1;

       }

 

       /* Do we have a bbt per chip ? */

       if (td->options & NAND_BBT_PERCHIP) {

              chips = this->numchips;

              bbtblocks = this->chipsize >> this->bbt_erase_shift;

              startblock &= bbtblocks - 1;

       } else {

              chips = 1;

              bbtblocks = mtd->size >> this->bbt_erase_shift;

       }

 

       /* Number of bits for each erase block in the bbt */

       bits = td->options & NAND_BBT_NRBITS_MSK;

 

       for (i = 0; i < chips; i++) {

              /* Reset version information */

              td->version[i] = 0;

              td->pages[i] = -1;/*从这里可知,每个td->pages存放一个nand的坏块储存位置*/

              /* Scan the maximum number of blocks */

              for (block = 0; block < td->maxblocks; block++) {

 

                     int actblock = startblock + dir * block;

                     loff_t offs = (loff_t)actblock << this->bbt_erase_shift;

 

                     /* Read first page */

                     scan_read_raw(mtd, buf, offs, mtd->writesize);/*读取该块的第一个page*/

                     /*check_pattern做的事情比较简单,检查该page的oob区域中的pattern是否和td中存储的相匹配*/

if (!check_pattern(buf, scanlen, mtd->writesize, td)) {

                            td->pages[i] = actblock << blocktopage;

                            if (td->options & NAND_BBT_VERSION) {

                                   td->version[i] = buf[mtd->writesize + td->veroffs];

                            }

                            break;

                     }

              }

              startblock += this->chipsize >> this->bbt_erase_shift;

       }

       /* Check, if we found a bbt for each requested chip */

       for (i = 0; i < chips; i++) {

              if (td->pages[i] == -1)

                     printk(KERN_WARNING "Bad block table not found for chip %d\n", i);

              else

                     printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],

                            td->version[i]);

       }

       return 0;

}

3.2.3        check_create

check_create创建或者更新坏块表。

static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)

{

       int i, chips, writeops, chipsel, res;

       struct nand_chip *this = mtd->priv;

       struct nand_bbt_descr *td = this->bbt_td;

       struct nand_bbt_descr *md = this->bbt_md;

       struct nand_bbt_descr *rd, *rd2;

 

       /* Do we have a bbt per chip ? */

       if (td->options & NAND_BBT_PERCHIP)

              chips = this->numchips;

       else

              chips = 1;

/*我们这里的chips永远都是1。*/

       for (i = 0; i < chips; i++) {

              writeops = 0;

              rd = NULL;

              rd2 = NULL;

              /* Per chip or per device ? */

              chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;

              /* Mirrored table avilable ? */

              if (md) {

                     /*如果主坏块表和映像坏块表都没有找到,writeops置为3,程序到create处,一般来说,只有nand初次被使用是才会出现这种情况*/

                     if (td->pages[i] == -1 && md->pages[i] == -1) {

                            writeops = 0x03;

                            goto create;

                     }

                     /*如果没有找到主坏块表,则将writeops置1*,rd置为md,表示md需要先被读取,然后才能更新/

                     if (td->pages[i] == -1) {

                            rd = md;

                            td->version[i] = md->version[i];

                            writeops = 1;

                            goto writecheck;

                     }

                     /*如果没有找到映像坏块表,则将writeops置2*/

                     if (md->pages[i] == -1) {

                            rd = td;

                            md->version[i] = td->version[i];

                            writeops = 2;

                            goto writecheck;

                     }

                     /*程序执行到这里,主坏块表和映像坏块表都找到了,比较他们的version一样的话,则两个坏块表都需要先被读取,然后才能更新*/

                     if (td->version[i] == md->version[i]) {

                            rd = td;

                            if (!(td->options & NAND_BBT_VERSION))

                                   rd2 = md;

                            goto writecheck;

                     }

 

                     if (((int8_t) (td->version[i] - md->version[i])) > 0) {

                            rd = td;

                            md->version[i] = td->version[i];

                            writeops = 2;

                     } else {

                            rd = md;

                            td->version[i] = md->version[i];

                            writeops = 1;

                     }

 

                     goto writecheck;

 

              } else {

                     if (td->pages[i] == -1) {

                            writeops = 0x01;

                            goto create;

                     }

                     rd = td;

                     goto writecheck;

              }

       create:

              /* Create the bad block table by scanning the device ? */

              if (!(td->options & NAND_BBT_CREATE))

                     continue;

 

              /* Create the table in memory by scanning the chip(s) */

              create_bbt(mtd, buf, bd, chipsel);

 

              td->version[i] = 1;

              if (md)

                     md->version[i] = 1;

       writecheck:

              /*如果有需要先读取的情况,调用read_abs_bbt先读取坏块信息*/

              /* read back first ? */

              if (rd)

                     read_abs_bbt(mtd, buf, rd, chipsel);

              /* If they weren't versioned, read both. */

              if (rd2)

                     read_abs_bbt(mtd, buf, rd2, chipsel);

              /*下面这种情况是找到了映像坏块表,没有找到主坏块表*/

              /* Write the bad block table to the device ? */

              if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {

                     res = write_bbt(mtd, buf, td, md, chipsel);

                     if (res < 0)

                            return res;

              }

/*下面这种情况是找到主坏块表,没有找到映像坏块表*/

              /* Write the mirror bad block table to the device ? */

              if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {

                     res = write_bbt(mtd, buf, md, td, chipsel);

                     if (res < 0)

                            return res;

              }

       }

       return 0;

}

3.2.4        write_bbt

相关阅读 更多 +
排行榜 更多 +
mirrox模组(玩家自制)手机版下载

mirrox模组(玩家自制)手机版下载

休闲益智 下载
集装箱模拟器手机版下载安装

集装箱模拟器手机版下载安装

模拟经营 下载
哔咔漫画app下载免费2025

哔咔漫画app下载免费2025

浏览阅读 下载