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

📄 nand.c

📁 DMA-2442开发板bootloader
💻 C
📖 第 1 页 / 共 4 页
字号:
	rNFCMD = NAND_CMD_ERASE2;
	//for(i=0;i<40;i++);
	//NF_DETECT_RB();
	//rNFCMD = NAND_CMD_STATUS;

	stat = WaitNFBusy();
	NFChipDs();
	return OK;
#if 0
	if (NF_RDDATA() & 0x1) {
		NF_nFCE_H();
		printf("[ERASE_ERROR:block#=%d]\n",block);
		//NF_MarkBadBlock(block);
		return FAIL;
	}
	else {
		NF_nFCE_H();
		return OK;
	}
#endif
}

#endif
static int NF_IsBadBlock(U32 block)
{
	int i;
	unsigned int blockPage;
	U8 data;

	blockPage = block * cpages_in_block ; 

	//NF_RSTECC();
	NF_nFCE_L();
	NF_CLEAR_RB();

	if (cpage2Kis) {
		rNFCMD = NAND_CMD_READ0;
		rNFADDR = cpage_size & 0xff;
		rNFADDR = (cpage_size >> 8) & 0x0f;    // The mark of bad block is in 0 page
		rNFADDR = blockPage  & 0xff;   // For block number A[24:17]
		rNFADDR = (blockPage >> 8) & 0xff;  // For block number A[25]
	        rNFCMD = NAND_CMD_READSTART;
	}
	else {
		rNFCMD = NAND_CMD_READOOB;
		rNFADDR = 517 & 0xf;
		rNFADDR = blockPage & 0xff;    // The mark of bad block is in 0 page
		rNFADDR = (blockPage >> 8) & 0xff;   // For block number A[24:17]
		rNFADDR = (blockPage >> 16) & 0xff;  // For block number A[25]
	}

	for(i=0;i<10;i++);  /* dummy check me */
	NF_DETECT_RB();

	data=NF_RDDATA();

	NF_nFCE_H();
	//printf("NF_IsBadBlock:data =%x\n",data);
	if(data != 0xff)
	{
		printf("[block %d has been marked as a bad block(%x)]\n",block,data);
		return 1;
	}
	else
	{
		return 0;
	}
}
/*
 * Read data from NAND.
 */
int
s3c244x_nand_read(U32 targetBlock,U32 targetSize, U32 srcAddress)
{


	int i;
	//int programError=0;
	U8 *srcPt,*saveSrcPt;
	U32 blockIndex;
#if 0
	printf("NAND Flash reading\n");
	printf("Source base address    =0x%x\n",srcAddress);
	printf("Target start block num =%x\n",targetBlock);
	printf("Target size            =0x%x\n",targetSize);
	printf("block read :\n");
#endif
	srcPt=(U8 *)srcAddress;
	blockIndex=targetBlock;
	while(1) {
		saveSrcPt=srcPt;	
#if BAD_CHECK       
		if(NF_IsBadBlock(blockIndex)) {	// 1:bad 0:good
			blockIndex++;   // for next block
			continue;
		}
#endif
	
		for(i=0; i< cpages_in_block ;i++) {
			if(!NF_ReadPage(blockIndex,i,srcPt)) {
					printf("ECC Error(block=%d,page=%d!!!\n",(int)blockIndex,i);
					
				}			
			srcPt += cpage_size;
			//printf(".");
		
		}
		//printf("srcPt = %x",srcPt);

		//printf( "%X ", blockIndex );

		//if (!( blockIndex % 16 )) printf(".");
		
		//printf( "%X ", blockIndex );

		if((U32)srcPt>=(srcAddress+targetSize))
			break;	// Exit while loop		
		blockIndex++;
	}

	//printf("\n\n");
	return 0;
}

