sst36vf1601c_x16mode.cpp
来自「SST公司」· C++ 代码 · 共 635 行 · 第 1/3 页
CPP
635 行
/* segment (from 000010H--000017H) in SST36VF1601C. */
/* */
/* NOTE: */
/* 1. Before run this subroutine, call above SecID_Lock_Status( )to */
/* make sure User SecID segment is NOT locked. */
/* 2. Call Query_SecID(WORD *SST_SecID, WORD *User_SecID) to read back */
/* all programmed data to verify if they match original data. */
/* 3. It's recommended to lock out User SecID after programming. */
/* 4. There's no way to unlock the User SecID once it's locked. */
/* */
/* Input: *SrcWord Pointer to source data */
/* Dst Valid address in User SecID from 000010h to 000017h.*/
/* length Number of words needs to be programmed. */
/* */
/* Output: TRUE for successful programming. */
/* FALSE for timeout error or invalid parameter Dst or length. */
/************************************************************************/
BYTE User_SecID_Word_Program(WORD *SrcWord, U32 Dst, BYTE length)
{
BYTE ReturnStatus=TRUE;
if (Dst<0x10 || Dst>0x17 ) return FALSE;
if (length>8 || (Dst+length)>0x17) return FALSE;
while (length--)
{ *(WORD *) (BaseAddrs + 0x5555*AddrsShift) = 0xAA; // 1st write data 0xAA to device addr 5555H for A14 to A0
*(WORD *) (BaseAddrs + 0x2AAA*AddrsShift) = 0x55; // 2nd write data 0x55 to device addr 2AAAH for A14 to A0
*(WORD *) (BaseAddrs + 0x5555*AddrsShift) = 0xA5; // 3rd write data 0xA5 to device addr 5555H for A14 to A0
*(WORD *) (BaseAddrs + Dst*AddrsShift) = *SrcWord; // 4th write data WORD *SrcWord to destination Dst
++Dst; // point to next address
++SrcWord; // point to next data
// Read the toggle bit to detect end-of-programming for User Sec ID. Or delay 10us for every WORD programming.
// DO Not use Data# Polling DQ7 for User_SecID_Word_Program!! (Refer to datasheet.)
ReturnStatus = Check_ToggleDQ6(Dst, WordProgramTime); // wait for TOGGLE bit to get ready
if (!ReturnStatus)
return FALSE; // User_SecID_Word_Program failed!
}
return TRUE;
}
/************************************************************************/
/* PROCEDURE: User_SecID_Lock_Out */
/* */
/* This procedure locks out User Security ID. */
/* */
/* NOTE: */
/* 1. Data in User SecID segment can't be erased, They are OTP. */
/* 2. User SecID segment can't be unlocked once it's locked. */
/* */
/* Input: None */
/* */
/* Output: TRUE if successfully locked after programming. */
/* FALSE if timeout error or failed to lock User SecID. */
/************************************************************************/
BYTE User_SecID_Lock_Out(void)
{
BYTE ReturnStatus=TRUE;
if(SecID_Lock_Status( )) // double check if it's already locked.
return TRUE; // return TRUE if locked.
*(WORD *) (BaseAddrs + 0x5555*AddrsShift) = 0xAA; // 1st write data 0xAA to device addr 5555H for A14 to A0
*(WORD *) (BaseAddrs + 0x2AAA*AddrsShift) = 0x55; // 2nd write data 0x55 to device addr 2AAAH for A14 to A0
*(WORD *) (BaseAddrs + 0x5555*AddrsShift) = 0x85; // 3rd write data 0x85 to device addr 5555H for A14 to A0
*(WORD *) (BaseAddrs + 0x12345*AddrsShift) = 0x00; // 4th write data 0x00 to any address such as 0x123456
ReturnStatus = Check_ToggleDQ6(0, WordProgramTime); // wait for TOGGLE bit to get ready
if(ReturnStatus && SecID_Lock_Status( )) // double check if it's really locked.
return TRUE; // return TRUE if locked.
else return FALSE; // otherwise, return FALSE.
}
/************************************************************************/
/* PROCEDURE: Erase_Suspend */
/* */
/* This procedure temporarily suspends a Sector/Block-Erase operation. */
/* */
/* Input: None */
/* */
/* Output: None */
/************************************************************************/
void Erase_Suspend(void)
{ *(WORD *) (BaseAddrs + 0x5678*AddrsShift) = 0xB0; // write data 0xB0 into any address, e.g.5678H
Delay_20_Microseconds(); // The device will be ready to read after 20us.
}
/************************************************************************/
/* PROCEDURE: Erase_Resume */
/* */
/* This procedure resumes the suspended Sector-Erase or Block-Erase. */
/* */
/* Input: Dst Any address within suspended Sector/Block-Erase. */
/* */
/* Output: TRUE if success, otherwise FALSE if timeout. */
/************************************************************************/
BYTE Erase_Resume(U32 Dst)
{ BYTE ReturnStatus=TRUE;
*(WORD *) (BaseAddrs + 0x89ABC*AddrsShift) = 0x30; // write data 0x30 to any address, e.g.89ABCH
// Then there are three ways to determine when internal operation will be ready:
// First check DQ6, Secondly check DQ7, Lastly delay 25ms.
ReturnStatus=Check_ToggleDQ6(Dst, BlockEraseTime); // because BlockEraseTime=SectorEraseTime.
// ReturnStatus = Check_DataPollingDQ7(Dst, 0xFFFF, BlockEraseTime); // wait until DQ7 outputs 1
return ReturnStatus; // Don't return to caller until erase is completed!
}
/************************************************************************/
/* PROCEDURE: Check_ToggleDQ6 */
/* */
/* During the internal erase/program, any consecutive read operation */
/* on DQ6 will produce alternating 0's and 1's, i.e. toggling between */
/* 0 and 1. When the operation is completed, DQ6 will stop toggling. */
/* */
/* Input:Dst Any valid device address of erase/programming. */
/* MaxCycles Maximum cycles allowed for this erase or programming.*/
/* */
/* Output: TRUE if success, otherwise FALSE if timeout. */
/************************************************************************/
BYTE Check_ToggleDQ6(U32 Dst, U32 MaxCycles)
{
WORD CurrData, PreData;
U32 TimeOut = 0;
PreData = *(WORD *) (BaseAddrs + Dst*AddrsShift); // read data
PreData = PreData & 0x40; // get DQ6
while (TimeOut < MaxCycles) // check if time-out
{ CurrData = *(WORD *) (BaseAddrs + Dst*AddrsShift); // read again
CurrData = CurrData & 0x40; // retrieve bit DQ6
if (PreData == CurrData)
{ CurrData = *(WORD *) (BaseAddrs + Dst*AddrsShift); // To make sure it's true that DQ6 stops toggling,
CurrData = CurrData & 0x40; // so read two additional times before exit.
PreData = *(WORD *) (BaseAddrs + Dst*AddrsShift);
PreData = PreData & 0x40;
if (PreData == CurrData)
return TRUE; // return true if DQ6 stops toggling.
else continue; // otherwise, continue to check DQ6 toggling.
}
PreData = CurrData;
TimeOut++;
}
return FALSE; // timeout error
}
/************************************************************************/
/* PROCEDURE: Check_DataPollingDQ7 */
/* */
/* During internal program, any attempt to read DQ7 of the last */
/* word data loaded will receive the complement of the true data. */
/* Once the program cycle is completed, DQ7 will show true data. */
/* */
/* For erase, DQ7 will output 0 during busy of internal operation. */
/* DQ7 will ouput 1 once the internal erase operation is completed. */
/* */
/* Input:Dst Any valid device address of erase/programming. */
/* TrueData This is the original (true) data. */
/* MaxCycles Maximum cycles allowed for this erase/programming. */
/* */
/* Output: TRUE if success, otherwise FALSE if timeout. */
/************************************************************************/
BYTE Check_DataPollingDQ7(U32 Dst, WORD TrueData, U32 MaxCycles)
{
WORD CurrData;
U32 Timeout = 0;
TrueData = TrueData & 0x80; // keep DQ7 only
while (Timeout < MaxCycles) // compare if timeout
{
CurrData = *(WORD *) (BaseAddrs + Dst*AddrsShift); // read data WORD.
CurrData = CurrData & 0x80; // get bit DQ7
if (CurrData == TrueData)
{CurrData = *(WORD *) (BaseAddrs + Dst*AddrsShift); // To make sure device is really ready,
CurrData = CurrData & 0x80; // so read two additional times before exit.
if(CurrData != TrueData) continue;
CurrData = *(WORD *) (BaseAddrs + Dst*AddrsShift); // 2nd read data WORD.
CurrData = CurrData & 0x80; // get bit DQ7 again
if(CurrData != TrueData) continue;
return TRUE; // return TRUE if DQ7 outputs true data.
}
Timeout++;
}
return FALSE; // otherwise, return FALSE if timeout error.
}
void Delay_150_Nanoseconds(void) // delay 150ns.
{for(int i=0; i<10; i++); // change the number 10 according to your system speed.
}
void Delay_1_Microsecond(void) // delay 1us
{for(int i=0; i<70; i++); // change number 70 according to your system speed.
}
void Delay_20_Microseconds(void) // delay 20us.
{for(int i=0; i<0x5000; i++); // change number 0x5000 according to your system speed.
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?