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

📄 nand.c

📁 s3c44b0的应用程序
💻 C
字号:
#include "..\inc\def.h"
#include "..\inc\44b.h"
#include "..\inc\44blib.h"
#include "..\pro\nand.h"

#define	NAND_SUPPORT
#ifdef	NAND_SUPPORT
#define	LINUX_KERNEL_ADDR	0x0c000000
#define	INITRD_START		0x0c200000
#define	BOOT_PORG_ADDR		0x0c400000

struct NFChipInfo {
	U32 id;
	U32 size;
}static NandFlashChip[4] = {
	{0xec73, SIZE_16M},
	{0xec75, SIZE_32M},
	{0xec76, SIZE_64M},
	{0, 0},
};

struct Partition{
	U32 offset;
	U32 size;
	char *name;
};

struct Partition NandPartition[6] = {
	{0x00000000, 0x00200000, "boot"},
	{0x00200000, 0x00200000, "kernel"},
	{0x00400000, 0x00200000, "rootfs"},
	{0x00600000, 0x00200000, "ext-fs1"},
	{0x00800000, 0x00200000, "ext-fs2"},
	{0x00000000, 0x00000000, 0}
};

/*
EQU		R/B(READY/BUSY)		PC0
EQU		/CEB(CHIP_ENABLE)	PC1
EQU		CLE(COMMAND)		PC2
EQU		ALE(ADDRESS)		PC3	
WEB		SMCWE	NGCS1	0X02000000
REB		SWCOE	NGCS1	0X02000000
EQU		WPB		VDD
EQU		SEB		GND	
*/

U32 NandFlashSize;
static U16 NandAddr;
static U16 HaveNandChip;
#define	NAND_DAT	0x02000000
#define NAND_CLE(t)	(t?(rPDATC |= 1<<2):(rPDATC &= ~(1<<2)))
#define NAND_ALE(t)	(t?(rPDATC |= 1<<3):(rPDATC &= ~(1<<3)))
#define	READCMD0	0
#define	READCMD1	1
#define	READCMD2	0x50
#define	ERASECMD0	0x60
#define	ERASECMD1	0xd0
#define	PROGCMD0	0x80
#define	PROGCMD1	0x10
#define	QUERYCMD	0x70
#define	READIDCMD	0x90
#define	NFChipEn()	(rPDATC &= ~(1<<1))
#define	NFChipDs()	(rPDATC |= 1<<1)
#define	NFIsBusy()	(!(rPDATC&(1)))
#define	WrNFDat(dat)	*(volatile U8 *)NAND_DAT = (dat)
#define	RdNFDat()		*(volatile U8 *)NAND_DAT

//#define	WIAT_BUSY_HARD	0
//#define	ER_BAD_BLK_TEST	0
//#define	WR_BAD_BLK_TEST	0
#ifdef	WIAT_BUSY_HARD
#define	WaitNFBusy()	while(NFIsBusy())
#else

void WrNFCmd(cmd)
{
	NAND_CLE(1);
	*(volatile U8 *)NAND_DAT = (cmd);
	NAND_CLE(0);
}

void WrNFAddr(addr)
{
	NAND_ALE(1);
	*(volatile U8 *)NAND_DAT = (addr);
	NAND_ALE(0);
}

static U32 WaitNFBusy(void)
{
	U8 stat;
		WrNFCmd(QUERYCMD);
	do {
		stat = RdNFDat();
		//Uart_Printf("%x\n", stat);
	}while(!(stat&0x40));
	WrNFCmd(READCMD0);
	return stat&1;
}
#endif
static U32 NFReadID(void)
{
	U32 id, loop = 0;
	NFChipEn();
	WrNFCmd(READIDCMD);
	WrNFAddr(0);
	while(NFIsBusy()&&(loop<10000)) loop++;
	if(loop>=10000)
		return 0;
	id  = RdNFDat()<<8;
	id |= RdNFDat();
	NFChipDs();
		return id;
}
static U16 NFReadStat(void)
{
	U16 stat;
		NFChipEn();	
	WrNFCmd(QUERYCMD);
	stat = RdNFDat();	
	NFChipDs();
		return stat;
}
static U32 NFEraseBlock(U32 addr)
{
	U8 stat=1;
	addr &= ~0x1f;                   //????????????????
	NFChipEn();	
	WrNFCmd(ERASECMD0);	
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
	WrNFCmd(ERASECMD1);	
	stat = WaitNFBusy();
	NFChipDs();
	#ifdef	ER_BAD_BLK_TEST
	if(!((addr+0xe0)&0xff)) stat = 1;	//just for test bad block      ????????????
#endif
		Uart_Printf("Erase block 0x%08x %s\n", addr, stat?"fail":"ok");
		return stat;
}
//addr = page address
static void NFReadPage(U32 addr, U8 *buf)
{
	U16 i;
		NFChipEn();
	WrNFCmd(READCMD0);
	WrNFAddr(0);
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
//	InitEcc();
	WaitNFBusy();		
	for(i=0; i<512; i++)
		buf[i] = RdNFDat();	
 //   WrNFCmd(READCMD1);
//	WrNFAddr(0);
//	WrNFAddr(addr);
//	WrNFAddr(addr>>8);
//	if(NandAddr)
//		WrNFAddr(addr>>16);
//	InitEcc();
//	WaitNFBusy();		
//	for(i=256; i<512; i++)
//		buf[i] = RdNFDat();		
		NFChipDs();
}
//addr = page address
static U32 NFWritePage(U32 addr, U8 *buf)
{
	U16 i, stat;
//	U8 tmp[3];

		NFChipEn();
//	WrNFCmd(READCMD0);	
	WrNFCmd(PROGCMD0);
	WrNFAddr(0);
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
	WrNFAddr(addr>>16);
//	InitEcc();	
	for(i=0; i<512; i++)
		WrNFDat(buf[i]);
		/*	tmp[0] = rNFECC0;
    tmp[1] = rNFECC1;
    tmp[2] = rNFECC2;
    		WrNFDat(tmp[0]);
    WrNFDat(tmp[1]);
    WrNFDat(tmp[2]);*/
   	WrNFCmd(PROGCMD1);
	stat = WaitNFBusy();
/*	WrNFCmd(READCMD1);
	WrNFCmd(PROGCMD0);
	WrNFAddr(0);
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
	WrNFAddr(addr>>16);
//	InitEcc();	
	for(i=0; i<256; i++)
		WrNFDat(buf[i]);
		/*	tmp[0] = rNFECC0;
    tmp[1] = rNFECC1;
    tmp[2] = rNFECC2;
    		WrNFDat(tmp[0]);
    WrNFDat(tmp[1]);
    WrNFDat(tmp[2]);
   	WrNFCmd(PROGCMD1);
   	stat = WaitNFBusy();    */
	NFChipDs();
	#ifdef	WR_BAD_BLK_TEST
	if((addr&0xff)==0x17) stat = 1;	//just for test bad block
#endif
		if(stat)
		Uart_Printf("Write nand flash 0x%x fail\n", addr);
	else {	
		U8 RdDat[512];
				NFReadPage(addr, RdDat);
		for(i=0; i<512; i++)
			if(RdDat[i]!=buf[i]) {
				Uart_Printf("Check data at page 0x%x, offset 0x%x fail\n", addr, i);
				stat = 1;
				break;
			}
	}
			return stat;	
}
static void NFMarkBadBlk(U32 addr)
{
	addr &= ~0x1f;
		NFChipEn();
		WrNFCmd(READCMD2);	//point to area c
		WrNFCmd(PROGCMD0);
	WrNFAddr(6);		//mark offset 6,7
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
	WrNFDat(0);			//mark with 0
	WrNFDat(0);
	WrNFCmd(PROGCMD1);
	WaitNFBusy();		//needn't check return status
		WrNFCmd(READCMD0);	//point to area a
			NFChipDs();
}
static int NFChkBadBlk(U32 addr)
{
	U8 dat;
		addr &= ~0x1f;
		NFChipEn();
		WrNFCmd(READCMD2);	//point to area c
	WrNFAddr(6);		//mark offset 6,7
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
	WaitNFBusy();
	dat = RdNFDat();
		WrNFCmd(READCMD0);	//point to area a
		NFChipDs();
	return (dat!=0xff);
}

static struct Partition *NandPartSel(char *info)
{
	int i, max_sel;
	Uart_Printf("Please select Nand flash region to %s, Esc to abort\n", info);
		for(i=0; NandPartition[i].size; i++)
		Uart_Printf("%d : start 0x%08x, size 0x%08x\t[part%d]\n", i, 

NandPartition[i].offset, NandPartition[i].size, i/*NandPartition[i].name*/);
	max_sel = i;	
		while(1) {
		char c = Uart_Getch();
				if(c==0x1b)     //"enter" key
			return 0;
		if((c>='0')&&(c<(max_sel+'0')))
			return &(NandPartition[c-'0']);
	}	
}

