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

📄 nand.c

📁 vxwork操作系统的相关内容
💻 C
字号:
/*
 create by hzh, support 512/page NAND Flash only
*/
#ifndef BOOT_NAND

#include <string.h>
#include "2440addr.h"
/*#include "bootrom.h"*/

#define U32 unsigned int
#define U16 unsigned short
#define S32 int
#define S16 short int
#define U8  unsigned char
#define	S8  char

#define TRUE 	1   
#define FALSE 	0
#define OK		1
#define FAIL	0

#define	EnNandFlash()	(rNFCONT |= 1)
#define	DsNandFlash()	(rNFCONT &= ~1)
#define	NFChipEn()		(rNFCONT &= ~(1<<1))
#define	NFChipDs()		(rNFCONT |= (1<<1))
#define	InitEcc()		(rNFCONT |= (1<<4))
#define	MEccUnlock()	(rNFCONT &= ~(1<<5))
#define	MEccLock()		(rNFCONT |= (1<<5))
#define	SEccUnlock()	(rNFCONT &= ~(1<<6))
#define	SEccLock()		(rNFCONT |= (1<<6))

#define	WrNFDat8(dat)	(rNFDATA8 = (dat))
#define	WrNFDat32(dat)	(rNFDATA = (dat))
#define	RdNFDat8()		(rNFDATA8)	
#define	RdNFDat32()		(rNFDATA)	

#define	WrNFCmd(cmd)	(rNFCMD = (cmd))
#define	WrNFAddr(addr)	(rNFADDR = (addr))
#define	WrNFDat(dat)	WrNFDat8(dat)
#define	RdNFDat()		RdNFDat8()	

#define	RdNFMEcc()		(rNFMECC0)	
#define	RdNFSEcc()		(rNFSECC)	

#define	RdNFStat()		(rNFSTAT)
#define	NFIsBusy()		(!(rNFSTAT&1))
#define	NFIsReady()		(rNFSTAT&1)





#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	RdIDCMD		0x90

static U16 NandAddr;


#define TACLS		1
#define TWRPH0		4
#define TWRPH1		0

static void InitNandCfg(void)
{
	

	rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);	
	#if 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.
	#endif
	rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
	#if 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.

//	rNFSTAT = 0;
    
//    Nand_Reset();
	#endif
}

#ifdef	WIAT_BUSY_HARD
#define	WaitNFBusy()	while(NFIsBusy())
#else
static U32 WaitNFBusy(void)	
{
	U8 stat;
	
	WrNFCmd(QUERYCMD);
	do {
		stat = RdNFDat();
	}while(!(stat&0x40));
	WrNFCmd(READCMD0);
	return stat&1;
}
#endif

static U32 ReadChipId(void)
{
	U32 id;
	
	NFChipEn();	
	WrNFCmd(RdIDCMD);
	WrNFAddr(0);
	while(NFIsBusy());	
	id  = RdNFDat()<<8;
	id |= RdNFDat();		
	NFChipDs();		
	
	return id;
}

U16 ReadStatus(void)
{
	U16 stat;
	
	NFChipEn();	
	WrNFCmd(QUERYCMD);		
	stat = RdNFDat();	
	NFChipDs();
	
	return stat;
}

U32 EraseBlock(U32 addr)
{
	U8 stat;

	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;	
#endif
	
	printf("Erase block 0x%x %s\n", addr, stat?"fail":"ok");
		
	return stat;
}


void ReadPage(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();
	NFChipDs();
}

U32 WritePage(U32 addr, U8 *buf)
{
	U32 i, mecc;
	U8 stat, tmp[7];
	
	
	NFChipEn();
	WrNFCmd(PROGCMD0);
	WrNFAddr(0);
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
	InitEcc();	
	MEccUnlock();
	for(i=0; i<512; i++)
		WrNFDat(buf[i]);
	MEccLock();
	
	mecc = RdNFMEcc();
		
	tmp[0] = mecc&0xff;
    tmp[1] = (mecc>>8)&0xff;
    tmp[2] = (mecc>>16)&0xff;
    tmp[3] = (mecc>>24)&0xff;
    tmp[5] = 0xff;	
    
    SEccUnlock();
	WrNFDat(tmp[0]);
	WrNFDat(tmp[1]);
	WrNFDat(tmp[2]);
	WrNFDat(tmp[3]);
	SEccLock();
	WrNFDat(tmp[4]);
	WrNFDat(tmp[5]);
    	
	WrNFCmd(PROGCMD1);
	stat = WaitNFBusy();
	NFChipDs();
	
#ifdef	WR_BAD_BLK_TEST
	if((addr&0xff)==0x17) stat = 1;
#endif
		
	if(stat)
		printf("Write nand flash 0x%x fail\n", addr);
	else {	
		U8 RdDat[512];
		
		ReadPage(addr, RdDat);		
		for(i=0; i<512; i++)
			if(RdDat[i]!=buf[i]) {
				printf("Check data at page 0x%x, offset 0x%x fail\n", addr, i);
				stat = 1;
				break;
			}
	}
		
	return stat;	
}

