⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nand_test.c

📁 MBA2440(s3c2440)的 源代码文件 ARM920T内核。
💻 C
字号:
/****************************************************************************
 * file name	: nand_test.c
 * Date			: 15. 04. 2005
 * Version		: 1.0
 * Description	: NAND flash test menu display function
 *
 *
 ****************************************************************************/

#include "nand_test.h"


void NAND_flash_test(void)
{
	int sel = 0;

	while(1){
		Uart_Printf("+--------------[ NAND flash test ]----------------+\n");
		Uart_Printf("|  1:SOP(K9F5608U0B)\n");
		Uart_Printf("|  2:SMC(K9S1208V0M)\n");
		Uart_Printf("|  3:Previous menu\n");
		Uart_Printf("+-------------------------------------------------+\n");
		Uart_Printf(" Select the type of a NAND flash memory : ");
		sel = Uart_GetIntNum();
		Uart_Printf("+-------------------------------------------------+\n\n\n");
		
		switch(sel){
			case 1:
				K9F5608_menu();
				break;
			case 2:
				K9S1208_menu();
				break;
			case 3 :
				return;
			default:
				Uart_Printf("Wrong number seleted.. Try again!!\n\n\n");
				break;
		}
	}

}


void NAND_reset(void)
{
	int i;

	NF_nFCE_L();
	NF_CLEAR_RB();
	NF_CMD(NAND_CMD_RESET);
	for(i=0;i<10;i++);
	NF_nFCE_H();
}

void NAND_init(void)
{
	rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);	
	// TACLS		[14:12]	CLE&ALE duration = HCLK*TACLS.
	// TWRPH0		[10:8]	TWRPH0 duration = HCLK*(TWRPH0+1)
	// TWRPH1		[6:4]	TWRPH1 duration = HCLK*(TWRPH1+1)
	// AdvFlash(R)	[3]		Advanced NAND, 0:256/512, 1:1024/2048
	// PageSize(R)	[2]		NAND memory page size
	//						when [3]==0, 0:256, 1:512 bytes/page.
	//						when [3]==1, 0:1024, 1:2048 bytes/page.
	// AddrCycle(R)	[1]		NAND flash addr size
	//						when [3]==0, 0:3-addr, 1:4-addr.
	//						when [3]==1, 0:4-addr, 1:5-addr.
	// BusWidth(R/W) [0]	NAND bus width. 0:8-bit, 1:16-bit.
	
	rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
	// Lock-tight	[13]	0:Disable lock, 1:Enable lock.
	// Soft Lock	[12]	0:Disable lock, 1:Enable lock.
	// EnablillegalAcINT[10]	Illegal access interupt control. 0:Disable, 1:Enable
	// EnbRnBINT	[9]		RnB interrupt. 0:Disable, 1:Enable
	// RnB_TrandMode[8]		RnB transition detection config. 0:Low to High, 1:High to Low
	// SpareECCLock	[6]		0:Unlock, 1:Lock
	// MainECCLock	[5]		0:Unlock, 1:Lock
	// InitECC(W)	[4]		1:Init ECC decoder/encoder.
	// Reg_nCE		[1]		0:nFCE=0, 1:nFCE=1.
	// NANDC Enable	[0]		operating mode. 0:Disable, 1:Enable.
    
	NAND_reset();
}


void spin_wheel(void)
{
	static int p = 0;
	static char w[] = "\\/-";
	Uart_Printf("\010%c", w[p]);
	(++p==3)?(p=0):0;
}


int NAND_readID(void){
	int i;
	int id = 0;

	NF_nFCE_L();
    NF_CMD(NAND_CMD_READID);
	NF_ADDR(0x0);
	for (i=0; i<10; i++);
	id  = NF_RDDATA8()<<8;	// Maker code : 0xec
	id |= NF_RDDATA8();		// Devide code(K9S1208V:0x76), (K9K2G16U0M:0x75)
	NF_nFCE_H();

	return (id & 0xffff);
}


