QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 6876|回复: 2

关于flash_eraseall的问题

[复制链接]
发表于 2007-6-13 09:27:22 | 显示全部楼层 |阅读模式
对于NAND Flash类型的记忆体,网上资料都说在erase的动作中会把bad block给标记出来。对此我研究了flash_eraseall的代码,企图找到mark bad block是如何实现的。后来发现flash_eraseall其实仅对NANDFlash做了ioctl(fd, MEMGETBADBLOCK, &offset),ioctl(fd, MEMERASE, &erase) 两个动作,并没有做检测并且mark bad block。于是我怀疑这个动作内嵌在MEMERASE或者MEMGETBADBLOCK之中了,我就又找到mtd_ioctl.c,看到:
******************************
case MEMERASE:
        {
                struct erase_info *erase;

                if(!(file->f_mode & 2))
                        return -EPERM;

                erase=kmalloc(sizeof(struct erase_info),GFP_KERNEL);
                if (!erase)
                        ret = -ENOMEM;
                else {
                        wait_queue_head_t waitq;
                        DECLARE_WAITQUEUE(wait, current);

                        init_waitqueue_head(&waitq);

                        memset (erase,0,sizeof(struct erase_info));
                        if (copy_from_user(&erase->addr, argp,
                                    sizeof(struct erase_info_user))) {
                                kfree(erase);
                                return -EFAULT;
                        }
                        erase->mtd = mtd;
                        erase->callback = mtdchar_erase_callback;
                        erase->priv = (unsigned long)&waitq;

                        /*
                          FIXME: Allow INTERRUPTIBLE. Which means
                          not having the wait_queue head on the stack.

                          If the wq_head is on the stack, and we
                          leave because we got interrupted, then the
                          wq_head is no longer there when the
                          callback routine tries to wake us up.
                        */
                        ret = mtd->erase(mtd, erase);
                        if (!ret) {
                                set_current_state(TASK_UNINTERRUPTIBLE);
                                add_wait_queue(&waitq, &wait);
                                if (erase->state != MTD_ERASE_DONE &&
                                    erase->state != MTD_ERASE_FAILED)
                                        schedule();
                                remove_wait_queue(&waitq, &wait);
                                set_current_state(TASK_RUNNING);

                                ret = (erase->state == MTD_ERASE_FAILED)?-EIO:0;
                        }
                        kfree(erase);
                }
                break;
        }
******************************
case MEMGETBADBLOCK:
        {
                loff_t offs;

                if (copy_from_user(&offs, argp, sizeof(loff_t)))
                        return -EFAULT;
                if (!mtd->block_isbad)
                        ret = -EOPNOTSUPP;
                else
                        return mtd->block_isbad(mtd, offs);
                break;
        }

貌似也没有看到我希望的mark bad block的过程,所以想在此请教大家,为何我在erase NANDFlash的全过程看不到标记坏块的动作,是否真的不存在?那么NANDFlash是如何标记在使用过程中产生的坏块的?
 楼主| 发表于 2007-7-5 14:25:21 | 显示全部楼层
问题已解决。所有erase NANDFlash的动作最终都是通过struct mtd_info中的erase指针实现的。

struct mtd_info {
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
         int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
         int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
         int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
         int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
...
...
...

这个指针在 cfi_cmdset_0002.c中被调用指向了一个函数“mtd->erase = cfi_amdstd_erase_chip;”
函数也定义在 cfi_cmdset_0002.c中,所以最终可以看到erase的全部自检机制,即在erase结束后,会把刚erase过的空间里的值读两次出来,对第二次读出来的值作比较,该值必须同时满足‘等于第一次读出来的值’和‘等于0xFF’才算erase成功,不然就是坏块,做标记。
相关代码如下:
static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
{
        struct cfi_private *cfi = map->fldrv_priv;
        unsigned long timeo = jiffies + HZ;
        unsigned long int adr;
        DECLARE_WAITQUEUE(wait, current);
        int ret = 0;
/* Did we succeed? */
        if (!chip_good(map, adr, map_word_ff(map))) {
                /* reset on all failures. */
                map_write( map, CMD(0xF0), chip->start );
                /* FIXME - should have reset delay before continuing */

                ret = -EIO;
        }

        chip->state = FL_READY;
        xip_enable(map, chip, adr);
        put_chip(map, chip, adr);
        spin_unlock(chip->mutex);
....

static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected)
{
        map_word oldd, curd;

        oldd = map_read(map, addr);
        curd = map_read(map, addr);

        return        map_word_equal(map, oldd, curd) &&
                map_word_equal(map, curd, expected);
}


希望能给正在研究nandflash的同学一些帮助
回复

使用道具 举报

发表于 2009-2-17 14:00:12 | 显示全部楼层

感谢楼主

我最近也在查nandflash的坏块标识的资料,看了楼主的帖子,对nandflash的坏块标识机制加深了一定的认识,谢谢楼主~~~~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-3-29 00:39 , Processed in 0.173038 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表