天天看點

小張學linux核心驅動篇:5.mtd驅動架構nandflash特點:硬體結構mtd nandflash驅動rawnand驅動字元裝置接口nor flash

nandflash特點:

  1. nand存在位反轉的現象,是以需要ecc校驗資料,ecc校驗可以矯正一位的位反轉,發現兩位的位反轉;
  2. nand存在壞塊的問題,所謂壞塊,就是不能擦除的塊,nandflash隻能從1寫為0;而不能從0寫為1,也就是write時,隻能将某一位拉低;而擦除操作是将0拉高位1。擦除是按塊擦的,寫的話按頁寫。寫的話按頁寫是為了提高效率,而擦除隻能按塊擦除。
  3. nandflash的接口有并口和spi接口的。

硬體結構

原理圖

并口的nandflash,8bit flash,位址和資料線共用

小張學linux核心驅動篇:5.mtd驅動架構nandflash特點:硬體結構mtd nandflash驅動rawnand驅動字元裝置接口nor flash

ALE和CLE用于位址和資料選擇。

内部結構

小張學linux核心驅動篇:5.mtd驅動架構nandflash特點:硬體結構mtd nandflash驅動rawnand驅動字元裝置接口nor flash

頁結構

每一頁2048 data+64OOB;OOB(out of band);OOB主要有2byte壞快辨別 + ECC資料;

壞塊辨別0xff為好塊,其他為壞。壞塊辨別每一塊的第一頁的OOB區内。

小張學linux核心驅動篇:5.mtd驅動架構nandflash特點:硬體結構mtd nandflash驅動rawnand驅動字元裝置接口nor flash

以上頁結構資訊,不同的晶片廠商結構也不一樣。

nandflash指令集

#define NAND_CMD_READ0		0
#define NAND_CMD_READ1		1
#define NAND_CMD_RNDOUT		5
#define NAND_CMD_PAGEPROG	0x10
#define NAND_CMD_READOOB	0x50
#define NAND_CMD_ERASE1		0x60
#define NAND_CMD_STATUS		0x70
#define NAND_CMD_SEQIN		0x80
#define NAND_CMD_RNDIN		0x85
#define NAND_CMD_READID		0x90
#define NAND_CMD_ERASE2		0xd0
#define NAND_CMD_PARAM		0xec
#define NAND_CMD_GET_FEATURES	0xee
#define NAND_CMD_SET_FEATURES	0xef
#define NAND_CMD_RESET		0xff

/* Extended commands for large page devices */
#define NAND_CMD_READSTART	0x30
#define NAND_CMD_RNDOUTSTART	0xE0
#define NAND_CMD_CACHEDPROG	0x15

#define NAND_CMD_NONE		-1
           

mtd nandflash驅動

mtd架構分層:

裝置層: mtdchar.c/mtdblock.c; 字元裝置和塊裝置接口。

原始裝置層 mtdcore.c 提供mtd_info;mtd_partion;mtd_part結構。

硬體驅動層 /mtd/nand/下

nand_base.c nand通用接口;

分rawnand;onenand,spinand;

rawnand: 位址資料總線為并口。

spinand:通過spi總線控制,相當與rawnand封裝成了spi接口。多了一個spi解釋單元。

onenand:可以了解為nor+nand。

mtd架構能做什麼不能做什麼?

  1. nand flash有壞塊,mtd驅動架構能幫我們跳壞塊嗎?

    答:不能,mtd隻提供讀寫page接口,和ioctl接口來測試該塊是否為壞塊,但是不會在讀寫的時候幫我們自動跳過壞塊,跳壞塊操作需要我們應用來自己實作。

  2. nandflash會存在位反轉現象,mtd驅動架構會幫我們做ecc校驗嗎? 糾正一位的bitflip,發現2bit的bitflip?

    答:這個mtd驅動架構會幫做,但是ecc校驗可選軟體ecc和硬體ecc,軟體ecc算法mtd架構提供,硬體ecc則是硬體結構提供,讀資料的時候會校驗。

  3. nandflash擦除是按塊擦除的,寫是按頁寫的,如果我們要寫一個塊中的某一頁,需要将整個塊讀出來然後,修改然後擦除寫入。即read-update-erase-write;這個操作mtd會幫我們做嗎?

    答:不會。mtd隻提供頁寫入接口,這一系列操作需要使用者自己做。至于提高寫入速率的操作,也需要使用者自己實作。

