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

📄 flash.c

📁 一款交换机BSP开发代码
💻 C
字号:
/*
 * STAR NETWORKS TECHNOLOGY CO.,LTD.
 * Copyright (c) 1999-2000, All rights reserved.
 *
 * FILE NAME
 *
 *		flash.c
 *
 * ABSTRACTS
 *
 *		Flash memory program.
 *
 * HISTORY
 *
 *		01 2000-10-23 	ZXH		created.
 */

#include "flash.h"

int Flash_Type ;
unsigned int CTRL_CODE_ADDR;
extern int VER_FLAG;

/* Reset to read array. */

void Flash_Reset (volatile unsigned short *base_address)
{
	if( IS_SST_FLASH(Flash_Type) )
	{
		base_address[0x5555] = 0xf0;
	}
	else if ( IS_INTEL_FLASH(Flash_Type) )
	{
		base_address[0] = 0xff;
	}
}

/* Read flash memory ID. */

unsigned long get_flash_id (volatile unsigned short *base_address)
{
	unsigned short l, h;

	// sst flash command
	base_address[0x5555] = 0xaa;
	base_address[0x2aaa] = 0x55;
	// intel flash command
	base_address[0x5555] = 0x90;

	h = base_address[0x00];
	l = base_address[0x01];

	if(h==1)
		l&=0xff;

	return ((unsigned long) h << 16) | l;
}

void Init_Flash(volatile unsigned short *base_address)
{
	unsigned long	flash_id;
	unsigned short	manu_id,dev_id;

	flash_id = get_flash_id( base_address );

	switch(flash_id)
	{
	case SST39VF800:
		Flash_Type = 1;
		CTRL_CODE_ADDR = 0x1e0000;//错误值
		break;

	case SST39VF160:
		CTRL_CODE_ADDR = 0x1e0000;
		Flash_Type = 2;
		break;
		
	case SST39VF1601:
		CTRL_CODE_ADDR = 0x1e0000;
		Flash_Type = 2;
		break;

	case SST39VF1602:
		CTRL_CODE_ADDR = 0x1e0000;
		Flash_Type = 2;
		break;

	case INTEL28F800T:
		CTRL_CODE_ADDR = 0x1e0000;//错误值
		Flash_Type = 3;
		break;

	case INTEL28F800B:
		CTRL_CODE_ADDR = 0x1e0000;//错误值
		Flash_Type = 4;
		break;

	case INTEL28F160T:
		CTRL_CODE_ADDR = 0x1e0000;//错误值
		Flash_Type = 5;
		break;

	case INTEL28F160B:
		CTRL_CODE_ADDR = 0x1e0000;//错误值
		Flash_Type = 6;
		break;

	case INTEL28F320T:
		CTRL_CODE_ADDR = 0x1e0000;//错误值
		Flash_Type = 7;
		break;

	case INTEL28F320B:
		CTRL_CODE_ADDR = 0x1e0000;//错误值
		Flash_Type = 8;
		break;
//hl 2002.10.31 add
	case AM29DL323DB:
		CTRL_CODE_ADDR = 0x3e0000;
		Flash_Type = 9;
		break;


	default:
		CTRL_CODE_ADDR = 0x1e0000;
		Flash_Type = 0;
		break;
	}

	Flash_Reset ( base_address );

}


/* INTEL :read status data */
unsigned short read_status(volatile unsigned short *base_address,int timeout)
{
	int loop ;
	unsigned short status;
	// read status
#ifdef	_BOOT
	loop = timeout;
      if(!VER_FLAG)
		SET_TCN1_1(0);
	else
		SET_TCN1_2(0);

	do
	{
		// read status
		base_address[0] = 0x70;
		status = base_address[0];

		// Check WSMS
		if (status & 0x80 )
		{
			break;
		}

            if(!VER_FLAG)
           {
		if (READ_TCN1_1() > TIMER1_10MS_COUNT)
		{
			SET_TCN1_1(0);
			loop --;
		}
           }
	   else
	   {
	   	if (READ_TCN1_2() > TIMER1_10MS_COUNT)
		{
			SET_TCN1_2(0);
			loop --;
		}
	   }
	}
	while(loop);
#else
	loop = GET_SYS_CLOCK();

	do
	{
		// read status
		base_address[0] = 0x70;
		status = base_address[0];

		// Check WSMS
		if (status & 0x80 )
		{
			break;
		}
	}
	while (GET_SYS_CLOCK() - loop < timeout);
#endif	// _BOOT

	//clear status register
	base_address[0] = 0x50;

	// reset flash
	base_address[0] = 0xff;

	return status;
}

