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

📄 nand.c

📁 1针对三星44B0的开发程序2对于网卡的驱动程序3程序采用C语言编程4采用ARM指令集5全部代码在 ADS1.2 中编译调试
💻 C
字号:
#include "../inc/def.h"
#include "../inc/config.h"
#include "../inc/utils.h"
#include "../inc/board.h"

#ifdef	NAND_FLASH_SUPPORT

struct NFChipInfo {
	U32 id;
	U32 size;
}

static NandFlashChip[] = {
	{0xec73, SIZE_16M},
	{0xec75, SIZE_32M},
	{0xec76, SIZE_64M},
	{0xec79, SIZE_128M},
	{0, 0},
};



/*
struct Partition oNandPartition[] = {
	{0x00000000, 0x00030000, "boot"},
	{0x00030000, 0x001d0000, "kernel"},
	{0x00200000, 0x00600000, "rootfs"},
	{0x00800000, 0x00800000, "ext-fs1"},
	{0x01000000, 0x01000000, "ext-fs2"},
	{0x00000000, 0x00000000, 0}
};*/

extern struct Partition *pNandPart;

U32 NandFlashSize;

static U16 NandAddr;
static U16 support;

#define	NAND_DAT	0x02000000
#define	NAND_ALE	0x02000004
#define	NAND_CLE	0x02000002

#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

void NFChipSel(U32);
int  NFIsReady(void);
void NFWrCmd(int);
void NFWrAddr(int);
void NFWrDat(int);
U8   NFRdDat(void);

#define	NFChipEn()	NFChipSel(1)
#define	NFChipDs()	NFChipSel(0)
#define	NFIsBusy()	(!NFIsReady())

//#define	NFWrCmd(cmd)	*(volatile U8 *)NAND_CLE = (cmd)
//#define	NFWrAddr(addr)	*(volatile U8 *)NAND_ALE = (addr)
//#define	NFWrDat(dat)	*(volatile U8 *)NAND_DAT = (dat)
//#define	NFRdDat()		*(volatile U8 *)NAND_DAT

//#define	WIAT_BUSY_HARD
//#define	ER_BAD_BLK_TEST
//#define	WR_BAD_BLK_TEST

#ifdef	WIAT_BUSY_HARD
#define	NFWaitBusy()	while(NFIsBusy())
#else
static U32 NFWaitBusy(void)
{
	U8 stat;
	
	NFWrCmd(QUERYCMD);
	do {
		stat = NFRdDat();
		//printf("%x\n", stat);
	}while(!(stat&0x40));
	NFWrCmd(READCMD0);
	return stat&1;
}
#endif

static U32 NFReadID(void)
{
	U32 id, loop = 0;

	NFChipEn();
	NFWrCmd(READIDCMD);
	NFWrAddr(0);
	while(NFIsBusy()&&(loop<10000)) loop++;
	if(loop>=10000)
		return 0;
	id  = NFRdDat()<<8;
	id |= NFRdDat();
	NFChipDs();
	
	return id;
}

static U16 NFReadStat(void)
{
	U16 stat;
	
	NFChipEn();	
	NFWrCmd(QUERYCMD);
	stat = NFRdDat();	
	NFChipDs();
	
	return stat;
}

static U32 NFEraseBlock(U32 addr)
{
	U8 stat;

	addr &= ~0x1f;
		
	NFChipEn();	
	NFWrCmd(ERASECMD0);		
	NFWrAddr(addr);
	NFWrAddr(addr>>8);
	if(NandAddr)
		NFWrAddr(addr>>16);
	NFWrCmd(ERASECMD1);		
	stat = NFWaitBusy();
	NFChipDs();
	
#ifdef	ER_BAD_BLK_TEST
	if(!((addr+0xe0)&0xff)) stat = 1;	//just for test bad block
#endif
	
	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();
	NFWrCmd(READCMD0);
	NFWrAddr(0);
	NFWrAddr(addr);
	NFWrAddr(addr>>8);
	if(NandAddr)
		NFWrAddr(addr>>16);
//	InitEcc();
	NFWaitBusy();		
	for(i=0; i<512; i++)
		buf[i] = NFRdDat();		
	NFChipDs();
}