static int s3c244x_nand_write(U32 targetBlock,U32 targetSize, U32 srcAddress )
{
	int i,j;
	int programError=0;
	U8 *srcPt,*saveSrcPt;
	U8 *dstPt=(U8*)0x33000000;
	U32 blockIndex;

	printf("NAND Flash writing\n");
	printf("Source base address    =0x%x\n",srcAddress);
	printf("Target start block num =%d\n",targetBlock);
	printf("Target size            =0x%x\n",targetSize);
	printf("block writed :\n");

	srcPt=(U8 *)srcAddress;
	blockIndex=targetBlock;
	while(1) {
		saveSrcPt=srcPt;	
#if BAD_CHECK       
		if(NF_IsBadBlock(blockIndex)) {	// 1:bad 0:good
			blockIndex++;   // for next block
			continue;
		}
#endif
		if(!NF_EraseBlock(blockIndex)) {
			blockIndex++;   // for next block
			printf(" Error->  Erase Block %d  \n",(int)blockIndex);
			continue;
		}

		for(i=0; i< cpages_in_block ;i++) {
			if(!NF_WritePage(blockIndex,i,srcPt)) {
				// block num, page num, buffer
				programError=1;
				break;
			}
		
#if ECC_CHECK    

	
				if(!NF_ReadPage(blockIndex,i,srcPt)) {
					printf("ECC Error(block=%d,page=%d!!!\n",(int)blockIndex,i);
				}
				for(j=0;j<2048;j++)
			{
				//if(i==0)
					//printf("srcpt=%x,dstpt=%x\n",srcPt[j],dstPt[j]);
				if(srcPt[j]!=dstPt[j])
					printf("Error:%x\n",srcPt[j]);
			}
			
#endif	    
		
					
			srcPt += cpage_size;
			//printf(".");
			if((U32)srcPt>=(srcAddress+targetSize)) // Check end of buffer
				break;	// Exit for loop
		}
		if(programError==1) {
			blockIndex++;
			srcPt=saveSrcPt;
			programError=0;
			continue;
		}

		printf( "%X ", blockIndex );

		if (!( blockIndex % 16 )) printf("\n");
		if((U32)srcPt>=(srcAddress+targetSize))
			break;	// Exit while loop
		blockIndex++;
	}

	printf("\n\n");
	return 0;
}

/************************************************************/
/************************************************************/

struct Partition{
	U32 offset;
	U32 size;
	char *name;
};
/*********************************************************************
type			page_size  	obb_size  	pages_in_block 	block_size	block_num
K9F1208			512		16			32				16K			4096
K9F1G08			2048	64			64				128K		1024
***********************************************************************/
/**************************************************************
partition:		
boot:		0						0x00030000	256k	
kernel:		0x00030000				0x001d0000	
rootfs		0x00200000				0x01e00000	30M
extfs		0x02000000				0x02000000	32M
*************************************************************/
/************************************************************/

static struct Partition K9f1208_Part[] = {
	{0, 		 0x00030000, "boot"},		//196K
	{0x00030000, 0x001d0000, "kernel"},
	{0x00200000, 0x01e00000, "rootfs"},		//30M
	{0x02000000, 0x02000000, "ext-fs1"},	//32M
	{0,			 0         , 0}
};

static struct Partition K9f1g08_Part[] = {
	{0, 		 0x00040000, "boot"},		//256K
	{0x00040000, 0x00200000, "kernel"},	// 2m-256k
	{0x00200000, 0x01e00000, "rootfs"},		//30M
	{0x02000000, 0x02000000, "ext-fs1"},	//32M
	{0,			 0         , 0}
};

static struct Partition *NAND_PART;


