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

📄 flash.c

📁 ucos-II+移植到arm+s3c2410的全套代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************\
	Copyright (c) 2004-2007 threewater@up-tech.com, All rights reserved.
	by threewter	2004.4.26
\***************************************************************************/


/***************************************************************************\
    #说明: C库函数等定义
	----------------------------------  Bug  --------------------------------------

	----------------------------------  TODO list  --------------------------------------

	----------------------------------修正--------------------------------------
	2004-11-16	为yaffs文件系统添加了更多的处理函数,ReadSparePage,ReadPage512,
			WriteSparePage,WritePage512, CheckPageEreased等

	2004-5-2	1、创建

\***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../inc/drv/reg2410.h"
#include "../inc/drv/flash.h"
#include "../inc/macro.h"
#include "../inc/sys/lib.h"

#define BAD_CHECK	(1)
#define ECC_CHECK	(1)
#define WRITEVERIFY  (0)  //Verifing is enable when writing flash
#define RAM_DISK		0

#define fNFCONF_TWRPH1			Fld(3,0)
#define NFCONF_TWRPH1			FMsk(fNFCONF_TWRPH1)
#define NFCONF_TWRPH1_0		FInsrt(0x0, fNFCONF_TWRPH1) /* 0 */
#define fNFCONF_TWRPH0			Fld(3,4)
#define NFCONF_TWRPH0			FMsk(fNFCONF_TWRPH0)
#define NFCONF_TWRPH0_3		FInsrt(0x3, fNFCONF_TWRPH0) /* 3 */
#define fNFCONF_TACLS			Fld(3,8)
#define NFCONF_TACLS			FMsk(fNFCONF_TACLS)
#define NFCONF_TACLS_0			FInsrt(0x0, fNFCONF_TACLS) /* 0 */
#define fNFCONF_nFCE			Fld(1,11)
#define NFCONF_nFCE				FMsk(fNFCONF_nFCE)
#define NFCONF_nFCE_LOW		FInsrt(0x0, fNFCONF_nFCE) /* active */
#define NFCONF_nFCE_HIGH		FInsrt(0x1, fNFCONF_nFCE) /* inactive */
#define fNFCONF_ECC				Fld(1,12)
#define NFCONF_ECC				FMsk(fNFCONF_ECC)
#define NFCONF_ECC_NINIT		FInsrt(0x0, fNFCONF_ECC) /* not initialize */
#define NFCONF_ECC_INIT		FInsrt(0x1, fNFCONF_ECC)    /* initialize */
#define fNFCONF_ADDRSTEP		Fld(1,13)                 /* Addressing Step */
#define NFCONF_ADDRSTEP		FMsk(fNFCONF_ADDRSTEP)
#define fNFCONF_PAGESIZE		Fld(1,14)
#define NFCONF_PAGESIZE		FMsk(fNFCONF_PAGESIZE)
#define NFCONF_PAGESIZE_256	FInsrt(0x0, fNFCONF_PAGESIZE) /* 256 bytes */
#define NFCONF_PAGESIZE_512	FInsrt(0x1, fNFCONF_PAGESIZE) /* 512 bytes */
#define fNFCONF_FCTRL			Fld(1,15)  /* Flash controller enable/disable */
#define NFCONF_FCTRL			FMsk(fNFCONF_FCTRL)
#define NFCONF_FCTRL_DIS		FInsrt(0x0, fNFCONF_FCTRL) /* Disable */
#define NFCONF_FCTRL_EN		FInsrt(0x1, fNFCONF_FCTRL) /* Enable */

#define NFSTAT_RnB				(1 << 0)
#define NFSTAT_nFWE			(1 << 8)
#define NFSTAT_nFRE				(1 << 9)
#define NFSTAT_ALE				(1 << 10)
#define NFSTAT_CLE				(1 << 11)
#define NFSTAT_AUTOBOOT		(1 << 15)

#define NF_CMD(cmd)				{rNFCMD=cmd;}
#define NF_ADDR(addr)			{rNFADDR=addr;}	
#define NF_nFCE_L()				{rNFCONF&=~NFCONF_nFCE_HIGH;}
#define NF_nFCE_H()				{rNFCONF|=NFCONF_nFCE_HIGH;}
#define NF_RSTECC()				{rNFCONF|=NFCONF_ECC_INIT;}
#define NF_RDDATA()				(rNFDATA)
#define NF_WRDATA(data)			{rNFDATA=data;}

