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

📄 nandflash.c

📁 应用ADS下载nand flash源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************/
/*                                                                       */
/* FILE NAME                                      VERSION                */
/*                                                                       */
/* source\flash.c                                  1.0                   */
/*                                                                       */
/* DESCRIPTION : 2440 MPU Nand Flash                                     */
/*                                                                       */
/*                                                                       */
/* DATA STRUCTURES                                                       */
/*                                                                       */
/* FUNCTIONS : s3c2440 Nand Flash Program Code                           */
/*                                                                       */
/* CPU DEPENDENCES                                                       */
/*                                                                       */
/* Made by Song Seun Keun                                                */
/*                                                                       */
/*                                Copyrigth (C) 2001 AIJISYSTEM CO.,LTD  */
/*************************************************************************/

#include <stdio.h>
#include <string.h>
#include "common.h"

#define SAMSUNG
//#define TOSHIBA
#define CACHE

#define PAGE_CNT 32
#define PAGE_SIZE 512
#define BLOCK_COUNT 8192  //4096 
#define BLOCK_SIZE 0x4000

/* Hardware dependent functions */
#ifdef SAMSUNG
#define NF_RDDATA() (rNFDATA)
#define NF_nFCE_L() {rNFCONT&=~(1<<1);}
#define NF_nFCE_H() {rNFCONT|=(1<<1);}
#define NF_WRDATA(data) {rNFDATA=data;}
#define NF_CMD(cmd)	{rNFCMD=cmd;}
#define NF_ADDR(addr)	{rNFADDR=addr;}	
#define NF_CLEAR_RB()   {rNFSTAT |= (1<<2);}	
#define NF_DETECT_RB()  {while(!(rNFSTAT&(1<<2)));}
#endif

// Host program苞 data & command甫 林绊罐扁 困茄 structure
extern FLASH_INFO Flash_Info;

uchar TempBuf[BLOCK_SIZE];
uchar FillBuf[PAGE_SIZE];
ulong Current_Block_No = 0;
ulong Current_Page_No = 0;
ulong image_size = 0;
ulong debugadd = 0;
volatile int READMEM = 1000;
int WRITE = 1;


void Main(void)
{
	switch(Flash_Info.Command)
	{
		case FPROGRAM: Program();
				break;
		case FERASEALL: 
				Flash_Info.Result = 1;
				//EraseAll();
				break;
		case FERASESEC: 
				Flash_Info.Result = 1;
				//EraseSector();
				break;
		case FREADID: ReadChipID();
				break;
		case FREADMEM: ReadMem();
				break;
		case FWRITE_BIB: 
				break;
		case FINIT: InitFlash();
				break;
		default :
			Flash_Info.Result = 0;
	}
}

// Flash program function
void  Program(void)
{
	ulong len, flen, i, wSize;
	volatile ulong status;
	uchar *srcP, *bsrcP;

    Flash_Info.Result = 0;
	srcP = (uchar *)Flash_Info.Buf;
	len = Flash_Info.Length;
	
	/* Calculate the Block Address */
	if(WRITE)
	{
		ulong sBlock;
		debugadd = Flash_Info.TargetAddr;
		sBlock = Flash_Info.TargetAddr >> 14;
		Current_Block_No = sBlock;
		Current_Page_No = Current_Block_No*PAGE_CNT;
		WRITE-=WRITE;
	}
	
	while(len && (Current_Block_No < BLOCK_COUNT))
    {
    	if(!(Current_Page_No%PAGE_CNT)) {
    		if(Flash_Info.BadBlockTable[Current_Block_No]){
    			Current_Block_No++;
    			Current_Page_No = Current_Block_No*PAGE_CNT;
    		}
    		
    		if(Current_Block_No >= BLOCK_COUNT)
    			return;	
    		if(!PrepareBlock())
    			return;
    	}
    	
    	if(len > PAGE_SIZE)
			flen = PAGE_SIZE;
		else {
			flen = len;
			bsrcP = srcP+len;
			for(i=len; i<PAGE_SIZE;i++)
				*bsrcP++ = 0xff;
		}
			
		status = WriteChar(srcP, Current_Page_No);
		for(i=0;i<30;i++);
		if(!status) // error
			return;
		
		ReadChar(TempBuf, Current_Page_No, PAGE_SIZE);
		if(!Verification((ulong *)TempBuf, PAGE_SIZE, (ulong *)srcP))
			return;
		
		Current_Page_No++;
		wSize +=PAGE_SIZE;
		image_size +=PAGE_SIZE;
		len -= flen;
		srcP += PAGE_SIZE;
    }

//	LastAddr = Flash_Info.TargetAddr+wSize;
    Flash_Info.Result = 1;
}

// Chip erase function
void EraseAll(void)
{
	int i;
	Flash_Info.Result = 1; // 8Mbyte
	for(i=0;i<100;i++) OneBlockErase(i);
}

// Sector erase function
void EraseSector(void)
{
	Flash_Info.Result = 1;
}

// 窍唱狼 Sector 父 Erase
int OneBlockErase(ulong block)
{
	int i, Delay=5000;
	ulong nand_cntlr_block_addr;
			
	nand_cntlr_block_addr = block<<5;
	
	NF_nFCE_L();
	
	NF_CLEAR_RB();
	
	// Erase one block 1st command 
	rNFCMD = ERASE_CMD_FIRST;
	
	// For block number A[17:0] 
    rNFADDR = (nand_cntlr_block_addr&0xff);
   
    // For block number A[24:17] 
    rNFADDR = ((nand_cntlr_block_addr>>8)&0xff);
  
    // For block number A[25] 
    rNFADDR = ((nand_cntlr_block_addr>>16)&0xff);
    
    // Erase one block 2nd command 
    rNFCMD = ERASE_CMD_SECOND;  
    
    NF_DETECT_RB();
    
    while(Delay--);
    
    rNFCMD = READ_STATUS;   // Read status command
    
    for(i=0;i<10;i++);
    
    if(NF_RDDATA()&0x1){
    	Flash_Info.BadBlockTable[Current_Block_No]=1;
    	NF_nFCE_H();
    	return 0;
    }
    
    else{
    	NF_nFCE_H();
    	return 1;
    }    	
}