static void Test_Write(void)
{

U32 block=0, page=0;
	U32 i, status=FAIL, error, offset;
	unsigned char *srcPt, *dstPt;
	srcPt=(unsigned char *)0x31100000;
	dstPt=(unsigned char *)0x31200000;
		
	Uart_Printf("(K9F1G08) NAND Flash R/W test.\n");

	Uart_Printf("Block number: ");
	block = Uart_GetIntNum();
	Uart_Printf("Page nember: ");
	page = Uart_GetIntNum();
	Uart_Printf("offset data(-1:random): ");
	offset = Uart_GetIntNum();


	
	// Init R/W data.
	for(i=0; i<2048; i++) *dstPt++=0x0;

	for(i=0; i<2048; i++) {

		if(offset==-1) *srcPt++ = i%0xff;
		else *srcPt++ = i+offset;
	}
	


	srcPt=(unsigned char *)0x31100000;
	dstPt=(unsigned char *)0x31200000;
	// Block erase
	Uart_Printf("%d block erase.\n", block);
	if(NF_EraseBlock(block)==FAIL) return;

	Uart_Printf("Write data[%d block, %d page].\n", block, page);
	if(NF_WritePage(block, page, srcPt)==FAIL) return;
	
	Uart_Printf("Read data.\n");
	if(NF_ReadPage(block, page, dstPt)==FAIL) return;

	Uart_Printf("Checking data.\n");
	for(error=0, i=0; i<2048; i++) {
		if(*srcPt++!=*dstPt++) {
			Uart_Printf("Error:%d[W:%x,R:%x]\n", i, *srcPt, *dstPt);
			error++;
		}
	}
	if(error!=0) 
		Uart_Printf("Fail to R/W test(%d).\n", error);
	else
		Uart_Printf("R/W test OK.\n");

#if 0
	U8 *dstPt;
	U8 *srcPt;
	U32 i;
	
	for(i=0;i<2048;i++)
	{
		*srcPt++ = (i&0xff);
	}
	
	srcPt=(unsigned char *)0x31100000;
	dstPt=(unsigned char *)0x31300000;
	NF_WritePage(0,0,srcPt);
	NF_ReadPage(0,0,dstPt);
	for(i=0;i<2048;i++)
	{
		if(*srcPt++!=*dstPt++)
		{
			printf("Error:%d[W:%x,R:%x]\n", i, *srcPt, *dstPt);

		}
	}
	printf("R/W test Ok!\n");
	#endif
}
/*
static void TestFunc(void)
{
	U32 i;
	U8 buf[512];
	
	if(EraseBlock(0x180))
		return;
	
	for(i=0; i<512; i++)
		buf[i] = i;
		
	WritePage(0x180, buf);	
	for(i=0; i<512; i++)
		buf[i] = 0;
	ReadPage(0x180, buf);
	
	for(i=0; i<512; i++)
		printf("%4x", buf[i]);
}
*/
static U32 StartBlock, BlockCnt;
extern U32 downloadAddress; 
extern U32 downloadFileSize;


static int NandSelPart(char *info)
{
	U16 i, max_sel;
	struct Partition *ptr = NAND_PART;
	
	printf("Please select which region to %s : Esc to abort\n", info);
	
	for(i=0; ptr->size!=0; i++, ptr++)
		printf("%d : offset 0x%-8x, size 0x%-8x [%s]\n", i, ptr->offset, ptr->size, ptr->name);
		
	max_sel = i;
	
	while(1) {
		i = getch();
		if(i==0x1b)
			return -1;
		if((i>='0')&&(i<(max_sel+'0'))) {
			i -= '0';
			StartBlock = NAND_PART[i].offset>>block_offset;
			BlockCnt  = NAND_PART[i].size>>block_offset;
			printf("StartBlock=%x,BlockCnt=%d",StartBlock,BlockCnt);

			return i;
		}
	}	
}

static void WrFileToNF(void)
{
	int nf_part ,size,block;
	U32 ram_addr;
	
	nf_part = NandSelPart("write");
	if(nf_part<0)
		return;	
	
	if(downloadFileSize>NAND_PART[nf_part].size) {
		puts("Download file size is more large than selected partition size!!!\n");
		return;
	}
	
	printf("Now write nand flash page 0x%x from ram address 0x%x, filesize = %d\n", StartBlock, downloadAddress, downloadFileSize);
	puts("Are you sure? [y/n]\n");
	while(1) {
		char c = getch();
		if((c=='y')||(c=='Y'))
			break;
		if((c=='n')||(c=='N'))			
			return;
	}
	
	block = StartBlock;

	ram_addr = downloadAddress;
	size = downloadFileSize;

	s3c244x_nand_write(block, size,ram_addr);
	puts("Program nand flash partition success\n");
}




