Chinaunix首页 | 论坛 | 博客
  • 博客访问: 852088
  • 博文数量: 190
  • 博客积分: 7021
  • 博客等级: 少将
  • 技术积分: 1752
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-17 19:26
文章分类

全部博文(190)

文章存档

2014年(9)

2011年(32)

2010年(149)

我的朋友

分类: LINUX

2010-05-18 21:10:43

接着来分析nand_read_oob()函数,读取第二部分的数据。具体需要看数据手册,先看看函数的原型:
static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
{
int i, offset, page;
struct nand_chip *this = mtd->priv;

DEBUG(MTD_DEBUG_LEVEL3, __FUNCTION__"(): from = 0x%08x, len = %i\n", (unsigned int)from, (int)len);

page = ((int)from) >> this->page_shift;

offset = from & 0x0f;

*retlen = 0;

if ((offset + len) > mtd->oobsize)
{
    DEBUG(MTD_DEBUG_LEVEL0, __FUNCTION__"(): Attempt read past end of page" \
       "0x%08lx, colum %i, length %i\n", page, offset, len);
    return -EINVAL;

nand_select();
//在读oob区的数据的时候有专门的命令,因此地址可以直接是oob中的相对地址(offset)。
//在下面分析nand_write_oob()函数的时候就可以看到差别
nand_command(mtd, NAND_CMD_READOOB, offset, page);

this->wait_for_ready();

//将读出的数据一次放入buf数组中
for (i = 0; i < len; i++)
{
    buf[i] = this->read_data();
}

nand_deselect();

*retlen = len;
return 0;
}
看完了read,我们再来看看write函数,在读懂了nand_write以后,这个函数就很简单,基本流程是一样的:

/*
 * NAND write out-of-band
 */

static int
nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
               size_t *retlen, const u_char *buf)
{
    int i, offset, page, status, ret;
    struct nand_chip *this = mtd->priv;

    DEBUG(MTD_DEBUG_LEVEL3,
        __FUNCTION__"(): to = 0x%08x, len = %i\n", (unsigned int)to,
        (int)len);

    /* Shift to get page */
    page = ((int)to) >> this->page_shift;

    /* Mask to get column */
    offset = to & 0x1f;

    /* Initialize return length value */
    *retlen = 0;

    /* Do not allow write past end of page */
    if ((offset + len) > mtd->oobsize) {
        DEBUG(MTD_DEBUG_LEVEL0,
            __FUNCTION__"(): Attempt to write past end of page\n");
        return -EINVAL;
    }

    /* Select the NAND device */
    nand_select();

    /* Check the WP bit */
    nand_command(mtd, NAND_CMD_STATUS, -1, -1);
   
    this->wait_for_ready();

    if (!(this->read_data() & SMC_STAT_NOT_WP)) {
        DEBUG(MTD_DEBUG_LEVEL0,
            __FUNCTION__"(): Device is write protected!!!\n");
        ret = -EPERM;
        goto nand_write_oob_err;
    }  

    

    //0x80对页进行编程操作,用于写操作
    /* Write out desired data */
    nand_command(mtd, NAND_CMD_SEQIN, offset + mtd->oobblock, page);
    this->hwcontrol(NAND_CTL_DAT_OUT);
    for (i = 0; i < len; i++)
        this->write_data(buf[i]);
    this->hwcontrol(NAND_CTL_DAT_IN);

    /* Send command to program the OOB data */
    nand_command(mtd, NAND_CMD_PAGEPROG, -1, -1);

    this->wait_for_ready();

    /*
     * Wait for program operation to complete. This could
     * take up to 3000us (3ms) on some devices, so we try
     * and exit as quickly as possible.

     * 注意解释的最后一句话,其中最后的if语句起到了关键的作用

     */
    status = 0;
    for (i = 0; i < 24; i++) {
        /* Delay for 125us */
        udelay(125);

        /* Check the status */
        nand_command(mtd, NAND_CMD_STATUS, -1, -1);

        this->wait_for_ready();

        status = (int)this->read_data();
        if (status & SMC_STAT_READY)
            break;
    }

    /* See if device thinks it succeeded */
    if (status & SMC_STAT_WRITE_ERR) {
        DEBUG(MTD_DEBUG_LEVEL0,
            __FUNCTION__"(): Failed write, page 0x%08x\n", page);
        ret = -EIO;
        goto nand_write_oob_err;
    }

#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
    /* Send command to read back the data */
    nand_command(mtd, NAND_CMD_READOOB, offset, page);

    this->wait_for_ready();

    /* Loop through and verify the data */
    for (i = 0; i < len; i++) {
        if (buf[i] != this->read_data()) {
            DEBUG(MTD_DEBUG_LEVEL0,
                __FUNCTION__"(): Failed write verify, page 0x%08x\n",
                page);
            ret = -EIO;
            goto nand_write_oob_err;
        }
    }
#endif

    /* Return happy */
    *retlen = len;
    ret = 0;

nand_write_oob_err:
    /* De-select the NAND device */
    nand_deselect();

    return ret;
}

还有两个函数,nand_read_ecc和nand_write_ecc。这两个函数涉及到ecc检测,对那方面的知识几乎为0,要先去看看???
阅读(1629) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~