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

📄 nandflash.c

📁 对nand_flash的擦除、编程算法源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************/
/*                                                                       */
/* 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 SAMSUNG
//#define TOSHIBA

#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
volatile ushort *AutoKick_reg = (ushort *)0x80003404;  //MSM6250
//volatile ushort *AutoKick_reg = (ushort *)0x80001b40;  //MSM6500

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

uchar TempBuf[BLOCK_SIZE];
uchar FillBuf[PAGE_SIZE];
ulong Current_Block_No = 2;
ulong Current_Page_No = 0;
ulong BIB_Block_No = 1;
ulong LastAddr = 0;

ulong crc = 0;
ulong image_size = 0;
/* The CRC table size is based on how many bits at a time we are going
** to process through the table.  Given that we are processing the data
** 8 bits at a time, this gives us 2^8 (256) entries.
*/
#define CRC_TAB_SIZE    256             /* 2^CRC_TAB_BITS      */

/* CRC table for 30 bit CRC, with generator polynomial 0x6030b9c7,
** calculated 8 bits at a time, MSB first.
*/
const ulong crc30_table[ CRC_TAB_SIZE ] = {
  0x00000000, 0x2030b9c7, 0x2051ca49, 0x0061738e,
  0x20932d55, 0x00a39492, 0x00c2e71c, 0x20f25edb,
  0x2116e36d, 0x01265aaa, 0x01472924, 0x217790e3,
  0x0185ce38, 0x21b577ff, 0x21d40471, 0x01e4bdb6,
  0x221d7f1d, 0x022dc6da, 0x024cb554, 0x227c0c93,
  0x028e5248, 0x22beeb8f, 0x22df9801, 0x02ef21c6,
  0x030b9c70, 0x233b25b7, 0x235a5639, 0x036aeffe,
  0x2398b125, 0x03a808e2, 0x03c97b6c, 0x23f9c2ab,
  0x240a47fd, 0x043afe3a, 0x045b8db4, 0x246b3473,
  0x04996aa8, 0x24a9d36f, 0x24c8a0e1, 0x04f81926,
  0x051ca490, 0x252c1d57, 0x254d6ed9, 0x057dd71e,
  0x258f89c5, 0x05bf3002, 0x05de438c, 0x25eefa4b,
  0x061738e0, 0x26278127, 0x2646f2a9, 0x06764b6e,
  0x268415b5, 0x06b4ac72, 0x06d5dffc, 0x26e5663b,
  0x2701db8d, 0x0731624a, 0x075011c4, 0x2760a803,
  0x0792f6d8, 0x27a24f1f, 0x27c33c91, 0x07f38556,
  0x2824363d, 0x08148ffa, 0x0875fc74, 0x284545b3,
  0x08b71b68, 0x2887a2af, 0x28e6d121, 0x08d668e6,
  0x0932d550, 0x29026c97, 0x29631f19, 0x0953a6de,
  0x29a1f805, 0x099141c2, 0x09f0324c, 0x29c08b8b,
  0x0a394920, 0x2a09f0e7, 0x2a688369, 0x0a583aae,
  0x2aaa6475, 0x0a9addb2, 0x0afbae3c, 0x2acb17fb,
  0x2b2faa4d, 0x0b1f138a, 0x0b7e6004, 0x2b4ed9c3,
  0x0bbc8718, 0x2b8c3edf, 0x2bed4d51, 0x0bddf496,
  0x0c2e71c0, 0x2c1ec807, 0x2c7fbb89, 0x0c4f024e,
  0x2cbd5c95, 0x0c8de552, 0x0cec96dc, 0x2cdc2f1b,
  0x2d3892ad, 0x0d082b6a, 0x0d6958e4, 0x2d59e123,
  0x0dabbff8, 0x2d9b063f, 0x2dfa75b1, 0x0dcacc76,
  0x2e330edd, 0x0e03b71a, 0x0e62c494, 0x2e527d53,
  0x0ea02388, 0x2e909a4f, 0x2ef1e9c1, 0x0ec15006,
  0x0f25edb0, 0x2f155477, 0x2f7427f9, 0x0f449e3e,
  0x2fb6c0e5, 0x0f867922, 0x0fe70aac, 0x2fd7b36b,
  0x3078d5bd, 0x10486c7a, 0x10291ff4, 0x3019a633,
  0x10ebf8e8, 0x30db412f, 0x30ba32a1, 0x108a8b66,
  0x116e36d0, 0x315e8f17, 0x313ffc99, 0x110f455e,
  0x31fd1b85, 0x11cda242, 0x11acd1cc, 0x319c680b,
  0x1265aaa0, 0x32551367, 0x323460e9, 0x1204d92e,
  0x32f687f5, 0x12c63e32, 0x12a74dbc, 0x3297f47b,
  0x337349cd, 0x1343f00a, 0x13228384, 0x33123a43,
  0x13e06498, 0x33d0dd5f, 0x33b1aed1, 0x13811716,
  0x14729240, 0x34422b87, 0x34235809, 0x1413e1ce,
  0x34e1bf15, 0x14d106d2, 0x14b0755c, 0x3480cc9b,
  0x3564712d, 0x1554c8ea, 0x1535bb64, 0x350502a3,
  0x15f75c78, 0x35c7e5bf, 0x35a69631, 0x15962ff6,
  0x366fed5d, 0x165f549a, 0x163e2714, 0x360e9ed3,
  0x16fcc008, 0x36cc79cf, 0x36ad0a41, 0x169db386,
  0x17790e30, 0x3749b7f7, 0x3728c479, 0x17187dbe,
  0x37ea2365, 0x17da9aa2, 0x17bbe92c, 0x378b50eb,
  0x185ce380, 0x386c5a47, 0x380d29c9, 0x183d900e,
  0x38cfced5, 0x18ff7712, 0x189e049c, 0x38aebd5b,
  0x394a00ed, 0x197ab92a, 0x191bcaa4, 0x392b7363,
  0x19d92db8, 0x39e9947f, 0x3988e7f1, 0x19b85e36,
  0x3a419c9d, 0x1a71255a, 0x1a1056d4, 0x3a20ef13,
  0x1ad2b1c8, 0x3ae2080f, 0x3a837b81, 0x1ab3c246,
  0x1b577ff0, 0x3b67c637, 0x3b06b5b9, 0x1b360c7e,
  0x3bc452a5, 0x1bf4eb62, 0x1b9598ec, 0x3ba5212b,
  0x3c56a47d, 0x1c661dba, 0x1c076e34, 0x3c37d7f3,
  0x1cc58928, 0x3cf530ef, 0x3c944361, 0x1ca4faa6,
  0x1d404710, 0x3d70fed7, 0x3d118d59, 0x1d21349e,
  0x3dd36a45, 0x1de3d382, 0x1d82a00c, 0x3db219cb,
  0x1e4bdb60, 0x3e7b62a7, 0x3e1a1129, 0x1e2aa8ee,
  0x3ed8f635, 0x1ee84ff2, 0x1e893c7c, 0x3eb985bb,
  0x3f5d380d, 0x1f6d81ca, 0x1f0cf244, 0x3f3c4b83,
  0x1fce1558, 0x3ffeac9f, 0x3f9fdf11, 0x1faf66d6
};

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

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

    Flash_Info.Result = 0;
	Flash_Info.TargetAddr &= 0x3FFFFFF;
	wSize = 0;

	if(Flash_Info.TargetAddr != LastAddr) {
		fillsize = Flash_Info.TargetAddr - LastAddr;
		for(i = 0; i < PAGE_SIZE; i++)
			FillBuf[i] = 0xff;

	    while(fillsize && (Current_Block_No < BLOCK_COUNT))
	    {
	    	if(!(Current_Page_No%PAGE_CNT)) {
	    		if(!PrepareBlock())
	    			return;
	    	}
	    	
	    	if(Current_Block_No >= BLOCK_COUNT)
	    		return;
	    		
			status = WriteChar(FillBuf, Current_Page_No);
			if(!status) // error
					return;
			
			ReadChar(TempBuf, Current_Page_No*PAGE_SIZE, PAGE_SIZE);
			if(!Verification((ulong *)TempBuf, PAGE_SIZE, (ulong *)FillBuf))
				return;
			
			Current_Page_No++;
			crc = crc_30_step (crc, FillBuf, (ushort)PAGE_SIZE*8);
			image_size +=PAGE_SIZE;
			fillsize -= PAGE_SIZE;

			AutoKick();
	    }
	}

	AutoKick();
	
	srcP = (uchar *)Flash_Info.Buf;
	len = Flash_Info.Length;
    
    while(len && (Current_Block_No < BLOCK_COUNT))
    {
    	if(!(Current_Page_No%PAGE_CNT)) {
    		if(!PrepareBlock())
    			return;
    	}
    	
    	if(Current_Block_No >= BLOCK_COUNT)
    		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);
		if(!status) // error
				return;
		