#define LINUX_PAGE_SHIFT	12
#define LINUX_PAGE_SIZE		(1<<LINUX_PAGE_SHIFT)
#define COMMAND_LINE_SIZE 	1024

struct param_struct {
    union {
	struct {
	    unsigned long page_size;			/*  0 */
	    unsigned long nr_pages;				/*  4 */
	    unsigned long ramdisk_size;			/*  8 */
	    unsigned long flags;				/* 12 */
#define FLAG_READONLY	1
#define FLAG_RDLOAD		4
#define FLAG_RDPROMPT	8
	    unsigned long rootdev;				/* 16 */
	    unsigned long video_num_cols;		/* 20 */
	    unsigned long video_num_rows;		/* 24 */
	    unsigned long video_x;				/* 28 */
	    unsigned long video_y;				/* 32 */
	    unsigned long memc_control_reg;		/* 36 */
	    unsigned char sounddefault;			/* 40 */
	    unsigned char adfsdrives;			/* 41 */
	    unsigned char bytes_per_char_h;		/* 42 */
	    unsigned char bytes_per_char_v;		/* 43 */
	    unsigned long pages_in_bank[4];		/* 44 */
	    unsigned long pages_in_vram;		/* 60 */
	    unsigned long initrd_start;			/* 64 */
	    unsigned long initrd_size;			/* 68 */
	    unsigned long rd_start;				/* 72 */
	    unsigned long system_rev;			/* 76 */
	    unsigned long system_serial_low;	/* 80 */
	    unsigned long system_serial_high;	/* 84 */
	    unsigned long mem_fclk_21285;       /* 88 */
	} s;
	char unused[256];
    } u1;
    union {
	char paths[8][128];
	struct {
	    unsigned long magic;
	    char n[1024 - sizeof(unsigned long)];
	} s;
    } u2;
    char commandline[COMMAND_LINE_SIZE];
};

extern void  call_linux(U32 a0, U32 a1, U32 a2);

/*************************************************************/
static __inline void cpu_arm920_cache_clean_invalidate_all(void)
{
	__asm{
		mov	r1, #0		
		mov	r1, #7 << 5			  	/* 8 segments */
cache_clean_loop1:		
		orr	r3, r1, #63UL << 26	  	/* 64 entries */
cache_clean_loop2:	
		mcr	p15, 0, r3, c7, c14, 2	/* clean & invalidate D index */
		subs	r3, r3, #1 << 26
		bcs	cache_clean_loop2		/* entries 64 to 0 */
		subs	r1, r1, #1 << 5
		bcs	cache_clean_loop1		/* segments 7 to 0 */
		mcr	p15, 0, r1, c7, c5, 0	/* invalidate I cache */
		mcr	p15, 0, r1, c7, c10, 4	/* drain WB */
	}
}
void cache_clean_invalidate(void)
{
	cpu_arm920_cache_clean_invalidate_all();
}

static __inline void cpu_arm920_tlb_invalidate_all(void)
{
	__asm{
		mov	r0, #0
		mcr	p15, 0, r0, c7, c10, 4	/* drain WB */
		mcr	p15, 0, r0, c8, c7, 0	/* invalidate I & D TLBs */
	}
}

void tlb_invalidate(void)
{
	cpu_arm920_tlb_invalidate_all();
}

void disable_irq(void);

void call_linux(U32 a0, U32 a1, U32 a2)
{
	void (*goto_start)(U32, U32);
	
	rINTMSK=BIT_ALLMSK;
	
	cache_clean_invalidate();

⌨️ 快捷键说明

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