// Read Manufacturer & Device ID
void ReadChipID(void)
{
    ulong manId,devId;

	int i;
	
	NF_nFCE_L();
	
	rNFCMD = ID_CMD;
	rNFADDR = 0x0;
	
	for(i=0;i<10;i++); /* Wait for done */
	
	NF_nFCE_H();
			
	manId = NF_RDDATA();
	
	
	devId = (manId >> 15) & 0xff;
	manId = (manId >> 23) & 0xff;

	Flash_Info.Result = (devId << 8) + manId;
}

ulong PrepareBlock(void)
{

	if(Flash_Info.BadBlockTable[Current_Block_No])
		return 0;
	if(!OneBlockErase(Current_Block_No++))
		return 0;
		
	return 1;
}

int BlankCheck(ulong *targetP,ulong targetSize) 
{
	ulong i;
	
	for(i=0; i<targetSize; i+=4)
		if(*targetP++ != 0xffffffff)
			return 0;
	
	return 1;
}

int Verification(ulong *targetP, ulong limit, ulong *srcAddr)
{
	ulong i;

	for(i=0; i<limit; i+=4, targetP++, srcAddr++)
		if(*targetP != *srcAddr) {
			return 0;
		}

	return 1;
}

int ReadChar(uchar *data, ulong targetAddr, ulong size)
{
	ulong i, j, len, flen;
	
	len = size;
	
	for(i=0;i<size;i+=PAGE_SIZE){
		if(len > PAGE_SIZE)
			flen = PAGE_SIZE;
		else 
			flen = len;
		
		NF_nFCE_L();
		
		NF_CLEAR_RB()
	
		rNFCMD = READ;
	
		rNFADDR = 0;
	
		/* For block number A[17:0] */
    	rNFADDR = (targetAddr&0xff);
   
    	/* For block number A[24:17] */
    	rNFADDR = ((targetAddr>>8)&0xff);
  
    	/* For block number A[25] */
    	rNFADDR = ((targetAddr>>16)&0xff);
    
    	for(j=0;j<10;j++);
    
    	NF_DETECT_RB();
    
		//memcpy((void *)data, (void *)data_reg, flen);
		for(j=0;j<512;j++) *data++ = NF_RDDATA();
	
		len -= PAGE_SIZE;
		
		if(Flash_Info.Command == FREADMEM) targetAddr ++;
	}

	return 1;
}

int WriteChar(uchar *data, ulong page_addr)
{
	int i;
		
	NF_nFCE_L();
	
	NF_CLEAR_RB();
	
	/* Write Reset */
	rNFCMD = WRITE_RESET;

    /* Write Command */
    rNFCMD = PROGRAM_FIRST;
    
    rNFADDR = 0x0;
    
    /* For block number A[17:0] */
    rNFADDR = (page_addr&0xff);
   
    /* For block number A[24:17] */
    rNFADDR = ((page_addr>>8)&0xff);
  
    /* For block number A[25] */
    rNFADDR = ((page_addr>>16)&0xff);
     
    //memcpy((void *)data_reg, (void *)data, PAGE_SIZE);
    for(i=0;i<512;i++) NF_WRDATA(*data++);
    
    //for(i=0;i<100;i++); // for the timing issue
    
    /* Write second command */
    rNFCMD = PROGRAM_SECOND;
    
    for(i=0;i<100;i++); //for the timing issue
    
    NF_DETECT_RB();
    
    /* Read command */
    rNFCMD = READ_STATUS;
    
    for(i=0;i<30;i++); // for the timing issue
    
    if(NF_RDDATA()&0x1){
    	Flash_Info.BadBlockTable[Current_Block_No]=1;
    	NF_nFCE_H();
    	return 0;
    }
    
    else{
    	NF_nFCE_H();
    	return 1;	
    }
}


void  ReadMem(void)
{
	ulong TargetAdd;
	uchar *srcP;

	srcP = (uchar *)Flash_Info.Buf;
	
	TargetAdd = Flash_Info.TargetAddr;
	
	/* Calculate the Block Address */
	if(READMEM)
	{
		ulong sBlock;
		sBlock = Flash_Info.TargetAddr >> 14;
		Current_Block_No = sBlock;
		Current_Page_No = Current_Block_No*PAGE_CNT;
		READMEM-=READMEM;
	}
	
	FlashConfig ();

	ReadChar(srcP, Current_Page_No, Flash_Info.Length);
	
	Current_Page_No+=8;
	
    Flash_Info.Result = 1;
}

void InitFlash(void)
{
	int i;
	ulong TargetAdd;
	
	image_size = 0;

	TargetAdd = Flash_Info.TargetAddr;
	
	FlashConfig();
	
	MMU_Init();
		
	for(i=0;i<4096;i++) Flash_Info.BadBlockTable[i]=0;
	
	for(i=1;i<4096;i++)
	{
		if(!Bad_Block_Check(i)) Flash_Info.BadBlockTable[i]=1;
	}
	
	Current_Block_No = 0;
	Current_Page_No = 0;
	
	/* Calculate the Block Address */

⌨️ 快捷键说明

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