📄 flash.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 + -