void NAND_check_block(U32 blk_max_cnt)
{
	int i, start, end, badblock;
	
	NAND_init();
	badblock = 0;
	Uart_Printf("block number must be between 0 and %d\n",blk_max_cnt-1);
	Uart_Printf("Select the number of start block to check: ");
	start = Uart_GetIntNum();
	if( (start<0) || (start>blk_max_cnt) ){
		Uart_Printf("/n/nStart block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
		return;
	}
	Uart_Printf("\nSelect the number of end block to check: ");
	end = Uart_GetIntNum();
	if( (end<0) || (end>blk_max_cnt) ){
		Uart_Printf("/n/nEnd block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
		return;
	}
	
	Uart_Printf("\n\nDisplay block status\n");
	for(i=start;i<end;i++){
		Uart_Printf("%4d",i);
		if(NAND_check_badblock(i) == 1){
			Uart_Printf("\b\b\b\b");
			Uart_Printf("BLOCK[%4d] is bad\n",i);
			badblock++;
		}else{
			if(i != end)	Uart_Printf("\b\b\b\b");
		}
	}
	if(badblock == 0)
		Uart_Printf("\nBLOCK[%d] ~ BLOCK[%d] is good..\n", start, end);
	else
		Uart_Printf("%d blocks is bad block..\n", badblock);

	Uart_Printf("\nBlock check has been done..\n\n\n");	
	
}

int NAND_check_badblock(U32 block)
{
	int i, blockpage = block * NAND_PAGE_COUNT;
	U8 data;
	
	NF_nFCE_L();
	NF_CLEAR_RB();
	NF_CMD(NAND_CMD_READOOB);
	NF_ADDR(517 & 0xf);
	NF_ADDR(blockpage & 0xff);
	NF_ADDR((blockpage >> 8) & 0xff);
	NF_ADDR((blockpage >> 16) & 0xff);
	for(i=0;i<10;i++);
	NF_DETECT_RB();
	data = NF_RDDATA8();
	NF_nFCE_H();
	
	if(data != 0xff)	return 1;	//is bad block
	else				return 0;	//isn't bad block
}


int NAND_mark_badblock(U32 block)
{
	int i;
	U32 blockpage = block * NAND_PAGE_COUNT;
	
	seBuf[0]=0xff;
	seBuf[1]=0xff;
	seBuf[2]=0xff;
	seBuf[5]=0x44;   // Bad blcok mark=0
	
	NF_nFCE_L();
    NF_CMD(NAND_CMD_READOOB);	
    NF_CMD(NAND_CMD_SEQIN);

	NF_ADDR(0x0);
	NF_ADDR(blockpage&0xff);
    NF_ADDR((blockpage>>8)&0xff);
    NF_ADDR((blockpage>>16)&0xff);
    
    for(i=0;i<NAND_OOB_SIZE;i++)	NF_WRDATA8(seBuf[i]);
    
    NF_CMD(NAND_CMD_PAGEPROG);
    for(i=0;i<10;i++); 
	NF_DETECT_RB();
	NF_CMD(NAND_CMD_STATUS);
	
	for(i=0;i<3;i++);
	
	if(NF_RDDATA8() & 0x1){
		NF_nFCE_H();	//spare array write error
//		Uart_printf("[Marking badblock is error!!]\n");
	}else{
		NF_nFCE_H();	// block is marked as bad block
	}
	return 1;
}


void NAND_erase(U32 blk_max_cnt){
	int i, start, end, erase_err;
	
	Uart_Printf("NAND flash Erase Test\n");
	Uart_Printf("\nYou MUST be well aware that\n");
	Uart_Printf("1. the block size of NAND flash is 0x%x\n", NAND_BLOCK_SIZE);
	Uart_Printf("2. the page size of NAND flash is 0x%x\n", NAND_PAGE_SIZE);
	
	NAND_init();
	erase_err = 0;
	
	Uart_Printf("\n\nblock number must be between 0 and %d\n",blk_max_cnt-1);
	Uart_Printf("Select the number of start block to erase: ");
	start = Uart_GetIntNum();
	if( (start<0) || (start>blk_max_cnt) ){
		Uart_Printf("/n/nStart block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
		return;
	}
	Uart_Printf("\nSelect the number of end block to erase: ");
	end = Uart_GetIntNum();
	if( (end<0) || (end>blk_max_cnt) ){
		Uart_Printf("/n/nEnd block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
		return;
	}
	
	if(start>end){
		Uart_Printf("start block number is bigger than end block number.. Try again\n");
		return;
	}
	
	Uart_Printf("\n\nStart Erasing block\n");
	for(i=start;i<=end;i++){
		Uart_Printf("%4d",i);
		if(NAND_erase_block(i) == 1){
			Uart_Printf("\b\b\b\b");
			Uart_Printf("%4d:ERROR!!\n", i);
			erase_err++;
		}else{
			if(i != end)	Uart_Printf("\b\b\b\b");
		}
	}
	if(erase_err == 0)
		Uart_Printf("\nBLOCK[%d] ~ BLOCK[%d] is erased..\n", start, end);
		
	Uart_Printf("\nBlock erase has been done..\n\n\n");
}

int NAND_erase_block(U32 block)
{
	int i;
	U32 blockpage = block * NAND_PAGE_COUNT;
	
	NF_nFCE_L();
	NF_CLEAR_RB();
	
	NF_CMD(NAND_CMD_ERASE1);
	NF_ADDR(blockpage & 0xff);
    NF_ADDR((blockpage >> 8) & 0xff);   
    NF_ADDR((blockpage >> 16) & 0xff);
	NF_CMD(NAND_CMD_ERASE2);
	for(i=0;i<40;i++);
	NF_DETECT_RB();
	NF_CMD(NAND_CMD_STATUS);
	
	if(NF_RDDATA8() & 0x1) // Erase error
    {	
    	NF_nFCE_H();
		NAND_mark_badblock(block);
		return 1;
    }else{
    	NF_nFCE_H();
        return 0;
    }
}


void NAND_read(U32 blk_max_cnt)
{
	U32 s_blk_num, i;
	U8 *buf;
	
	Uart_Printf("NAND flash Read Test\n");
	Uart_Printf("This test reads data from NAND flash and copies data to memory\n");
	Uart_Printf("This test reads only one block you select\n");
	Uart_Printf("\nYou MUST be well aware that\n");
	Uart_Printf("1. the block size of NAND flash is 0x%x\n", NAND_BLOCK_SIZE);
	Uart_Printf("2. the page size of NAND flash is 0x%x\n", NAND_PAGE_SIZE);
	
	Uart_Printf("\n\nblock number must be between 0 and %d\n",blk_max_cnt-1);
	Uart_Printf("Select the number of block to read: ");
	s_blk_num = Uart_GetIntNum();
	if( (s_blk_num<0) || (s_blk_num>blk_max_cnt) ){
		Uart_Printf("/n/nStart block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
		return;
	}
	
	Uart_Printf("\nInput the target address to copy in memory[0x...]: ");
    buf = (U8 *)Uart_GetIntNum();
	Uart_Printf("\n\n");
	
	Uart_Printf("Read data from %d block and copy data to 0x%x\n", s_blk_num, (int)buf);
	if(NAND_read_block(s_blk_num, buf) == 1){
		Uart_Printf("\nThis block is bad block\n");
	}else{
		Uart_Printf("\nReading block is completed\n");
	}

	Uart_Printf("\n\nDisplay data you read(page 0 of block %d) :", s_blk_num);
	for(i=0;i<NAND_PAGE_SIZE/4;i++){
		if(i%8==0)	Uart_Printf("\n");
		Uart_Printf("%08lx ", *(U32 *)(buf+(i*4)));
	}

	Uart_Printf("\n\n");
}


int NAND_read_block(U32 b_num, U8 *dst_addr)
{
	U8 *buf = dst_addr;
	char page_buf[NAND_PAGE_SIZE];
	int i;
	
	if(NAND_check_badblock(b_num))	return 1;
	
	for(i=0;i<NAND_PAGE_COUNT;i++){
		NAND_read_page(b_num, i, buf);
		spin_wheel();
	}
	return 0;
}


int NAND_read_page(U32 block, U32 page, U8 *buffer)
{
	U32 blockpage = (block*NAND_PAGE_COUNT)+(page&0x1f);
	int i, ecc;
	U8 *bufPt = buffer;
	U8 se[16], ecc0, ecc1, ecc2;
	
	NF_RSTECC();
	NF_MECC_UnLock();
	
	NF_nFCE_L();
	NF_CLEAR_RB();
	NF_CMD(NAND_CMD_READ0);
	NF_ADDR(0);
	NF_ADDR(blockpage&0xff);
	NF_ADDR((blockpage>>8)&0xff);
	NF_ADDR((blockpage>>16)&0xff);
	NF_DETECT_RB();
	
	for(i=0;i<NAND_PAGE_SIZE;i++)	*bufPt++ = NF_RDDATA8();
	
	NF_nFCE_H();

    return 0;
}


void NAND_write(U32 blk_max_cnt)
{
	U32 s_blk_num, i;
	U8 *buf;
	
	Uart_Printf("NAND flash Write Test\n");
	Uart_Printf("This test reads data from memory and writes data to NAND flash\n");
	Uart_Printf("This test writes only one block you select\n");
	Uart_Printf("\nYou MUST be well aware that\n");
	Uart_Printf("1. the block size of NAND flash is 0x%x\n", NAND_BLOCK_SIZE);
	Uart_Printf("2. the page size of NAND flash is 0x%x\n", NAND_PAGE_SIZE);
	
	Uart_Printf("\n\nblock number nust be between 0 and %d\n",blk_max_cnt-1);
	Uart_Printf("Select the number of block to write: ");
	s_blk_num = Uart_GetIntNum();
	if( (s_blk_num<0) || (s_blk_num>blk_max_cnt) ){
		Uart_Printf("/n/nStart block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
		return;
	}
	
	Uart_Printf("\nInput the source data address to read in memory[0x...]: ");
    buf = (U8 *)Uart_GetIntNum();
	Uart_Printf("\n\n");
	
	Uart_Printf("Read data from 0x%x and copy data to %d block\n", (int)buf, s_blk_num);
	if(NAND_write_block(s_blk_num, buf) == 1){
			Uart_Printf("\nThis block is bad block\n");
	}else{
		Uart_Printf("\nWriting block is completed\n");
	}
	
	Uart_Printf("\n\nDisplay data you write(page 0 of block %d) :", s_blk_num);
	for(i=0;i<NAND_PAGE_SIZE/4;i++){
		if(i%8==0)	Uart_Printf("\n");
		Uart_Printf("%08lx ", *(U32 *)(buf+(i*4)));
	}
	
	Uart_Printf("\n\n");
}


int NAND_write_block(U32 b_num, U8 *src_addr)
{
	U8 *buf = src_addr;
	char page_buf[NAND_PAGE_SIZE];
	int i;
	
	if(NAND_check_badblock(b_num))	return 1;
	
	for(i=0;i<NAND_PAGE_COUNT;i++){
		NAND_write_page(b_num, i, buf);
		spin_wheel();
	}
		
	return 0;
}


int NAND_write_page(U32 block, U32 page, U8 *buffer)
{
	U32 blockpage = (block*NAND_PAGE_COUNT)+(page&0x1f);
	int i;
	U8 *bufPt = buffer;
	U32 mecc, secc;

	NF_SOFT_UnLock();
	NF_RSTECC();
	NF_MECC_UnLock();
	
	NF_nFCE_L();
	NF_CLEAR_RB();
	NF_CMD(NAND_CMD_READ0);
	NF_CMD(NAND_CMD_SEQIN);
	NF_ADDR(0);
	NF_ADDR(blockpage&0xff);
	NF_ADDR((blockpage>>8)&0xff);
	NF_ADDR((blockpage>>16)&0xff);
	
	for(i=0;i<NAND_PAGE_SIZE;i++)	NF_WRDATA8(*bufPt++);
	
	NF_MECC_Lock();
	mecc = rNFMECC0;
	seBuf[0] = (U8)(mecc & 0xff);
	seBuf[1] = (U8)((mecc>>8) & 0xff);
	seBuf[2] = (U8)((mecc>>16) & 0xff);
	seBuf[3] = (U8)((mecc>>24) & 0xff);
	seBuf[5] = 0xff;

	NF_SECC_UnLock();
	for(i=0;i<3;i++){
		NF_WRDATA8(seBuf[i]);
	}
	
	NF_SECC_Lock();
	secc = rNFSECC;
	seBuf[8] = (U8)(secc & 0xff);
	seBuf[9] = (U8)((secc>>8) & 0xff);
	for(i=3;i<16;i++){
		NF_WRDATA8(seBuf[i]);
	}
	
	NF_CLEAR_RB();
	NF_CMD(NAND_CMD_PAGEPROG);	 // Write 2nd command
	for(i=0;i<10;i++);
	NF_DETECT_RB();
	NF_CMD(NAND_CMD_STATUS);   // Read status command   

	for(i=0;i<3;i++);  //twhr=60ns
	if (NF_RDDATA8()&0x1){// Page write error
		NF_nFCE_H();
		Uart_Printf("\n[WRITE ERROR:block#=%d]\n",block);
		NAND_mark_badblock(block);
       }else{
		NF_nFCE_H();
	}
	return 0;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -