📄 sst39f080.c
字号:
/***********************************************************************/
/* Copyright Silicon Storage Technology, Inc. (SST), 1994-2001 */
/* Example "C" language Driver of 39VF080 4 Mbit Multi-Purpose Flash */
/* Chi Chung Yin, Silicon Storage Technology, Inc. */
/* */
/* Revision 1.0, Sept. 12, 2001 */
/* */
/***********************************************************************/
#define _39F080
#include "includes.h"
#define SECTOR_SIZE 256 /* Must be 128 bytes for */
#define SECTOR_BYTES 4096
#define BLOCKSIZE 16
#define SST_ID 0xBF /* SST Manufacturer's ID code */
#define SST_39VF080 0xd8 /* SST 39VF080 device code */
#define FIRST_ADDR_IDENTIFY 0x05555
#define SECOND_ADDR_IDENTIFY 0x02AAA
#define MANUFACTURERIDADDR 0x00000
#define DEVICEID 0x00001
/*************************************************************************/
/* PROCEDURE: Check_SST_39VF080 */
/* */
/* This procedure decides whether a physical hardware device has a */
/* SST 39VF080 8 Mbit Multi-Purpose Flash installed or not. */
/* */
/* Input: */
/* None */
/* */
/* Output: */
/* return TRUE: indicates a SST 39VF080 */
/* return FALSE: indicates not a SST 39VF080 */
/************************************************************************/
void Change_Bank(DWORD addr)
{
static uchar Bank_Status = 0;
if(Bank_Status)
{
if(addr<BANK_DIFFER_ADDR)
{
Bank_Status = 0;
bsr0 = 0;
}
}
else
{
if(addr>=BANK_DIFFER_ADDR)
{
Bank_Status = 1;
bsr0 = 1;
}
}
}
int Check_SST_39VF080(void)
{
UCHAR SST_id1;
UCHAR SST_id2;
/* Issue the Software Product ID code to 39VF080 */
asm("fclr I");
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0XAA); /* set up address to be 5555h */
Addressing_One_Byte(SECOND_ADDR_IDENTIFY,0X55);
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0X90);
asm("fset I");
Delay10ms(1); /* check DATABOOK for the most */
/* accurate value -- Tida */
/* Read the product ID from 39VF080 */
SST_id1 = Read_One_Byte(MANUFACTURERIDADDR); /* get first ID byte */
SST_id2 = Read_One_Byte(DEVICEID); /* get first ID byte */
/* Determine whether there is a SST 39VF080 installed or not */
if ((SST_id1 == SST_ID) && (SST_id2 ==SST_39VF080))
FlashState = TRUE;
else
FlashState = FALSE;
/* Issue the Soffware Product ID Exit code thus returning the 39VF080 */
/* to the read operating mode */
asm("fclr I");
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0XAA); /* set up address to be 5555h */
Addressing_One_Byte(SECOND_ADDR_IDENTIFY,0X55);
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0XF0);
asm("fset I");
Delay10ms(1); /* check DATABOOK for the most */
/* accurate value -- Tida */
return(FlashState);
}
/*************************************************************************/
/* PROCEDURE: Erase_Entire_Chip */
/* */
/* This procedure can be used to erase the entire chip. */
/* */
/* Input: */
/* Src SOURCE address which the erase operation will start */
/* */
/* Output: */
/* NONE */
/************************************************************************/
void Erase_Entire_Chip(void)
{
/* Issue the Sector Erase command to 39VF080 */
asm("fclr I");
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0XAA); /* set up address to be 5555h */
Addressing_One_Byte(SECOND_ADDR_IDENTIFY,0X55);
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0X80);
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0XAA); /* set up address to be 5555h */
Addressing_One_Byte(SECOND_ADDR_IDENTIFY,0X55);
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0X10);
asm("fset I");
Delay10ms(11); /* check DATABOOK for the most */
/* accurate value -- Tsce */
}
/*************************************************************************/
/* PROCEDURE: Erase_One_Sector */
/* */
/* This procedure can be used to erase a total of 4096 bytes. */
/* */
/* Input: */
/* Src SOURCE address which the erase operation will start */
/* */
/* Output: */
/* NONE */
/************************************************************************/
void Erase_One_Sector(WORD block)
{
/* Issue the Sector Erase command to 39VF080 */
clr_watchdog();
asm("fclr I");
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0XAA); /* set up address to be 5555h */
Addressing_One_Byte(SECOND_ADDR_IDENTIFY,0X55);
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0X80);
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0XAA); /* set up address to be 5555h */
Addressing_One_Byte(SECOND_ADDR_IDENTIFY,0X55);
Addressing_One_Byte((DWORD)block*SECTOR_BYTES,0X30);
asm("fset I");
Delay10ms(3); /* check DATABOOK for the most */
/* accurate value -- Tse */
}
void Write_Bytes(DWORD addr,LPBYTE pSrc,WORD SrcLen)
{
WORD i;
if(addr%SECTOR_BYTES==0)
{
Erase_One_Sector((WORD)(addr/SECTOR_BYTES));
}
for(i=0;i<SrcLen;i++)
{
Program_One_Byte(pSrc+i,addr+i);
}
//Uart1TxString("\r\nWrite bytes ok\r\n",20);
}
void Write_One_Byte(LPBYTE SrcByte, DWORD DstAddr,WORD sector)
{
Program_One_Byte(SrcByte,(DWORD)(DstAddr+(DWORD)((DWORD)sector*(DWORD)SECTOR_BYTES)));
}
void Addressing_One_Byte(DWORD addr,UCHAR Dst)
{
UCHAR far *pointer;
Change_Bank(addr);
addr &= BANK_MASK_ADDR;
pointer=(UCHAR far*)(addr+FALSH_OFFER_ADDR);
*pointer=Dst;
}
UCHAR Read_One_Byte(DWORD addr)
{
UCHAR far *temp;
asm("fclr I");
Change_Bank(addr);
addr &= BANK_MASK_ADDR;
temp=(UCHAR far*)(addr+FALSH_OFFER_ADDR);
asm("fset I");
//asm("NOP");
return(*temp);
}
uchar Read_Sector_Byte(WORD sector,DWORD addr)
{
DWORD darr;
darr = sector;
darr <<= 12;
darr += addr;
return Read_One_Byte(darr);
}
/************************************************************************/
/* PROCEDURE: Program_One_Byte */
/* */
/* This procedure can be used to program ONE byte of date to the */
/* 39VF080. */
/* */
/* NOTE: It is VERY important the sector containing the byte to be */
/* programmed was ERASED first. */
/* */
/* Input: */
/* Src The BYTE which will be written to the 39VF080. */
/* Dst DESTINATION address which will be written with the */
/* data passed in from Src */
/* */
/* Output: */
/* None */
/************************************************************************/
void Program_One_Byte (LPBYTE SrcByte, DWORD DstAddr)
{
asm("fclr I");
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0XAA); /* set up address to be 5555h */
Addressing_One_Byte(SECOND_ADDR_IDENTIFY,0X55);
Addressing_One_Byte(FIRST_ADDR_IDENTIFY,0XA0);
Addressing_One_Byte(DstAddr,SrcByte[0]); /* transfer the byte to destination */
asm("fset I");
Check_Toggle_Ready(DstAddr,SrcByte[0]); /* wait for TOGGLE bit to get ready */
}
/************************************************************************/
/* PROCEDURE: Check_Toggle_Ready */
/* */
/* During the internal program cycle, any consecutive read operation */
/* on DQ6 will produce alternating 0's and 1's i.e. toggling between */
/* 0 and 1. When the program cycle is completed, DQ6 of the data will */
/* stop toggling. After the DQ6 data bit stops toggling, the device is */
/* ready for next operation. */
/* */
/* Input: */
/* Dst must already set-up by the caller */
/* */
/* Output: */
/* None */
/************************************************************************/
void Check_Toggle_Ready (DWORD addr,UCHAR src)
{
UCHAR Loop = TRUE;
UCHAR PreData;
UCHAR CurrData;
PreData = src;
PreData = PreData & 0x40;
asm("fclr I");
TenMsecCount=0;
asm("fset I");
while((TenMsecCount< 1000) && (Loop))
{
clr_watchdog();
CurrData =Read_One_Byte(addr);
CurrData = CurrData & 0x40;
if (PreData == CurrData)
Loop = FALSE; /* ready to exit the while loop */
PreData = CurrData;
}
}
/************************************************************************/
/* PROCEDURE: Check_Data_Polling */
/* */
/* During the internal program cycle, any attempt to read DQ7 of the */
/* last byte loaded during the page/byte-load cycle will receive the */
/* complement of the true data. Once the program cycle is completed, */
/* DQ7 will show true data. */
/* */
/* Input: */
/* Dst must already set-up by the caller */
/* True Datathis is the original (true) data */
/* */
/* Output: */
/* None */
/************************************************************************/
void Check_Data_Polling (DWORD addr,UCHAR TrueData)
{
UCHAR Loop = TRUE;
UCHAR CurrData;
TrueData = TrueData & 0x80;
asm("fclr I");
TenMsecCount=0;
asm("fset I");
while ((TenMsecCount< 500) && (Loop))
{
clr_watchdog();
CurrData = Read_One_Byte(addr);
CurrData = CurrData & 0x80;
if (TrueData == CurrData)
{
Loop = FALSE; /* ready to exit the while loop */
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -