uboot2021.10-nandflash-1.nand_fill_oob

本文只是对该函数的注释,方便之后查阅,可能有误,请高手指正。

/**
 * nand_fill_oob - [INTERN] Transfer client buffer to oob
 * @mtd: MTD device structure
 * @oob: oob data buffer
 * @len: oob data write length
 * @ops: oob ops structure
 */
static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
			      struct mtd_oob_ops *ops)
{
	struct nand_chip *chip = mtd_to_nand(mtd);

	/*
	 * Initialise to all 0xFF, to avoid the possibility of left over OOB
	 * data from a previous OOB read.
	 */
	memset(chip->oob_poi, 0xff, mtd->oobsize);

	switch (ops->mode) {

	case MTD_OPS_PLACE_OOB:
	case MTD_OPS_RAW:
		memcpy(chip->oob_poi + ops->ooboffs, oob, len);
		return oob + len;

	case MTD_OPS_AUTO_OOB: {
		struct nand_oobfree *free = chip->ecc.layout->oobfree;
		uint32_t boffs = 0, woffs = ops->ooboffs;
		size_t bytes = 0;

		for (; free->length && len; free++, len -= bytes) {
			/* Write request not from offset 0? */
			if (unlikely(woffs)) {
				if (woffs >= free->length) {
					woffs -= free->length;
					continue;
				}
				boffs = free->offset + woffs;
				bytes = min_t(size_t, len,
					      (free->length - woffs));
				woffs = 0;
			} else {
				bytes = min_t(size_t, len, free->length);
				boffs = free->offset;
			}
			memcpy(chip->oob_poi + boffs, oob, bytes);
			oob += bytes;
		}
		return oob;
	}
	default:
		BUG();
	}
	return NULL;
}

这个函数不长。

1. 首先看一下三个宏的注释

/**
 * MTD operation modes
 *
 * @MTD_OPS_PLACE_OOB:    OOB data are placed at the given offset (default)

        这个说是会把oob放置在指定的位置
 * @MTD_OPS_AUTO_OOB:    OOB data are automatically placed at the free areas
 *            which are defined by the internal ecclayout

        这个说是把oob放置到空闲的位置,空闲位置由ecclayout指定
 * @MTD_OPS_RAW:    data are transferred as-is, with no error correction;
 *            this mode implies %MTD_OPS_PLACE_OOB
 *        这个说,数据和它本身一致,没有ecc
 * These modes can be passed to ioctl(MEMWRITE) and are also used internally.
 * See notes on "MTD file modes" for discussion on %MTD_OPS_RAW vs.
 * %MTD_FILE_MODE_RAW.
 */
enum {
    MTD_OPS_PLACE_OOB = 0,
    MTD_OPS_AUTO_OOB = 1,
    MTD_OPS_RAW = 2,
};

2. memset(chip->oob_poi, 0xff, mtd->oobsize);

对oob的数组填充0xff。mtd->oobsize指定缓存有多大。

3.case MTD_OPS_PLACE_OOB:
    case MTD_OPS_RAW:
        memcpy(chip->oob_poi + ops->ooboffs, oob, len);
        return oob + len;

对于以上两种情况,ops->ooboffs 指定偏移地址,oob指向存有ecc的缓存,len指定oob缓存中有的字节数。

就是,拷贝oob中的数据到chip->oob_poi这个数组中(注意下标被指定了ops->ooboffs,而可能是不为0的),拷贝的字节数为len

其中oob的值由参数传入,len的值由参数传入。

注意返回值为oob + len,是个地址值。

4. 对于自动放置的情况

case MTD_OPS_AUTO_OOB: {
        struct nand_oobfree *free = chip->ecc.layout->oobfree;   //oobfree 是指的空闲区的头指针,可能不止一个
        uint32_t boffs = 0, woffs = ops->ooboffs; //起始位置
        size_t bytes = 0;

        //需要考虑的情况是一个空闲区域可能写不下,所以要for循环处理。

        for (; free->length && len; free++, len -= bytes) {    //空闲区长度不为0,且要写的长度len不为0
            /* Write request not from offset 0? */
            if (unlikely(woffs)) {     //woffs 大于 0。 //woffs取0的可能性比较大
                if (woffs >= free->length) {   大于等于,写的偏移比空闲长度大。因为指定了偏移woffs,所以要把前面的位置空出来。
                    woffs -= free->length;    //减去
                    continue; 
                }
                boffs = free->offset + woffs;   //开始写的位置boffs,此时woffs可能还不为0,但是已经小于free->length,所以还要在偏移一点点woffs,但是这次已经落在free区间了。
                bytes = min_t(size_t, len,
                          (free->length - woffs));   //取出较小的值
                woffs = 0;   //偏移清零
            } else {   //woffs 等于0
                bytes = min_t(size_t, len, free->length);   //对len和free->length取个小的
                boffs = free->offset;  //起始位置,是free区域的起始偏移位置
            }
            memcpy(chip->oob_poi + boffs, oob, bytes);    //写入字节,最大长度为bytes
            oob += bytes;   //oob的指针向后移动。
        }  //end for
        return oob;

} //end case

分析到此结束。

应该来说还是比较简单。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大智兄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值