【韦东山旧1期学习笔记】09.S3C2440 Nand Flash实验(三)

Nand Flash坏块管理

        由于Nand Flash的工艺不能保证Nand的Memory Array在其生命周期中保持性能的可靠,因此,在Nand的生产中及使用过程中会产生坏块。坏块的特性是:当编程/擦除这个块时,不能将某些位拉高,这会造成Page Program和Block Erase操作时的错误,相应地反映到Status Register的相应位。总体上,坏块可以分为两大类:
  (1) 固有坏块
    这是生产过程中产生的坏块,一般芯片原厂都会在出厂时都会将坏块第一个page的spare area的某个字节标记为非0xff的值。
  (2) 使用坏块
    这是在NAND Flash使用过程中,如果Block Erase或者Page Program错误,就可以简单地将这个块作为坏块来处理,这个时候需要把坏块标记起来。为了和固有坏块信息保持一致,将新发现的坏块的第一个page的 spare area的某字节标记为非0xff的值。
    一般来说,small page的NAND芯片,坏块信息存储在每个block的第一个page的oob的第六个字节中,而big page的NAND芯片,坏块信息存储在每个block的第一个page的oob的第1个字节中。
    而K9F2G08U0C每页的大小为2KB,属于大页。所以我们要检查每个块的第一页或者第二页的第一个字节是否非0xFF。若非0xFF,则该块即为坏块。
为此,检测坏块的代码如下所示:

int nand_BadBlockCheck(unsigned char* nandAddr) {
	unsigned int blockAddr = (unsigned int)nandAddr / K9F2G08U0C_BLOCK_SIZE;
	blockAddr *= K9F2G08U0C_BLOCK_SIZE;
       	unsigned int page = blockAddr /	K9F2G08U0C_PAGE_SIZE;
	unsigned int col = 2048;

	//nand_selectChip();
	nand_cmd(0x00);
	nand_col(col);
	nand_page(page);
	nand_cmd(0x30);
	nand_waitReady();
	//nand_cmd(0xFF);
	//nand_waitReady();
	//nand_deSelectChip();
	unsigned char data = nand_ReadData();
	if(data != 0xFF){
		//坏块
		return 1;	
	}

	return 0;
}

Nand Flash的擦除和写入

Nand Flash在进行写入操作之前必须先执行擦除操作。

擦除操作

擦除操作是以块为单位的,其时序图如下所示:
在这里插入图片描述
对应擦除代码如下所示:

int nand_Erase(unsigned char* nandAddr, unsigned int length) {
	unsigned char status = 0;
	unsigned int page = (unsigned int)nandAddr / K9F2G08U0C_PAGE_SIZE;
	if((unsigned int)nandAddr & (K9F2G08U0C_BLOCK_SIZE - 1)){
		printf("nand_Erase Error. Address 0x%x is not aligned by Block size %dKB.\n\r", nandAddr, K9F2G08U0C_BLOCK_SIZE/1024);
		return -1;
	}
	if(length & (K9F2G08U0C_BLOCK_SIZE - 1)){
		printf("nand_Erase Error. Erase length %d is not aligned by Block size %dKB.\n\r", length, K9F2G08U0C_BLOCK_SIZE/1024);
		return -1;
	}
	nand_selectChip();
	nand_waitReady();	
	while(length > 0) {
		page = (unsigned int)nandAddr / K9F2G08U0C_PAGE_SIZE;
		nand_cmd(0x60);
		nand_page(page);
		nand_cmd(0xD0);
		nand_waitReady();
		nand_cmd(0x70);
		status = nand_ReadData();
		if(status & 0x1){
			//Erase this block failed
			printf("Erase Block(0x%8x) failed.\n\r", nandAddr);
		}
		nandAddr += K9F2G08U0C_BLOCK_SIZE;
		length -= K9F2G08U0C_BLOCK_SIZE;
	}
	nand_deSelectChip();
}

写入操作

写入操作是以页为单位的,其操作时序如下所示:
在这里插入图片描述
对应写入代码如下所示:

void nand_Write(unsigned char* nandAddr, unsigned char* srcData, unsigned int len) {
	//从指定的内存源地址srcData处开始写入数据,
	//存储到Nand Flash的nand地址nandAddr处,字节长度由len指定
	unsigned char status = 0;
	unsigned int tmpNandAddr = (unsigned int)nandAddr;
	unsigned int pageAddr = tmpNandAddr / K9F2G08U0C_PAGE_SIZE;
	//对src取模,得到列地址
	unsigned int colAddr = tmpNandAddr & (K9F2G08U0C_PAGE_SIZE - 1);
	unsigned idx = 0;
	//Nand是按页写入,按块擦除
	nand_selectChip();
	nand_waitReady();
	while(idx < len) {
		/* 一个block只判断一次 */
		if (!(tmpNandAddr & 0x1FFFF) && nand_BadBlockCheck((unsigned char*)tmpNandAddr)) {
			tmpNandAddr += (128*1024);  /* 跳过当前block */
			pageAddr = tmpNandAddr / K9F2G08U0C_PAGE_SIZE;
			colAddr = tmpNandAddr & (K9F2G08U0C_PAGE_SIZE - 1);
			continue;
		}

		nand_cmd(0x80);
		//发送12位列地址
		nand_addr(colAddr & 0xFF);
		nand_addr((colAddr >> 8) & 0x1F);
		//发送17位行地址
		nand_addr(pageAddr & 0xFF);
		nand_addr((pageAddr >> 8) & 0xFF);
		nand_addr((pageAddr >> 16) & 0x1);

		for( ;(colAddr < 2048) & (idx < len); idx++){
			nand_WriteData(srcData[idx]);
			colAddr++;
		}
		nand_cmd(0x10);
		nand_waitReady();
		//当前页的数据写入完毕,开始下一页,从头列开始写入
		colAddr = 0;
		pageAddr++;
		nand_cmd(0x70);
		nand_waitReady();
		status = nand_ReadData();
		if(status & 0x1) {
			printf("Write Page address 0x%8x failed.\n\r", pageAddr);
		}
	}
	
	//reset nand chip
	nand_cmd(0xFF);
	nand_waitReady();
	nand_deSelectChip();
	return;
}

实验结果图

编译并烧写至Nand Flash中,并选择Nand方式启动,上电,观察串口输出,如下所示:
在这里插入图片描述

实验完整代码

Nand实验代码总共由19个源文件构成。

.
├── CRT0.S
├── Ctype.c
├── Ctype.h
├── main.c
├── Makefile
├── myprintf.c
├── myprintf.h
├── nand.c
├── nand.h
├── nand.lds
├── relocate.c
├── s3c2440_soc.h
├── sdram.c
├── sdram.h
├── stdarg.h
├── uart.c
├── uart.h
├── util.c
└── util.h

0 directories, 19 files

完整代码下载路径如下所示:
Nand Flash完整驱动

发布了26 篇原创文章 · 获赞 2 · 访问量 1069

猜你喜欢

转载自blog.csdn.net/BakerTheGreat/article/details/104344020