u-boot-1.1.6 nand flash 中 create_bbt 解读

开发?p>

澹?jz2440_v3

/**
 * create_bbt - [GENERIC] Create a bad block table by scanning the device
 * @mtd:	MTD device structure
 * @buf:	temporary buffer
 * @bd:		descriptor for the good/bad block search pattern
 * @chip:	create the table for a specific chip, -1 read all chips.
 *		Applies only if NAND_BBT_PERCHIP option is set
 *
 * Create a bad block table by scanning the device
 * for the given good/bad block identify pattern
 */
static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
{
	struct nand_chip *this = mtd->priv;
	int i, j, numblocks, len, scanlen;
	int startblock;
	loff_t from;
	size_t readlen, ooblen;

	if (bd->options & NAND_BBT_SCANALLPAGES)
		len = 1 << (this->bbt_erase_shift - this->page_shift);
	else {
		if (bd->options & NAND_BBT_SCAN2NDPAGE)
			len = 2;
		else
			len = 1;
	}
	// len = 1
	scanlen	= mtd->oobblock + mtd->oobsize; // 2048 Bytes + 64 Bytes
	readlen = len * mtd->oobblock; // 2048
	ooblen = len * mtd->oobsize; // 64

	if (chip == -1) {
		/* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it
		 * makes shifting and masking less painful
		 * 请注意,这里的 numblocks 是2*(真正的numblocks),请参阅下面的i+=2,
		 * 因为它可以减少移位和掩蔽的痛苦
		 */
		numblocks = mtd->size >> (this->bbt_erase_shift - 1); // 2048*2 = 4096 blocks
		startblock = 0;
		from = 0;
	} else {
		if (chip >= this->numchips) {
			printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)
",
				chip + 1, this->numchips);
			return;
		}
		numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
		startblock = chip * numblocks;
		numblocks += startblock;
		from = startblock << (this->bbt_erase_shift - 1);
	}

	for (i = startblock; i < numblocks;) {
		// buf 为 1 block 的大小: (2048 Byte + 64 Byte) * 64 page
		nand_read_raw (mtd, buf, from, readlen, ooblen);
		for (j = 0; j < len; j++) {
			if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
				/**
				 * this->bbt定义在:
				 * 		nand_scan_bbt 中设置的 默认值: 0x00 (注:在本文中)
				 * 
				 * 含义:
				 * 		四个block的坏块信息存在一个this->bbt[]数组里,
				 * 		二进制的11表示其中一个是坏块,
				 * 		二进制的00表示其中一个是好块。
				 * 
				 * 实例:
				 * 		this->bbt[0]=03; 
				 * 		表示有一个坏块,分别是block 0;
				 * 		this->bbt[3]=30; 
				 * 		表示有一个坏块,分别是block 14;
				 * 		this->bbt[256]=3f; 
				 * 		表示有三个坏块,分别是block 1024,1025,1026
				 * 
				 * 注意(Note That):
				 * 
				 * 		芯片为小端模式,存储排列顺序为:
				 * 			00    00    00    00
				 * 			3	  2	    1	  0     ---> block index
				 * 					 .
				 * 					 .
				 * 					 .
				 *          00    00    00    00
				 * 			1027  1026  1025  1024  ---> block index
				 * 	
				 */
				this->bbt[i >> 3] |= 0x03 << (i & 0x6);
				/**
				 * 如果不乘2,表达式该为:
				 * this->btt[i>>2] |= 0x3 << (i & 0x3)*2;
				 * 硬件操作为:取最后两位,再向右移动一位
				 * 优化后:先移位然后再取后3位
				 */
				break;
			}
		}
		i += 2;
		from += (1 << this->bbt_erase_shift);
	}
}