//addr = page address
static U32 NFWritePage(U32 addr, U8 *buf)
{
	U16 i, stat;
//	U8 tmp[3];
	
	NFChipEn();
	NFWrCmd(PROGCMD0);
	NFWrAddr(0);
	NFWrAddr(addr);
	NFWrAddr(addr>>8);
	if(NandAddr)
		NFWrAddr(addr>>16);
//	InitEcc();	
	for(i=0; i<512; i++)
		NFWrDat(buf[i]);
		
	if(!addr) {
		NFWrDat('b');
		NFWrDat('o');
		NFWrDat('o');
		NFWrDat('t');		
	}
		
/*	tmp[0] = rNFECC0;
    tmp[1] = rNFECC1;
    tmp[2] = rNFECC2;
    	
	NFWrDat(tmp[0]);
    NFWrDat(tmp[1]);
    NFWrDat(tmp[2]);*/
    	
	NFWrCmd(PROGCMD1);
	stat = NFWaitBusy();
	NFChipDs();
	
#ifdef	WR_BAD_BLK_TEST
	if((addr&0xff)==0x17) stat = 1;	//just for test bad block
#endif
	
	if(stat)
		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]) {
				printf("Check data at page 0x%x, offset 0x%x fail\n", addr, i);
				stat = 1;
				break;
			}
	}
		
	return stat;	
}

static void NFMarkBadBlk(U32 addr)
{
	int i;
	addr &= ~0x1f;
	
	NFChipEn();
	
	NFWrCmd(READCMD2);	//point to area c
	
	NFWrCmd(PROGCMD0);
	NFWrAddr(0);		//mark offset 0~15
	NFWrAddr(addr);
	NFWrAddr(addr>>8);
	if(NandAddr)
		NFWrAddr(addr>>16);
	for(i=0; i<16; i++)
		NFWrDat(0);		//mark with 0	
	NFWrCmd(PROGCMD1);
	NFWaitBusy();		//needn't check return status
	
	NFWrCmd(READCMD0);	//point to area a
		
	NFChipDs();
}

static int NFChkBadBlk(U32 addr)
{
	U8 dat;
	
	addr &= ~0x1f;
	
	NFChipEn();
	
	NFWrCmd(READCMD2);	//point to area c
	NFWrAddr(5);		//mark offset 5
	NFWrAddr(addr);
	NFWrAddr(addr>>8);
	if(NandAddr)
		NFWrAddr(addr>>16);
	NFWaitBusy();
	dat = NFRdDat();
	
	NFWrCmd(READCMD0);	//point to area a
	
	NFChipDs();

	return (dat!=0xff);
}



static struct Partition *NFSelPart(char *info)
{
	int i, max_sel;

	printf("Please select Nand flash region to %s, Esc to abort\n", info);
	
	for(i=0; pNandPart[i].size; i++)
		printf("%d : start 0x%08x, size 0x%08x\t[part%d]\n", i, pNandPart[i].offset, pNandPart[i].size, i/*pNandPart[i].name*/);

	max_sel = i;	
	
	while(1) {
		char c = getch();
		
		if(c==0x1b)
			return 0;
		if((c>='0')&&(c<(max_sel+'0')))
			return &(pNandPart[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)) {
				printf("Skipped bad block at 0x%08x\n", i+start_page);
				i += 32;
				size -= 32<<9;
				continue;
			}
		}
		NFReadPage((i+start_page), ram_addr);
//			printf("Read page %d\n", i);
		i++;
		size -= 512;
		ram_addr += 512;
	}
}

