uboot2021.10-nandflash-2.nand_do_write_ops

 nand_do_write_ops 的一个注释。

这个函数带有ecc的数据的写入。比如yaffs文件系统就需要这个方法来操作。

/**
 * nand_do_write_ops - [INTERN] NAND write with ECC
 * @mtd: MTD device structure
 * @to: offset to write to
 * @ops: oob operations description structure
 *
 * NAND write with ECC.    //有ecc的写操作
 */
static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
			     struct mtd_oob_ops *ops)
{
	int chipnr, realpage, page, column;
	struct nand_chip *chip = mtd_to_nand(mtd);
	uint32_t writelen = ops->len;    //数据写入长度(不包括oob的长度),字节数

	uint32_t oobwritelen = ops->ooblen;       //oob的长度,字节数
	uint32_t oobmaxlen = mtd_oobavail(mtd, ops);     //oob的最大字节数

	uint8_t *oob = ops->oobbuf;     //指向数据的oob缓存首地址
	uint8_t *buf = ops->datbuf;     //指向数据的缓存首地址,所以在调用这个函数的时候,oob和数据已经被分离开了。
	int ret;
	int oob_required = oob ? 1 : 0;    //oob指针不为空,这等于1,否则等于0

	ops->retlen = 0;
	if (!writelen)              //写入的长度值为0,表示不用写入,退出
		return 0;

	/* Reject writes, which are not page aligned */
	if (NOTALIGNED(to)) {     //不是小页512对齐,退出,因为这里有ecc,每个ecc至少需要一个完整的小页
		pr_notice("%s: attempt to write non page aligned data\n",
			   __func__);
		return -EINVAL;
	}

	column = to & (mtd->writesize - 1);    //起始位置不是2k页对齐,记录偏移

	chipnr = (int)(to >> chip->chip_shift);   //多个flash芯片的情况,这个我的应该是返回0,只有一块芯片
	chip->select_chip(mtd, chipnr);    //选中第0块

	/* Check, if it is write protected */
	if (nand_check_wp(mtd)) {      //检测是不是写保护?
		ret = -EIO;
		goto err_out;
	}

	realpage = (int)(to >> chip->page_shift);    //计算页开始的位置,2k页,shift为12
	page = realpage & chip->pagemask;      //防止可能超出整个芯片,pagemask是不是总页数-1?

	/* Invalidate the page cache, when we write to the cached page */
	if (to <= ((loff_t)chip->pagebuf << chip->page_shift) &&
	    ((loff_t)chip->pagebuf << chip->page_shift) < (to + ops->len))   //数据应该没有超过芯片的最大范围?
		chip->pagebuf = -1;       //==-1?

	/* Don't allow multipage oob writes with offset */
	if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) {   //对oob的字节数进行合法性判断
		ret = -EINVAL;
		goto err_out;
	}

	while (1) {     //开始写入
		int bytes = mtd->writesize;    //2k页 值为2048
		uint8_t *wbuf = buf;       //数据的首地址
		int use_bufpoi;
		int part_pagewr = (column || writelen < mtd->writesize);    //要写一页的一部分?

		if (part_pagewr)
			use_bufpoi = 1;    //只需要写一页的一部分。
		else if (chip->options & NAND_USE_BOUNCE_BUFFER)
			use_bufpoi = !IS_ALIGNED((unsigned long)buf,
						 chip->buf_align);      //缓存的对齐方式,
		else
			use_bufpoi = 0;    //一般情况下为0

		WATCHDOG_RESET();   //看门狗喂狗,实际没有开启
		/* Partial page write?, or need to use bounce buffer */
		if (use_bufpoi) {    //对于只有部分写入的情况,还有需要使用bounce buffer
			pr_debug("%s: using write bounce buffer for buf@%p\n",
					 __func__, buf);
			if (part_pagewr)
				bytes = min_t(int, bytes - column, writelen);   //取出一个小值
			chip->pagebuf = -1;   //==-1?
			memset(chip->buffers->databuf, 0xff, mtd->writesize);    //缓存填充0xff
			memcpy(&chip->buffers->databuf[column], buf, bytes);   //拷贝实际的字节数
			wbuf = chip->buffers->databuf;    //写缓存等于databuf
		}

		if (unlikely(oob)) {    //oob不是空指针,//但是大概率是空指针
			size_t len = min(oobwritelen, oobmaxlen);   //取出一个小值
			oob = nand_fill_oob(mtd, oob, len, ops);   //填充oob的内容。
			oobwritelen -= len;   //字节数减小
		} else {
			/* We still need to erase leftover OOB data */
			memset(chip->oob_poi, 0xff, mtd->oobsize);   //填充0xff
		}
		ret = chip->write_page(mtd, chip, column, bytes, wbuf,    //写一页数据,包含oob
					oob_required, page,
					(ops->mode == MTD_OPS_RAW));
		if (ret)    //返回值不为0,表示出错了!!,跳出循环
			break;

		writelen -= bytes;
		if (!writelen)    //字节数全部写完了,跳出循环
			break;

		column = 0;    //清零
		buf += bytes;        //buf的指针向后移动写入的字节数
		realpage++;     //下一页

		page = realpage & chip->pagemask;      //防止越界
		/* Check, if we cross a chip boundary */
		if (!page) {   //如果page为0,表示回绕了
			chipnr++;      //换到下一个芯片开始写
			chip->select_chip(mtd, -1);
			chip->select_chip(mtd, chipnr);
		}
	}

	ops->retlen = ops->len - writelen;     //真正写入的字节数,用来判断是否出错吧
	if (unlikely(oob))    //如果指定了oob,返回oob的写入长度
		ops->oobretlen = ops->ooblen;

err_out:
	chip->select_chip(mtd, -1);
	return ret;
}

1.一点小疑惑:

chip->pagebuf = -1;       //==-1? 这个地方出现了两次,正常也是一个数字。

 表示page的缓存失效!!!!

2.这个函数中真正做写操作的是write_page的指针。

3.对于不满一页(2k)的数据,我看到没有数据的地方是填充了0xff的。

4.调用这个函数的时候,data和oob是分开存放的。用不同的缓存存起来了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大智兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值