static void MarkBadBlk(U32 addr)
{
	addr &= ~0x1f;
	
	NFChipEn();
	
	WrNFCmd(READCMD2);	
	WrNFCmd(PROGCMD0);
	WrNFAddr(4);		
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
	WrNFDat(0);			
	WrNFDat(0);
	WrNFDat(0);			
	WrNFDat(0);
	WrNFCmd(PROGCMD1);
	WaitNFBusy();/*needn't check return status*/
	
	WrNFCmd(READCMD0);	
		
	NFChipDs();
}

static int CheckBadBlk(U32 addr)
{
	U8 dat;
	
	addr &= ~0x1f;
	
	NFChipEn();
	
	WrNFCmd(READCMD2);	
	WrNFAddr(5);		
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
	WaitNFBusy();
	dat = RdNFDat();
	
	WrNFCmd(READCMD0);	
	
	NFChipDs();

	return (dat!=0xff);
}

/************************************************************/
struct Partition{
	U32 offset;
	U32 size;
	char *name;
};
/*
static struct Partition NandPart[] = {
	{0, 		 0x00030000, "boot"},		//256K
	{0x00030000, 0x001d0000, "kernel"},
	{0x00200000, 0x02000000, "rootfs"},		//30M
	{0x02000000, 0x02000000, "ext-fs1"},	//32M
	{0,			 0         , 0}
};
*/
static struct Partition NandPart[] = {
	{0, 		 0x00030000, "boot"},		
	{0x00030000, 0x001d0000, "kernel"},
	{0x00200000, 0x01600000, "rootfs"},		
	{0x01800000, 0x02200000, "ext-fs1"},	
	{0,			 0         , 0}
};
/*
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 StartPage, BlockCnt;
U32 downloadAddress; 
U32 downloadFileSize;


static int NandSelPart(char *info)
{
	U16 i, max_sel;
	struct Partition *ptr = NandPart;
	
	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 = getchar();
		if(i==0x1b)
			return -1;
		if((i>='0')&&(i<(max_sel+'0'))) {
			i -= '0';
			StartPage = NandPart[i].offset>>9;
			BlockCnt  = NandPart[i].size>>14;
			return i;
		}
	}	
}

static void WrFileToNF(void)
{
	int nf_part, i ,size, skip_blks;
	U32 ram_addr;
	
	nf_part = NandSelPart("write");
	if(nf_part<0)
		return;	
	
	if(downloadFileSize>NandPart[nf_part].size) {
		printf("Download file size is more large than selected partition size!!!\n");
	}
	
	printf("Now write nand flash page 0x%x from ram address 0x%x, filesize = %d\n", StartPage, downloadAddress, downloadFileSize);
	printf("Are you sure? [y/n]\n");
	while(1) {
		char c = getchar();
		if((c=='y')||(c=='Y'))
			break;
		if((c=='n')||(c=='N'))			
			return;
	}
	
	skip_blks = 0;
	ram_addr = downloadAddress;
	size = downloadFileSize;
	for(i=0; size>0; )	{	
		if(!(i&0x1f)) {
			if(EraseBlock(i+StartPage)) {
				/*NandPart[nf_part].size -= 32<<9;	//partition available size - 1 block size
				if(downloadFileSize>NandPart[nf_part].size) {
					puts("Program nand flash fail\n");
					return;
				}
				MarkBadBlk(i+StartPage);
				skip_blks++;				
				i += 32;				
				continue;
			*/
			goto WrFileToNFErr;
			}
		}
		if(WritePage(i+StartPage, (U8 *)ram_addr)) {
			ram_addr -= (i&0x1f)<<9;
			size += (i&0x1f)<<9;
			i &= ~0x1f;
WrFileToNFErr:
			NandPart[nf_part].size -= 32<<9;	
			if(downloadFileSize>NandPart[nf_part].size) {
				printf("Program nand flash fail\n");
			}			
			MarkBadBlk(i+StartPage);
			skip_blks++;			
			i += 32;			
			continue;
		}
		ram_addr += 512;
		size -= 512;
		i++;
	}

	printf("Program nand flash partition success\n");
	if(skip_blks)
		printf("Skiped %d bad block(s)\n", skip_blks);
}

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


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