//		ReadChar(TempBuf, Current_Page_No*PAGE_SIZE, PAGE_SIZE);
//		if(!Verification((ulong *)TempBuf, PAGE_SIZE, (ulong *)srcP))
//			return;
		
		Current_Page_No++;
		crc = crc_30_step (crc, srcP, (ushort)PAGE_SIZE*8);
		wSize +=PAGE_SIZE;
		image_size +=PAGE_SIZE;
		len -= flen;
		srcP += PAGE_SIZE;
		
		AutoKick();
    }

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

// Chip erase function
void EraseAll(void)
{
	Flash_Info.Result = 1; // 8Mbyte
}

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

void WriteBIB(void)
{
	struct boot_info_block *bib;
	ulong i, bib_size, status;

	Flash_Info.Result = 0;

	bib = (struct boot_info_block *)Flash_Info.Buf;
	bib->magic1 = MAGIC1;
	bib->magic2 = MAGIC2;
	bib->version = BIB_VERSION;
	bib->crc = crc;
	bib->startaddr = 0x0;
	bib->length = image_size;
	bib_size = sizeof(struct boot_info_block);
	
	for(i=bib_size; i<PAGE_SIZE; i++)
		Flash_Info.Buf[i] = 0xff;
		
	OneBlockErase(BIB_Block_No);

	status = WriteChar(Flash_Info.Buf, BIB_Block_No*PAGE_CNT);
	if(!status)
		return;
		
	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;
	
	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)
	;

	/* 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;
}

ulong PrepareBlock(void)
{

	while(!Bad_Block_Check(++Current_Block_No))
		;
		
	if(Current_Block_No >= BLOCK_COUNT)
		return 0;

	if(!OneBlockErase(Current_Block_No))
		return 0;
		
	Current_Page_No = Current_Block_No*PAGE_CNT;

	return 1;
}

int BlankCheck(ulong *targetP,ulong targetSize) 
{
	ulong i;
	
	for(i=0; i<targetSize; i+=4)

⌨️ 快捷键说明

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