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

📄 nandflash.c

📁 对nand_flash的擦除、编程算法源码
💻 C
字号:
/*************************************************************************/
/*                                                                       */
/* FILE NAME                                      VERSION                */
/*                                                                       */
/* source\flash.c                                  1.0                   */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*                                                                       */
/*                                                                       */
/* DATA STRUCTURES                                                       */
/*                                                                       */
/* FUNCTIONS : Flash Fujitsu program code                            */
/*                                                                       */
/* DEPENDENCIES                                                          */
/*                                                                       */
/*                                                                       */
/*                                                                       */
/*                                Copyrigth (C) 2001 AIJISYSTEM CO.,LTD  */
/*************************************************************************/

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

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

#define BASE_ADDR	(ulong)0x64000000

volatile ulong *data_reg = (ulong *)0x64000000;
volatile ulong *spare_data_reg = (ulong *)0x64000320;
volatile ulong *cle_reg = (ulong *)0x64000300;
volatile ulong *ale_reg = (ulong *)0x64000304;
volatile ulong *status_reg = (ulong *)0x64000308;
volatile ulong *ecc_read_reg = (ulong *)0x6400030c;
volatile ushort *flash_cfg_reg = (ushort *)0x6400031c;
volatile ulong *clear_status_reg = (ulong *)0x80000c84;

// WatchDog reset阑 规瘤窍扁 困茄 register
//volatile ushort *AutoKick_reg = (ushort *)0x3000600;  //MSM3000, 3100, 5000, 5105
//volatile ushort *AutoKick_reg = (ushort *)0x3000700;  //MSM5100 watch dog address
//volatile ushort *AutoKick_reg = (ushort *)0x30006d0;  //MSM6050
//volatile ushort *AutoKick_reg = (ushort *)0x3001080;  //MSM5500
volatile ushort *AutoKick_reg = (ushort *)0x80000700;  //MSM6100

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

uchar TempBuf[BLOCK_SIZE];
ulong Current_Block_No = 0;
ulong Current_Page_No = 0;


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: 
			Flash_Info.Result = 1;
				break;
		case FINIT: InitFlash();
				break;
		default :
			Flash_Info.Result = 0;
	}
}

// Flash program function
void  Program(void)
{
    Flash_Info.Result = 1;
}

// Chip erase function
void EraseAll(void)
{
	ulong i;
	
	for(i=0; i < BLOCK_COUNT; i++) 
		OneBlockErase(i);

	Flash_Info.Result = 1; // 8Mbyte
}

// Sector erase function
void EraseSector(void)
{
	ulong sBlock, eBlock, eAddr, i;
	
	eAddr = Flash_Info.TargetAddr + Flash_Info.Length - 1;
	sBlock = Flash_Info.TargetAddr >> 14;
	eBlock = eAddr >> 14;
	
	for(i=sBlock; i <= eBlock; i++) {
		if(i >= BLOCK_COUNT)
			break;
		OneBlockErase(i);
	}
	
	Flash_Info.Result = 1;
}


// 窍唱狼 Sector 父 Erase
int OneBlockErase(ulong block)
{
	ulong status;
	ulong nand_cntlr_block_addr;
	int block_size_shift;
	ushort no_of_shifts = 1;
	
	AutoKick();
	
	block_size_shift = PAGE_CNT;
	while ( block_size_shift != 2 )
	{
		block_size_shift = block_size_shift >> 1;
		no_of_shifts++;
	}

	/* Set the block address in Nand_Flash_Addr */
	nand_cntlr_block_addr = block << (9 + no_of_shifts);
	*ale_reg = nand_cntlr_block_addr;

	/* Issue the block erase command */
	*cle_reg = ERASE_CMD;

	/* Wait for erase command to be executed */
	while(*status_reg & ERASE_CMD)
		AutoKick();

	/* Check status after erase */
	status = *status_reg;
	if( (status & FS_NAND_OP_ERR_MASK != 0) ||
		(status & FS_NAND_OP_RESULT_MASK != 0) )
	{
		return 0;
	}

	return 1;
}

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

	*cle_reg = RESET_CMD;

	*cle_reg = ID_CMD;

	/* Wait for completion. */
	while(*status_reg & ID_CMD)
	{
		*AutoKick_reg = 1;
		*AutoKick_reg = 0;
	}	
	
	manId = *status_reg;
	
	
	devId = (manId >> 15) & 0xff;
	manId = (manId >> 23) & 0xff;

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


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;

//	sourceP = (ushort *)srcAddr;
	
	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, len, flen, status;

	len = size;

	for (i=0; i<size; i+=PAGE_SIZE) {
		if(len > PAGE_SIZE)
			flen = PAGE_SIZE;
		else
			flen = len;	

		*ale_reg = targetAddr & 0x01FFFE00;
		*cle_reg = READ_DATA;

		while(*status_reg & READ_DATA) {
			*AutoKick_reg = 1;
			*AutoKick_reg = 0;
		}
			
		status = *status_reg;
		
		if( (status & FS_NAND_OP_ERR_MASK != 0) || 
			(status & FS_NAND_ECC_SELF_ERR_MASK != 0) || 
			(status & FS_NAND_READ_ECC_ERR_MASK != 0) )
				return 0;		
		
//		for(j=0; j<flen; j++, data++)
//			*data = *(data_reg+j);
		memcpy((void *)data, (void *)data_reg, flen);
		data += flen;

		len -= PAGE_SIZE;
		targetAddr += PAGE_SIZE;
		
		AutoKick();
	}

	return 1;
}

int WriteChar(uchar *data, ulong page_addr)
{
	ushort status;
 
	memcpy((void *)data_reg, (void *)data, PAGE_SIZE);

	*ale_reg = page_addr << 9;
	*cle_reg = PROGRAM_CMD;

	while(*status_reg & PROGRAM_CMD)
		AutoKick();
			
	status = *status_reg;
		
	if( (status & FS_NAND_OP_ERR_MASK != 0) || 
		(status & FS_NAND_OP_RESULT_MASK != 0) )
			return 0;		

	return 1;
}


void  ReadMem(void)
{
	uchar *srcP;

	srcP = (uchar *)Flash_Info.Buf;

	ReadChar(srcP, Flash_Info.TargetAddr, Flash_Info.Length);
	
    Flash_Info.Result = 1;
}

void InitFlash(void)
{
	ulong status;  

	/* Reset NAND flash memory */
	*cle_reg = RESET_CMD;

	/* Software reset the controller. */
	*cle_reg = RESET_CTRL;

	/* Reset NAND flash memory */
	*cle_reg = RESET_CMD;

	/* Configure NAND flash */
  	*flash_cfg_reg = FS_NAND_CNFG_VAL;

	/* Wait for completion. */
	while(*status_reg & PROGRAM_CMD)
	{
		*AutoKick_reg = 1;
		*AutoKick_reg = 0;
	}	
	
	/* Do a id check. */
	*cle_reg = ID_CMD;
	
	/* Wait for completion. */
	while(*status_reg & ID_CMD)
	{
		*AutoKick_reg = 1;
		*AutoKick_reg = 0;
	}	
	
	/* Do a status check */
	*cle_reg = STATUS_CMD;
	
	/* Wait for completion. */
	while(*status_reg & STATUS_CMD)
	{
		*AutoKick_reg = 1;
		*AutoKick_reg = 0;
	}	
	
	status = *status_reg;
	
	Current_Block_No = 0;
	Current_Page_No = 0;
} 

void AutoKick(void)
{
	*AutoKick_reg = 1;
	*AutoKick_reg = 0;
}


⌨️ 快捷键说明

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