u-boot-1.1.6中nand_write_ecc的错误

在使用tftp下载内核时,使用tftp 0x32000000 uImage,然后使用nand的命令将uImage写入nandflash中发现一个比较奇异的错误提示:10384bytes write error,通过调试发现,在校验函数nand_verify_pages中校验写入内容出错,通过分析代码,发现在写每块的page的时候出错,修改代码,在1680行添加this->data_poi = (u_char*) &buf[written];问题解决。

nand_write_ecc函数代码:

/**
 * nand_write_ecc - [MTD Interface] NAND write with ECC
 * @mtd:    MTD device structure
 * @to:        offset to write to
 * @len:    number of bytes to write
 * @retlen:    pointer to variable to store the number of written bytes
 * @buf:    the data to write
 * @eccbuf:    filesystem supplied oob data buffer
 * @oobsel:    oob selection structure
 *
 * NAND write with ECC
 */
static int nand_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)
{
    int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
    int autoplace = 0, numpages, totalpages;
    struct nand_chip *this = mtd->priv;
    u_char *oobbuf, *bufstart;
    int    ppblock = (1 << (this->phys_erase_shift - this->page_shift));

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

    /* Initialize retlen, in case of early exit */
    *retlen = 0;

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

    /* reject writes, which are not page aligned */
    if (NOTALIGNED (to) || NOTALIGNED(len)) {
        printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
        return -EINVAL;
    }

    /* Grab the lock and see if the device is available */
    nand_get_device (this, mtd, FL_WRITING);

    /* Calculate chipnr */
    chipnr = (int)(to >> this->chip_shift);
    /* Select the NAND device */
    this->select_chip(mtd, chipnr);

    /* Check, if it is write protected */
    if (nand_check_wp(mtd))
        goto out;

    /* if oobsel is NULL, use chip defaults */
    if (oobsel == NULL)
        oobsel = &mtd->oobinfo;

    /* Autoplace of oob data ? Use the default placement scheme */
    if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
        oobsel = this->autooob;
        autoplace = 1;
    }
    if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
        autoplace = 1;

    /* Setup variables and oob buffer */
    totalpages = len >> this->page_shift;
    page = (int) (to >> this->page_shift);
    /* Invalidate the page cache, if we write to the cached page */
    if (page <= this->pagebuf && this->pagebuf < (page + totalpages))
        this->pagebuf = -1;

    /* Set it relative to chip */
    page &= this->pagemask;
    startpage = page;
    /* Calc number of pages we can write in one go */
    numpages = min (ppblock - (startpage  & (ppblock - 1)), totalpages);
    oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages);
    bufstart = (u_char *)buf;

    /* Loop until all data is written */
    while (written < len) {

        this->data_poi = (u_char*) &buf[written];
        /* Write one page. If this is the last page to write
         * or the last page in this block, then use the
         * real pageprogram command, else select cached programming
         * if supported by the chip.
         */
        ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
        if (ret) {
            DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret);
            goto out;
        }
        /* Next oob page */
        oob += mtd->oobsize;
        /* Update written bytes count */
        written += mtd->oobblock;
        if (written == len)
            goto cmp;

        /* Increment page address */
        page++;

        /* Have we hit a block boundary ? Then we have to verify and
         * if verify is ok, we have to setup the oob buffer for
         * the next pages.
        */
        if (!(page & (ppblock - 1))){
            int ofs;
            this->data_poi = bufstart;
            ret = nand_verify_pages (mtd, this, startpage,
                page - startpage,
                oobbuf, oobsel, chipnr, (eccbuf != NULL));
            if (ret) {
                DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
                goto out;
            }
            *retlen = written;
            bufstart = (u_char*) &buf[written];

            ofs = autoplace ? mtd->oobavail : mtd->oobsize;
            if (eccbuf)
                eccbuf += (page - startpage) * ofs;
            totalpages -= page - startpage;
            numpages = min (totalpages, ppblock);
            page &= this->pagemask;
            startpage = page;
            oob = 0;
            this->oobdirty = 1;
            oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel,
                    autoplace, numpages);
            /* Check, if we cross a chip boundary */
            if (!page) {
                chipnr++;
                this->select_chip(mtd, -1);
                this->select_chip(mtd, chipnr);
            }
        }
    }
    /* Verify the remaining pages */
cmp:
    this->data_poi = bufstart;
     ret = nand_verify_pages (mtd, this, startpage, totalpages,
        oobbuf, oobsel, chipnr, (eccbuf != NULL));
    if (!ret)
        *retlen = written;
    else
        DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);

out:
    /* Deselect and wake up anyone waiting on the device */
    nand_release_device(mtd);

    return ret;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值