/* INTEL flash :change block lock status */

int Lock_Status( volatile unsigned short *block_address,int lock_status)
{
	unsigned short status,sts;
	int i,flag;

	//assert(lock_status)
	
	// reset flash
	Flash_Reset(block_address);
	
	//get lock status befor change status	
//	sts = get_lock_status(block_address);

	for ( i = FLASH_TIMES ; i > 0 ; i -- )
	{
		// config setup
		block_address[0] = 0x60;
		
		// lock status
		*((unsigned char *)block_address) = lock_status;

		// read status
		status = read_status(block_address,200);

		flag = -1;
		//check status register bit4,5,7
		if ( (status & 0xf0) == 0x80 )
		{
			// read configuation
			block_address[0] = 0x90;

			// block lock status data
			status = block_address[2];
			
			switch( lock_status )
			{
				case INTEL_LOCK:	status &=3;
									sts = BLOCK_LOCK;
									break;
				case INTEL_UNLOCK:	status &=3;
									sts = BLOCK_UNLOCK;
									break;
				case INTEL_LOCKDOWN:status &=2;
									sts = BLOCK_LOCKDOWN;
									break;
			}
			if( status == sts )
			{
				flag = 0;
				break;
			}
		}
	}

	Flash_Reset(block_address);
	return flag;
}


/* Program data to flash memory.  up to one block */

int Flash_Program (
	volatile unsigned short *base_address,
	volatile unsigned short *dptr, unsigned short *sptr, int length)
	{
	int i;
	unsigned short a, b;
	unsigned long loop,block_addr,flag;

	if ( IS_INTEL_FLASH(Flash_Type) )
	{
		// unlock block
		block_addr = (unsigned long ) dptr - (unsigned long)base_address;

		if ( block_addr & 0xffff0000)
		{
			// 64KB block
			block_addr &= 0xffff0000;

		}
		else
		{
			// 8KB block
			block_addr &= 0xffffe000;

		}

		block_addr += (unsigned long)base_address;
		// change lock status
		if ( Lock_Status((unsigned short *)block_addr,INTEL_UNLOCK ) )
		{
			return -1;
		}

	}

	flag = 0;

	// Check flash type
	if ( IS_SST_FLASH(Flash_Type) )
	{
		for (i = 0; i < length; i++, sptr++, dptr++)
		{
			base_address[0x5555] = 0xaa;
			base_address[0x2aaa] = 0x55;
			base_address[0x5555] = 0xa0;

			a = *sptr;
			*dptr = a;

			a &= 0x80;

#ifdef	_BOOT

			loop = 200;		// 2S
		if(!VER_FLAG)
			SET_TCN1_1(0);
		else
			SET_TCN1_2(0);

			do
			{
				// Check write data ok
				b = (*dptr)&0x80;

				if ( a == b )
				{
					b = (*dptr)&0x80;
					if ( a == b )
					{
						b = (*dptr)&0x80;
						if ( a == b )
							break;
					}
				}
				//break;
				if(!VER_FLAG)
				{
					if ( READ_TCN1_1() > TIMER1_10MS_COUNT )
					{
						// clear TCN1
						SET_TCN1_1(0);
						loop --;
					}
				}
				else
				{
					if ( READ_TCN1_2() > TIMER1_10MS_COUNT )
					{
						// clear TCN1
						SET_TCN1_2(0);
						loop --;
					}
				}
			}
			while ( loop );
#else
			loop = GET_SYS_CLOCK();

			do
			{
				// Check write data ok
				b = (*dptr)&0x80;
				if ( a == b )
				{
					b = (*dptr)&0x80;
					if ( a == b )
					{
						b = (*dptr)&0x80;
						if ( a == b )
							break;
					}
				}
			}
			while (GET_SYS_CLOCK() - loop < 200);	//2S

#endif	//_BOOT

			if ( a != b )
			{
				// SST Program Error
				flag = -1;
				break;
			}
		}
	}
	else if ( IS_INTEL_FLASH(Flash_Type) )
	{
		for (i = 0; i < length; i++, sptr++, dptr++)
		{
			base_address[0] = 0x40;

			a = *sptr;
			*dptr = a;

			// read status data
			// check .7 .3 .4 .1 for error
			if ( (read_status(base_address,200) & 0x9A)  != 0x80 )
			{
				flag = -1;
				break;
			}
			// check write data
			b = *dptr;

			if ( a != b )
			{
				// INTEL Program Error
				flag = -1;
				break;
			}
		}
	}

	if ( IS_SST_FLASH(Flash_Type) )
	{
		// flash reset
		base_address[0x5555] = 0xf0;
	}

	else if ( IS_INTEL_FLASH(Flash_Type) )
	{
		// lock block
		if ( Lock_Status((unsigned short *)block_addr,INTEL_LOCK ) )
		{
			return -1;
		}
	}

	return flag;
 }