#define NF_WAITRB()				while(!(rNFSTAT&NFSTAT_RnB));

flashinfo nand_flashinfo;

typedef struct _NandInfo
{
	unsigned char NandID;
	int totalBlock;		//整个flash的块数
	int PagePerBlock;	//每个块的page数
} NandInfo;

typedef struct _NandMaunfacture
{
	unsigned char ManuID;
	unsigned char ManuStr[10];
} NandManufacture;

#define K9F2808_ID (0xec73)

static NandInfo NandType[]= {
	{ 0xe3,  256, 16},
	{ 0xe5,  512, 16},
	{ 0xe6, 1024, 16},
	{ 0x73, 1024, 32},
	{ 0x75, 2048, 32},
	{ 0x76, 4096, 32},
	{ 0x79, 8192, 32},};
	
static NandManufacture NandManuId[] = {
	{ 0xec, "SamSung"},
	{ 0x98, "Toshiba"}};

//define nand flash command
#define NAND_SEQDATAINPUT	0x80
#define NAND_READ0			0x00
#define NAND_READ1			0x01
#define NAND_READ2			0x50
#define NAND_RESET			0xff
#define NAND_PAGEPROG		0x10
#define NAND_ERASE0		0x60
#define NAND_ERASE1		0xd0
#define NAND_STATUS		0x70
#define NAND_IDREAD		0x90

#define MANUID(id)		(((id)&0xff00)>>8)
#define TYPEID(id)		((id)&0xff)

#if(RAM_DISK==1)
	#define RAM_DISK_SIZE		(4*1024*1024)
	#define Page_Size			(528)
	#define Cluster_Size			(32*Page_Size)
	unsigned char *RamDisk=(unsigned char *)(0xC080000+1*1024*1024);
#endif

static int Flash_Reset(void);//flash reset
static unsigned int Get_Flash_Id(void);

int NandFlash_init(void)
{
	U32 flashid;
	int i;

	// set NAND Flash controller
	rNFCONF = NFCONF_FCTRL_EN | NFCONF_nFCE_HIGH | NFCONF_TWRPH0_3 |NFCONF_ECC_INIT;

	if(Flash_Reset()!=OK){
		printk("Failed to reset Nand Flash!\n");
		for(;;);
		return FAIL;
	}

	if((flashid=Get_Flash_Id())==FAIL){
		printk("Failed to get Nand Flash ID!\n");
		return FAIL;
	}

	printk("Nand Flash ID is 0x%x, ", flashid);
	for(i=0;i<NumberOfArray(NandManuId);i++){
		if(NandManuId[i].ManuID==MANUID(flashid)){
			printk("Manufacture is %s. ", NandManuId[i].ManuStr);
			break;
		}
	}

	for(i=0;i<NumberOfArray(NandType);i++){
		if(NandType[i].NandID==TYPEID(flashid)){
			nand_flashinfo.PagePerBlock=NandType[i].PagePerBlock;
			nand_flashinfo.totalBlock=NandType[i].totalBlock;
			nand_flashinfo.totalsize=nand_flashinfo.totalBlock*
				nand_flashinfo.PagePerBlock*NandPageSize;
			nand_flashinfo.blocksize = NandType[i].PagePerBlock*NandPageSize;
			printk("Size is %dMByte\n", nand_flashinfo.totalsize/1024/1024);
			break;
		}
	}

//	if(totalsize>32)	//nand flash larger than 32MByte
//		rSmcConf|=BigCardEn;
	return OK;
}

static unsigned int Get_Flash_Id(void)
{
#if(RAM_DISK==1)	//for ramdisk
	return K9F2808_ID;
#else	//for flash
	int i;
	U16 id;

	NF_nFCE_L();

	NF_CMD(NAND_IDREAD);
	NF_ADDR(0x0);

	for(i=0;i<10;i++); //wait tWB(100ns)////?????

	id=NF_RDDATA()<<8;	// Maker code(K9S1208V:0xec)
	id|=NF_RDDATA();	// Devide code(K9S1208V:0x76)

	NF_nFCE_H();

	return id;

#endif
}