/******************************************************/
int WrFileToNF(U32 src_addr, U32 w_size)
{
	struct Partition *part;
	U32 start_page, i, skip_blks;
	U8 *ram_addr;
	int size;	//must be int
	
	if(!support)
		return -1;
		
	part = NFSelPart("write");
	if(!part)
		return -1;
	
	if(w_size>part->size) {
		puts("File size is too long!\n");
		return -1;
	}

	start_page = part->offset>>9;
	
	printf("Are you sure to write nand flash from 0x%x with ram address 0x%x, size %d ?\n", part->offset, src_addr, w_size);
	if(!getyorn())
		return -1;
		
	skip_blks = 0;
	ram_addr = (U8 *)src_addr;
	size = w_size;
	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) {
					puts("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(w_size>part->size) {
				puts("Program nand flash fail\n");
				return -1;
			}			
			NFMarkBadBlk(i+start_page);
			skip_blks++;			
			i += 32;		
			continue;
		}
		ram_addr += 512;
		size -= 512;
		i++;
	}

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

int RdFileFrNF(U32 dst_addr, U32 load_part)
{
	U32 i;
	struct Partition *part;
	
	if(!support)
		return -1;

	for(i=0; pNandPart[i].size; i++);
	if(i>load_part)
		part = pNandPart+load_part;
	else {
		part = NFSelPart("read");
		if(!part)
			return -1;
	}
	
	puts("Loading...\n");
	
	NFReadPart(part, (U8 *)dst_addr);
	
	puts("end\n");
	
	return 0;
}

int EraseNandPart(void)
{
	struct Partition *part;
	U32 start_page, blk_cnt;
	int i, err = 0;	

	if(!support)
		return -1;
		
	part = NFSelPart("erase");
	if(!part)
		return -1;

	start_page = part->offset>>9;
	blk_cnt  = part->size>>14;

	printf("Are you sure to erase nand flash from page 0x%x, block count 0x%x ?", start_page, blk_cnt);
	if(!getyorn())
		return -1;
	
	for(i=0; blk_cnt; blk_cnt--, i+=32) {
		if(NFEraseBlock(i+start_page)) {
			err ++;
			puts("Press any key to continue...\n");
			getch();
		}
	}
	
	puts("Erase Nand partition completed ");
	if(err)
		printf("with %d bad block(s)\n", err);
	else
		puts("success\n");
	
	return 0;
}

#ifdef	SAVE_ENV_IN_NAND
U32 NFSaveParams(char *pEnv)
{
	char dat[512];
	U32 addr;
	
	if(support) {
		memcpy(dat, pEnv, sizeof(EnvParams));
		for(addr=SIZE_64K>>9; addr<(0x30000>>9); addr++) {
			NFEraseBlock(addr);
			if(!NFWritePage(addr, (U8 *)dat))
				return 0;
		}
	}
	return -1;
}

U32 NFSearchParams(char *pEnv)
{
	char dat[512];
	U32 addr;
	
	if(support) {
		for(addr=SIZE_64K>>9; addr<(0x30000>>9); addr++) {
			NFReadPage(addr, (U8 *)dat);		
			if(!strncmp(dat, "params", 7)) {
				memcpy(pEnv, dat, sizeof(EnvParams));			
				return 0;
			}
		}
	}
	return -1;	
}
#endif

static U32 nand_id;

void NandFlashInit(void)
{
	int i;	
	
	support = 0;
	nand_id = NFReadID();
	
	for(i=0; NandFlashChip[i].id!=0; i++)
		if(NandFlashChip[i].id==nand_id) {			
			nand_id = i;
			NandFlashSize = NandFlashChip[i].size;
			support  = 1;
			NandAddr = NandFlashSize>SIZE_32M;
			if(!pNandPart[0].size) {
				pNandPart[0].offset = 0;
				pNandPart[0].size   = NandFlashSize;
				pNandPart[1].size   = 0;				
			}			
			return;
		}
	
}

void NandFlashStatusRep(void)
{
	if(support) {
		printf("Nand Flash ID is 0x%x, Size = %dM, Status = 0x%x\n", NandFlashChip[nand_id].id, NandFlashChip[nand_id].size>>20, NFReadStat());
	} else {
		printf("No supported Nand Flash Found!\n");
	}
}

//void (*pNandFlashInit)(void) = NandFlashInit;

#endif	/* NAND_SUPPORT */

⌨️ 快捷键说明

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