/* SST:Erase flash memory by sector. */

int sst_erase_sector (volatile unsigned short *base_address, int offset)
{
	int	i;
	unsigned long loop;
	unsigned long *lptr;

	/* Blank check */

	lptr = (unsigned long*) &base_address[offset];

	for (i = 0; i < 0x400; i++) if (lptr[i] != 0xffffffff) break;

	if (i == 0x400) return 0; /* Already erased */

	/* Issue erase command */

	base_address[0x5555] = 0xaa;
	base_address[0x2aaa] = 0x55;
	base_address[0x5555] = 0x80;

	base_address[0x5555] = 0xaa;
	base_address[0x2aaa] = 0x55;
	base_address[offset] = 0x30;

	/* Wait for completion */
#ifdef	_BOOT

	loop = 1000;
	if(!VER_FLAG)
		SET_TCN1_1(0);
	else
		SET_TCN1_2(0);

	do
	{
		// check data polling
		if ((base_address[offset] & 0x80) == 0x80) return 0;

             if(!VER_FLAG)
             	{
			if ( READ_TCN1_1() > TIMER1_10MS_COUNT )
			{
				SET_TCN1_1(0);
				loop --;
			}
             	}
		else
		{
			if ( READ_TCN1_2() > TIMER1_10MS_COUNT )
			{
				SET_TCN1_2(0);
				loop --;
			}
		}
	}
	while( loop );

#else

	loop = GET_SYS_CLOCK ();

	do
	{
		if ((base_address[offset] & 0x80) == 0x80) return 0;
	}
	while (GET_SYS_CLOCK () - loop < 1000);

#endif	// _BOOT

	return -1;
}

/* SST:Erase flash memory by block. */