static void NFReadPart(struct Partition *part, U8 *buf)
{
	U32 i, start_page;
	U8 *ram_addr;
	int size;
		start_page = part->offset>>9;
	size = part->size;
	ram_addr = buf;
		for(i=0; size>0; ) {
		if(!(i&0x1f)) {
			if(NFChkBadBlk(i+start_page)) {
				Uart_Printf("Skipped bad block at 0x%08x\n", i+start_page);
				i += 32;
				size -= 32<<9;
				continue;
			}
		}
		NFReadPage((i+start_page), ram_addr);
		i++;
		size -= 512;
		ram_addr += 512;
	}
}
#endif	/* NAND_SUPPORT */

int getyorn()
{
	while(1)
	{
		char c = Uart_Getch();
		if((c=='y')||(c=='Y'))
			return 0;
		if((c=='n')||(c=='N'))
			return 1;
	}
}

/******************************************************/
void WrFileToNF(U32 FileAddr, U32 FileSize)
{
#ifdef	NAND_SUPPORT
	struct Partition *part;
	U32 start_page, i, skip_blks;
	U8 *ram_addr;
	int size;	//must be int
		if(!HaveNandChip)
		return;
			part = NandPartSel("write");
	if(!part)
		return;
		if(FileSize>part->size) {
		Uart_Printf("File size is too long!\n");		
		return;
	}
	start_page = part->offset>>9;
		Uart_Printf("Are you sure to write nand flash from 0x%x with ram address 0x%x, size %d ?\n", part->offset, FileAddr, FileSize);
	if(getyorn())
		return;
			skip_blks = 0;
	ram_addr = (U8 *)FileAddr;
	size = FileSize;
	for(i=0; size>0; )	{
		if(!(i&0x1f)) {
			if(NFEraseBlock(i+start_page)) {
/*				part->size -= 32<<9;	//fail, partition available size - 1 block size
				if(FileSize>part->size) {
					Uart_Printf("Program nand flash fail\n");
					return;
				}
				NFMarkBadBlk(i+start_page);
				skip_blks++;
				i += 32;		
					continue;*/
				goto WrFileToNFErr;
			}
		}
		if(NFWritePage(i+start_page, ram_addr)) {
			ram_addr -= (i&0x1f)<<9;
			size += (i&0x1f)<<9;
			i &= ~0x1f;
WrFileToNFErr:			
			part->size -= 32<<9;	//partition available size - 1 block size
			if(FileSize>part->size) {
				Uart_Printf("Program nand flash fail\n");
				return;
			}			
			NFMarkBadBlk(i+start_page);
			skip_blks++;			
			i += 32;		
			continue;
		}
		ram_addr += 512;
		size -= 512;
		i++;
	}
	Uart_Printf("Program nand flash partition success\n");
	if(skip_blks)
		Uart_Printf("Skiped %d bad block(s)\n", skip_blks);
	#endif	/* NAND_SUPPORT */
}
static U32 downloadAddress;

