yaffs2源码学习2:chunk和block

一、Nand Flash介绍

非易失性闪速存储器Flash具有速度快、成本低、密度大的特点,被广泛应用于嵌入式系统中。Flash存储器主要有NOR和NAND两种类型。NOR型比较适合存储程序代码;NAND型则可用作大容量数据存储。
一块Nand Flash芯片被分为了很多block,而每一个block又由很多个chunk构成,每个chunk由data和spare这两个区域组成,data区域存放文件数据,spare区域存放坏块信息,ECC校验等。我们以K9F2G08X0A为例进行介绍,如图:
K9F2G08X0A Nand flash图示

  1. K9F2G08X0A是2,112Mbit(2,214,592,512 bit)大小,共包含2048个BLOCK,每个BLOCK包含64个页,每个页包含2112个字节。
  2. 一个大小为2112的页由数据区域(2K)和SPARE区域(64Bytes)组成,其中SPARE区域用来存储坏块信息、ECC校验等。
  3. 读数据时可以按字节读取,但擦写单位最小是一个块。
  4. 器件中的坏块是随机分布的。出厂时坏块被标记在坏块的第一页或第二页,它们被标记为非0xFF的值。第一次使用时应扫描FLASH并记录坏块信息。
  5. 所有flash器件都受位交换现象的困扰。在使用中应采用错误探测/错误更正(EDC/ECC)算法确保数据可靠性。一旦发现ECC错误,应将数据所在块标记为坏块

对于数据,最基本的存储和删除单元就是chunk和block,所以这一部分我们介绍yaffs2中对于chunk和block相关操作的源码。

二、Chunk相关操作

2.1 chunk记录数据的种类

Nand Flash上共记录着三类数据,check point data、object header与file data。记录chunk状态的数据结构如下:

struct yaffs_ext_tags {
   
	unsigned chunk_used;	/*  Status of the chunk: used or unused */
	unsigned obj_id;	/* If 0 this is not used */
	unsigned chunk_id;	/* If 0 this is a header, else a data chunk */
	unsigned n_bytes;	/* Only valid for data chunks */

	/* The following stuff only has meaning when we read */
	enum yaffs_ecc_result ecc_result;
	unsigned block_bad;

	/* YAFFS 1 stuff */
	unsigned is_deleted;	/* The chunk is marked deleted */
	unsigned serial_number;	/* Yaffs1 2-bit serial number */

	/* YAFFS2 stuff */
	unsigned seq_number;	/* The sequence number of this block */

	/* Extra info if this is an object header (YAFFS2 only) */
	unsigned extra_available;	/* Extra info available if not zero */
	unsigned extra_parent_id;	/* The parent object */
	unsigned extra_is_shrink;	/* Is it a shrink header? */
	unsigned extra_shadows;	/* Does this shadow another object? */

	enum yaffs_obj_type extra_obj_type;	/* What object type? */

	loff_t extra_file_size;		/* Length if it is a file */
	unsigned extra_equiv_id;	/* Equivalent object for a hard link */
};
  • check point data YAFFS2按照block来分配存储空间记录check point data,即一个block要么全用于记录check point data,要么全用于记录普通数据。而chunk的tag.seq_number被复用于“记录block seq_number”,或“表示block记录着check point data”。这个复用的可能性是建立在block. seq_number的大小是在一个固定的区间内。
  • object header tag.chunkId等于0,表示相应chunk的data area记录着object header,并可由tag.objectId找到相应的文件。
  • file data tag.chunkId不等于0,则相应chunk的data area记录着file data,并且tag.chunkId表示该chunk在文件内的logical chunk id。此外可由tag.objectId找到相应的文件。

2.2 chunk的使用情况

在dev结构中,有个参数u8 *chunk_bits,记录着chunk的使用情况,每一个bit对应一个chunk,YAFFS2用该数据记录着chunk是否正在被使用。这信息在运行时只存在于内存中,当YAFFS2被unmout时,该数组当作check point data被记录下来,在下一次的mount时被读出并被恢复。关于某一chunk对应的bit的更改函数在文件“yaffs_bitmap.c”中,代码如下,内容比较简单,就不在详细的说明了,根据函数名也大概知道该函数做了什么工作。

static inline u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk)
{
   
	if (blk < (int)dev->internal_start_block ||
	    blk > (int)dev->internal_end_block) {
   
		yaffs_trace(YAFFS_TRACE_ERROR,
			"BlockBits block %d is not valid",
			blk);
		BUG();
	}
	return dev->chunk_bits +
	    (dev->chunk_bit_stride * (blk - dev->internal_start_block));
}

void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk)
{
   
	if (blk < (int)dev->internal_start_block ||
	    blk > (int)dev->internal_end_block ||
	    chunk < 0 || chunk >= (int)dev->param.chunks_per_block) {
   
		yaffs_trace(YAFFS_TRACE_ERROR,
			"Chunk Id (%d:%d) invalid",
			blk, chunk);
		BUG();
	}
}

void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk)
{
   
	u8 *blk_bits = yaffs_block_bits(dev, blk);
	memset(blk_bits, 0, dev->chunk_bit_stride);
}

void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值