int sst_erase_block (volatile unsigned short *base_address, int offset)
{
	int	i;
	unsigned long loop;
	unsigned long *lptr;

	/* Blank check */

	lptr = (unsigned long*) &base_address[offset];

	for (i = 0; i < 0x4000; i++) if (lptr[i] != 0xffffffff) break;

	if (i == 0x4000) return 0; /* Already erased */

	/* Issue erase command */

	base_address[0x5555] = 0xaa;
	base_address[0x2aaa] = 0x55;
	base_address[0x5555] = 0x80;

	base_address[0x5555] = 0xaa;
	base_address[0x2aaa] = 0x55;
	base_address[offset] = 0x50;

	/* Wait for completion */
#ifdef	_BOOT

	loop = 1000;
	if(!VER_FLAG)
		SET_TCN1_1(0);
	else
		SET_TCN1_2(0);

	do
	{
		// check data polling
		if ((base_address[offset] & 0x80) == 0x80) return 0;
		if(!VER_FLAG)
		{
			if ( READ_TCN1_1() > TIMER1_10MS_COUNT )
			{
				SET_TCN1_1(0);
				loop --;
			}
		}
		else
		{
			if ( READ_TCN1_2() > TIMER1_10MS_COUNT )
			{
				SET_TCN1_2(0);
				loop --;
			}
		}
	}
	while( loop );

#else

	loop = GET_SYS_CLOCK ();

	do
	{
		if ((base_address[offset] & 0x80) == 0x80) return 0;
	}
	while (GET_SYS_CLOCK () - loop < 1000);

#endif	// _BOOT

	return -1;
}

/* Erase flash memory by block(intel). */

int Flash_Erase (volatile unsigned short *base_address , int offset)
{
//	unsigned long loop;
	int	flag=0;

	if ( IS_SST_FLASH(Flash_Type) )
	{
		if ( offset & 0xffff0000 )
		{
			// 64KB block
			if (sst_erase_block(base_address,(offset & 0xffff0000)/2))
			{
				// reset flash
				base_address[0x5555] = 0xf0;
				flag = -1;
			}
		}
		else
		{
			// 8KB block
			if (sst_erase_sector(base_address,(offset & 0xffffe000)/2))
			{
				// reset flash
				base_address[0x5555] = 0xf0;
				flag = -1;
			}
			if (sst_erase_sector(base_address,(offset & 0xffffe000 + 0x1000)/2))
			{
				// reset flash
				base_address[0x5555] = 0xf0;
				flag = -1;
			}
		}
		// reset flash
		base_address[0x5555] = 0xf0;

	}

	else if ( IS_INTEL_FLASH(Flash_Type) )
	{
		int i;
		short * ptr ;
		if ( offset & 0xffff0000 )
		{
			ptr = (short *)((int)base_address + offset&0xffff0000);
			for (i = 0; i < 0x10000/2; i ++ )
			{
				if ( *ptr ++ != -1)
					break;
			}
			if (i == 0x10000/2)
				return 0;
		}
		else
		{
			ptr = (short *)((int)base_address + offset&0xffffe000);
			for ( i = 0; i < 0x2000/2; i ++)
			{
				if (*ptr ++ != -1)
					break;
			}
			if ( i== 0x2000/2)
				return 0;
		}

		offset >>= 1;
		// unlock flash
		Lock_Status(&base_address[offset],INTEL_UNLOCK);

		// erase setup
		*((char *)&base_address[offset]) = 0x20;

		// erase confirm
		*((char *)&base_address[offset]) = 0xD0;

		// read status
		// check .7 .3 .4 .5 .1 for error
		if ( (read_status(base_address,1000) & 0xBA) != 0x80 )
		{
			//Lock_Status(&base_address[offset],INTEL_LOCK);
			flag = -1;
		}
		Lock_Status(&base_address[offset],INTEL_LOCK);
	}

	return flag;
}


void Wait_10ms(void)
{
	if(!VER_FLAG)
	{
		SET_TCN1_1(0);

		while(1)
		{
			if(READ_TCN1_1() >= TIMER1_10MS_COUNT)
			{
				break;
			}
		}
	}
	else
	{
		SET_TCN1_2(0);

		while(1)
		{
			if(READ_TCN1_2() >= TIMER1_10MS_COUNT)
			{
				break;
			}
		}
	}
}
//int get_lock_status(unsigned short *block_address)
//{
//	int sts;
//	
//	// read configuation
//	block_address[0] = 0x90;
//
//	// block lock status data
//	sts = block_address[2];
//	
//	Flash_Reset(block_address);
//
//	return sts;
// }

⌨️ 快捷键说明

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