//void start_kernel(U32, U32);
void RdFileFrNF(U32 FileAddr, U32 FileSize)
{
#ifdef	NAND_SUPPORT
	U32 initrd, bootpart;
	void (*fp)(void);
		if(!HaveNandChip)
		return;
			Uart_Printf("Select which program to run?\n");
	Uart_Printf("1: Kernel without initrd\n");
	Uart_Printf("2: Kernel with initrd\n");
	Uart_Printf("3: NAND-BOOT\n");
	Uart_Printf("ESC : exit\n");
		while(1) {
		char c = Uart_Getch();
				if(c==0x1b)
			return;
		if((c=='1')||(c=='2')) {
			downloadAddress = LINUX_KERNEL_ADDR;
			bootpart = 1;
			initrd = (c=='1')?0:INITRD_START;
			break;
		}
		if(c=='3') {			
			downloadAddress = BOOT_PORG_ADDR;
			bootpart = 0;
			initrd = 0;
			break;
		}
	}
	Uart_Printf("Loading...\n");
		NFReadPart(&NandPartition[bootpart], (U8 *)downloadAddress);
	if(initrd)
		NFReadPart(&NandPartition[2], (U8 *)initrd);
	Uart_Printf("end\n");
	fp = (void (*)(void))downloadAddress;
	(*fp)();
//	start_kernel(downloadAddress, initrd);
	#endif	/* NAND_SUPPORT */
}
void EraseNandPart(U32 a1, U32 a2)
{
#ifdef	NAND_SUPPORT
	struct Partition *part;
	U32 start_page, blk_cnt;
	int i, err = 0;	
	if(!HaveNandChip)
		return;
			part = NandPartSel("erase");
	if(!part)
		return;
	start_page = part->offset>>9;
	blk_cnt  = part->size>>14;
	Uart_Printf("Are you sure to erase nand flash from page 0x%x, block count 0x%x ?\n", start_page, blk_cnt);
	if(getyorn())
		return;
		for(i=0; blk_cnt; blk_cnt--, i+=32) {
		if(NFEraseBlock(i+start_page)) {
			err ++;
			Uart_Printf("Press any key to continue...\n");
			Uart_Getch();
		}
	}
		Uart_Printf("Erase Nand partition completed \n");
	if(err)
		Uart_Printf("with %d bad block(s)\n", err);
	else
		Uart_Printf("success\n");
		#endif	/* NAND_SUPPORT */
}
void GetNandFlashChip(void)
{
#ifdef	NAND_SUPPORT
	int i;
	U32 id;
		HaveNandChip = 0;
	id = NFReadID();
	//Uart_Printf("Nand Flash ID = 0x%x, status = 0x%x\n", id, NFReadStat());
		for(i=0; NandFlashChip[i].id!=0; i++)
		if(NandFlashChip[i].id==id) {
			//Uart_Printf("This nand flash size = %dM\n",NandFlashChip[i].size>>20);
			NandFlashSize = NandFlashChip[i].size;
			HaveNandChip  = 1;
			if(!NandPartition[0].size) {
				NandPartition[0].offset = 0;
				NandPartition[0].size   = NandFlashSize;
				NandPartition[1].size   = 0;
			}
			return;
		}
	Uart_Printf("No supported Nand Flash Found!\n");
		#endif	/* NAND_SUPPORT */
}
void TestNandFlash(U32 a1, U32 a2)
{
//#ifdef	NAND_SUPPORT
//#ifdef	NAND_TEST
	U32 i;
	U32 blk;
	U8 dat[512];
		if(!HaveNandChip)
		return;
		NandAddr = 0;
	blk = 0x180;	//page number
	Uart_Printf("Erase Block 0x%x...\n", blk);
	NFEraseBlock(blk);
	Uart_Printf("status = %x\n", NFReadStat());
//	Uart_Printf("Write nand flash\n");
	for(i=0; i<512; i++)
		dat[i] = ~(i&0xff);
//	for(i=0; i<512; i++)
//		Uart_Printf("%4x,", dat[i]);
	NFWritePage(blk, dat);
//	Uart_Printf("Read nand flash\n");
//	for(i=0; i<512; i++)
//		dat[i] = 0;
//		NFReadPage(blk, dat);
//	for(i=0; i<512; i++)
//		Uart_Printf("%4x,", dat[i]);
//#endif
//#endif	/* NAND_SUPPORT */
}

void Nand_Arm_Set()
{
	rPDATC = 0xff02;
	rPCONC = 0x0ff0ff54;
	rPUPC  = 0x30f0;	//PULL UP RESISTOR should be enabled to I/O
}

void Nand_Work()
{
	Nand_Arm_Set();
	GetNandFlashChip();
	TestNandFlash(0, 0);
	while(1)
	{
		Uart_Printf("Are you sure to erase nand flash?\n");
		if(!getyorn())
			EraseNandPart(0,0);
		else
			break;
	}
	Uart_Printf("Erase nand flash finish.\n");
	Uart_Getch();
}

void NandInit()
{
	Nand_Arm_Set();
	GetNandFlashChip();
}

void ReadMap(U8 *mapa,int num)     // 
{
	U32 i;
	U32 page;
	int number;
		if(!HaveNandChip)
		return;
		NandAddr = 0;
	number = MAPNUMBER / 512;
	page = num * number;
	for(i=0;i<number;i++)
		NFReadPage(page+i,(mapa+512*i));     // page: offset page number of the current picture
//	Uart_Printf("Read nand flash\n");
//	for(i=0; i<MAPNUMBER; i++)
//		Uart_Printf("%4x,", mapa[i]);
}

void WriteMap(U8 *mapa,int num)   //*mapa:picture point, num :picture number
{
	U32 i,j;
	U32 blk,page;
	int number;
		if(!HaveNandChip)
		return;
		NandAddr = 0;
	number = MAPNUMBER / 512;
	page = num * number;	
	for(i=0;i<number;i++)
	  {  
	       if(((page+i) % 32)==0)	      // erase before program.  
	          NFEraseBlock(page+i);      
	       	          
		NFWritePage(page+i,(mapa+512*i));

    }
}

⌨️ 快捷键说明

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