static int Flash_Reset()		//flash reset
{
#if(RAM_DISK==0)	//for nand flash
	int i;
    
	NF_nFCE_L();
	NF_CMD(NAND_RESET);	//reset command

	for(i=0;i<10;i++);  //tWB = 100ns. //??????
	NF_WAITRB();      //wait 200~500us;

	NF_nFCE_H();

#endif

	return OK;
}

static U8 seBuf[16]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};

//检测是否是坏块,是返回1
static int NF_IsBadBlock(U32 block)
{
	int i;
	unsigned int blockPage;
	U8 data;

	blockPage=(block<<5);	// For 2'nd cycle I/O[7:5] 

	NF_nFCE_L();    
	NF_CMD(NAND_READ2);	// Spare array read command
	NF_ADDR(517&0xf);		// Read the mark of bad block in spare array(M addr=5) 
	NF_ADDR(blockPage&0xff);	// The mark of bad block is in 0 page
	NF_ADDR((blockPage>>8)&0xff);   // For block number A[24:17]
	NF_ADDR((blockPage>>16)&0xff);  // For block number A[25]

	for(i=0;i<10;i++);	// wait tWB(100ns) //?????

	NF_WAITRB();	// Wait tR(max 12us)

	data=NF_RDDATA();

	NF_nFCE_H();    

	if(data!=0xff)
	{
		printk("[block %d has been marked as a bad block(%x)]\n",block,data);
		return 1;
	}

	return 0;
}


static int NF_MarkBadBlock(U32 block)
{
	int i;
	U32 blockPage=(block<<5);

	seBuf[0]=0xff;
	seBuf[1]=0xff;    
	seBuf[2]=0xff;    
	seBuf[5]=0x44;   // Bad blcok mark=0

	NF_nFCE_L(); 
	NF_CMD(NAND_READ2);		//????
	NF_CMD(NAND_SEQDATAINPUT);	// Write 1st command

	NF_ADDR(0x0);		// The mark of bad block is 
	NF_ADDR(blockPage&0xff);	    // marked 5th spare array 
	NF_ADDR((blockPage>>8)&0xff);   // in the 1st page.
	NF_ADDR((blockPage>>16)&0xff);  //

	for(i=0;i<16;i++){
		NF_WRDATA(seBuf[i]);	// Write spare array
	}

	NF_CMD(NAND_PAGEPROG);   // Write 2nd command

	for(i=0;i<10;i++);  //tWB = 100ns. ///???????

	NF_WAITRB();      // Wait tPROG(200~500us)

	NF_CMD(NAND_STATUS);

	for(i=0;i<3;i++);  //twhr=60ns////??????

	if (NF_RDDATA()&0x1){ // Spare arrray write error
		NF_nFCE_H();
		printf("[Program error is occurred but ignored]\n");
	}
	else{
		NF_nFCE_H();
	}

	printf("[block #%d is marked as a bad block]\n",block);
	return OK;
}


/*****************************************************************\
	功能:擦除FLASH的1Block
	参数	block:擦除的 块位置
	返回值	成功返回OK,否则返回FAIL
\*****************************************************************/
int Erase_Block(unsigned int block)
{

#if(RAM_DISK==1)	//for ramdisk
	memset(RamDisk+block*Cluster_Size,0xff,Cluster_Size);
#else	//for flash

    U32 blockPage=(block<<5);
    int i;

#if BAD_CHECK
    if(NF_IsBadBlock(block))
	return FAIL;
#endif

	NF_nFCE_L();
	
	NF_CMD(NAND_ERASE0);   // Erase one block 1st command

	NF_ADDR(blockPage&0xff);	    // Page number=0
	NF_ADDR((blockPage>>8)&0xff);   
	NF_ADDR((blockPage>>16)&0xff);

	NF_CMD(NAND_ERASE1);   // Erase one blcok 2nd command
	 
	for(i=0;i<10;i++); //wait tWB(100ns)//??????

	NF_WAITRB();    // Wait tBERS max 3ms.

⌨️ 快捷键说明

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