extern int sprintf(char * /*s*/, const char * /*format*/, ...);

/************************************************************/
void InitNandFlash(int info)
{	
	U32 i;
	
	InitNandCfg();
	i = ReadChipId();
	if(info)
		printf("Read chip id = %x\n", i);	
	if((i==0x9873)||(i==0xec75))	
		NandAddr = 0;
	else if(i==0xec76)
		NandAddr = 1;
	else {	
		printf("Chip id error!!!\n");
		return;
	}
	if(info)
		printf("Nand flash status = %x\n", ReadStatus());
}

void NandErase(void)
{
	int i, err = 0;
	
	InitNandFlash(1);
	
	i = NandSelPart("erase");
	if(i<0)
		return;	
	
	printf("Are you sure to erase nand flash from page 0x%x, block count 0x%x ? [y/n]\n", StartPage, BlockCnt);
	while(1) {
		char c;
		
		c = getchar();
		if((c=='y')||(c=='Y'))
			break;
		if((c=='n')||(c=='N'))
			return;
	}	
	
	for(i=0; BlockCnt; BlockCnt--, i+=32) {
		if(EraseBlock(i+StartPage)) {
			err ++;
			printf("Press any key to continue...\n");
			getchar();
		}
	}	

	DsNandFlash();		
	printf("Erase Nand partition completed ");
	if(err)
		printf("with %d bad block(s)\n", err);
	else
		printf("success\n");
}

void NandWrite(void)
{
	InitNandFlash(1);
	WrFileToNF();
	DsNandFlash();		
}

void PrintBuffer(U8 *pData, U32 len)
{
  U32   i;
  char  buf[80];
  
  for(i = 0; i < len; i++)
  {
      if(0 == (i % 16))
      {
	      if(0 != i)
	      {
	          buf[59] = '\r';
	          buf[60] = '\n';
	          buf[61] = '\0';
	          printf(buf);
	      }
	      sprintf(buf, "0x%08x:", (unsigned int)pData + i);
  	  }
      sprintf(buf + (i % 16) * 3 + 11, " %02x", (unsigned char)pData[i]);
  }
  
}

void WriteBootrom(void)
{
    unsigned long i, rom_adr,rom_len,blk_num,page_num;
    rom_adr = (unsigned long)0x33e00000;

    rom_len = 0x100000;

	InitNandFlash(1);
	
    blk_num = rom_len / 0x4000;
    if(0 != (rom_len % 0x4000))
    	blk_num++;
    page_num = blk_num*32;
    printf("Bootrom length is 0x%x, block number is %d.\n",rom_len,blk_num);
    printf("Erasing block:");
    for(i = 0; i < page_num; i++)
	{
        EraseBlock(i);       
    }
    printf("Write data:");

    for(i = 0; i < page_num; i++)
	{
        WritePage(i, (U8*)(rom_adr + 512*i));       
    }
    printf("Write data finished.\n");
}
void ReadBootrom(int cmplen)
{
    unsigned long i, rom_adr,rom_len,blk_num,page_num,error_cnt=0;
    U8 buf[512];
    
    rom_adr = (unsigned long)0x33f00000;

    rom_len = 0x100000;

	InitNandFlash(1);
	
    blk_num = rom_len / 0x4000;
    if(0 != (rom_len % 0x4000))
    	blk_num++;
    page_num = blk_num*32;

    for(i = 0; i < page_num; i++)
	{
	    printf("Reading page %d....:\n", i);
        ReadPage(i, (U8*)(rom_adr + i*512));  
    }
    for(i = 0; i < cmplen; i++)
	{
        if(*(unsigned char*)(0x33f00000 + i) != *(unsigned char*)(0x33e00000 + i))
        {
             error_cnt++;
        }
    }
    
    printf("Compare length is 0x%x.\n", cmplen);
    printf("Error count is 0x%x.\n", error_cnt);
    
}

void testnand(void)
{
    U8 buf[512];
	InitNandFlash(1);
    EraseBlock(0);
    printf("Reading page 0 after erase:\n");
    ReadPage(0, (U8*)buf);  
    PrintBuffer(buf, 512);
    printf("Write page 0:\n");
    WritePage(0,(U8*)0x33e00000);
    printf("Reading page 0 after write:\n");
    ReadPage(0, (U8*)buf);  
    PrintBuffer(buf, 512);
    
}
#endif


⌨️ 快捷键说明

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