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 + -
显示快捷键?