rawnand驅動字元裝置接口

字元裝置寫流程圖:

小張學linux核心驅動篇:5.mtd驅動架構nandflash特點:硬體結構mtd nandflash驅動rawnand驅動字元裝置接口nor flash

1. 寫資料不跳壞塊

2. oob中ecc資料可以是

1> 原始資料中已經帶有的

2> 軟體算法生成的 3中算法;

3> 硬體實作ecc算法;需要驅動實作ecc…

3. 不提供block寫buffer;即read-update-erase-write流程。

讀資料流

小張學linux核心驅動篇:5.mtd驅動架構nandflash特點:硬體結構mtd nandflash驅動rawnand驅動字元裝置接口nor flash

1.同樣不跳壞塊

2.ecc校驗 nand_chip.ecc.correct

見代碼硬體ecc分支nand_read_page_hwecc:

static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
				uint8_t *buf, int oob_required, int page)
{
	int i, eccsize = chip->ecc.size, ret;
	int eccbytes = chip->ecc.bytes;
	int eccsteps = chip->ecc.steps;
	uint8_t *p = buf;
	uint8_t *ecc_calc = chip->ecc.calc_buf;
	uint8_t *ecc_code = chip->ecc.code_buf;
	unsigned int max_bitflips = 0;

	ret = nand_read_page_op(chip, page, 0, NULL, 0);
	if (ret)
		return ret;

	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
		chip->ecc.hwctl(mtd, NAND_ECC_READ);

		ret = nand_read_data_op(chip, p, eccsize, false);
		if (ret)
			return ret;

		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
	}

	ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false);
	if (ret)
		return ret;

	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
					 chip->ecc.total);
	if (ret)
		return ret;

	eccsteps = chip->ecc.steps;
	p = buf;

	for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
		int stat;

		stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
		if (stat == -EBADMSG &&
		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
			/* check for empty pages with bitflips */
			stat = nand_check_erased_ecc_chunk(p, eccsize,
						&ecc_code[i], eccbytes,
						NULL, 0,
						chip->ecc.strength);
		}

		if (stat < 0) {
			mtd->ecc_stats.failed++;
		} else {
			mtd->ecc_stats.corrected += stat;
			max_bitflips = max_t(unsigned int, max_bitflips, stat);
		}
	}
	return max_bitflips;
}
           

壞快表BBT

有的廠商将壞塊表存放在flash第一塊的第一頁中,因為廠商出廠時第一頁會確定為好塊的。但是如果flash用來存放代碼,則不能第一頁不能用來存放壞快表。有的廠商将壞塊表放在最後一塊,但是要確定最後一塊為好塊。

mtdchar iotcl判斷該塊是否為壞塊。

case MEMGETBADBLOCK:
	{
		loff_t offs;

		if (copy_from_user(&offs, argp, sizeof(loff_t)))
			return -EFAULT;
		return mtd_block_isbad(mtd, offs);
		break;
	}
           

調用鍊

小張學linux核心驅動篇:5.mtd驅動架構nandflash特點:硬體結構mtd nandflash驅動rawnand驅動字元裝置接口nor flash

如果記憶體中沒有bbt(chip->bbt);則去讀oob區域;

如果有bbt,則從bbt[]中讀取資料;

标記壞塊時,标記bbt并更新oob區域。

nor flash

cfi接口;jedec(老的接口)

繼續閱讀