nand_write_skip_bad函数解析

/**
 * nand_write_skip_bad:
 *
 * Write image to NAND flash.
 * Blocks that are marked bad are skipped and the is written to the next
 * block instead as long as the image is short enough to fit even after
 * skipping the bad blocks.  Due to bad blocks we may not be able to
 * perform the requested write.  In the case where the write would
 * extend beyond the end of the NAND device, both length and actual (if
 * not NULL) are set to 0.  In the case where the write would extend
 * beyond the limit we are passed, length is set to 0 and actual is set
 * to the required length.
 *
 * @param nand  	NAND device
 * @param offset	offset in flash
 * @param length	buffer length
 * @param actual	set to size required to write length worth of
 *			buffer or 0 on error, if not NULL
 * @param lim		maximum size that actual may be in order to not
 *			exceed the buffer
 * @param buffer        buffer to read from
 * @param flags		flags modifying the behaviour of the write to NAND
 * @return		0 in case of success
 */
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
		size_t *actual, loff_t lim, u_char *buffer, int flags)
{
	int rval = 0, blocksize;
	size_t left_to_write = *length;
	size_t used_for_write = 0;
	u_char *p_buffer = buffer;
	int need_skip;

	if (actual)
		*actual = 0;

	blocksize = nand->erasesize;

	/*
	 * nand_write() handles unaligned, partial page writes.
	 *
	 * We allow length to be unaligned, for convenience in
	 * using the $filesize variable.
	 *
	 * However, starting at an unaligned offset makes the
	 * semantics of bad block skipping ambiguous (really,
	 * you should only start a block skipping access at a
	 * partition boundary).  So don't try to handle that.
	 */
	if ((offset & (nand->writesize - 1)) != 0) {	//-- 页不对齐,出错误返回
		printf("Attempt to write non page-aligned data\n");
		*length = 0;
		return -EINVAL;
	}

	need_skip = check_skip_len(nand, offset, *length, &used_for_write);//-- 计算含坏块后的写总长度,用used_for_write返回

	if (actual)
		*actual = used_for_write;

	if (need_skip < 0) {//-- 说明要写的区域超过的设备容量
		printf("Attempt to write outside the flash area\n");
		*length = 0;
		return -EINVAL;
	}

	if (used_for_write > lim) {
		puts("Size of write exceeds partition or device limit\n");
		*length = 0;
		return -EFBIG;
	}

	if (!need_skip && !(flags & WITH_DROP_FFS)) {//-- 没有坏块并且flag不是WITH_DROP_FFS参数,直接按length长度写入
		rval = nand_write(nand, offset, length, buffer);

		if ((flags & WITH_WR_VERIFY) && !rval)
			rval = nand_verify(nand, offset, *length, buffer);

		if (rval == 0)
			return 0;

		*length = 0;
		printf("NAND write to offset %llx failed %d\n",
			offset, rval);
		return rval;
	}

	while (left_to_write > 0) {
		size_t block_offset = offset & (nand->erasesize - 1);	//-- 获取块内偏移,例如一个page 2048个字节,对于第2个page来说,在该块内该值为4096
		size_t write_size, truncated_write_size;

		WATCHDOG_RESET();

		//-- offset & ~(nand->erasesize - 1)算出来的值是要写入的page所在的block的第一个page的第一个字节。比如一个block有64个page,一个page有2048个字节,如果要
		//-- 要写第10个block的第2个page,那么该值为10 * 64 * 2048.此处应该就是坏块标记,是按照该块的第一个page的第一个字节是否为0xff来判断是否为坏块。
		if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {//-- 跳过一个坏块
			printf("Skip bad block 0x%08llx\n",
				offset & ~(nand->erasesize - 1));
			offset += nand->erasesize - block_offset;
			continue;
		}

		if (left_to_write < (blocksize - block_offset))
			write_size = left_to_write;
		else
			write_size = blocksize - block_offset;

		truncated_write_size = write_size;
#ifdef CONFIG_CMD_NAND_TRIMFFS
		if (flags & WITH_DROP_FFS)
			truncated_write_size = drop_ffs(nand, p_buffer,
					&write_size);
#endif

		rval = nand_write(nand, offset, &truncated_write_size,
				p_buffer);

		if ((flags & WITH_WR_VERIFY) && !rval)
			rval = nand_verify(nand, offset,//-- 将写入的数据再读一遍验证写入是否正确
				truncated_write_size, p_buffer);

		offset += write_size;
		p_buffer += write_size;

		if (rval != 0) {
			printf("NAND write to offset %llx failed %d\n",
				offset, rval);
			*length -= left_to_write;
			return rval;
		}

		left_to_write -= write_size;
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黑猫学长呀

有帮助到你就来打个赏呗

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

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

打赏作者

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

抵扣说明:

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

余额充值