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

📄 sst39vf800a.c

📁 一款常用FLASH芯片SST39VF800A的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************flash_sst39vf800a******************/
/*
   sst39vf800a:   512k x  16bit

  1. Manufacturer’s ID 0000H 00BFH
  2. Device ID         0001H 2781H
  3. Software Command Sequence
                       Addr1 Data2 Addr1 Data2 Addr1 Data2 Addr1 Data2 Addr1 Data2 Addr1 Data2
     Word-Program      5555H AAH   2AAAH 55H   5555H A0H   WA3   Data
     Sector-Erase      5555H AAH   2AAAH 55H   5555H 80H   5555H AAH   2AAAH 55H   SAX   30H
     Block-Erase       5555H AAH   2AAAH 55H   5555H 80H   5555H AAH   2AAAH 55H   BAX   50H
     Chip-Erase        5555H AAH   2AAAH 55H   5555H 80H   5555H AAH   2AAAH 55H   5555H 10H
     Software ID Entry 5555H AAH   2AAAH 55H   5555H 90H
     CFI Query Entry5  5555H AAH   2AAAH 55H   5555H 98H
     Software ID Exit7/XXH F0H
     CFI Exit
     Software ID Exit7/5555H AAH 2AAAH 55H 5555H F0H
     CFI Exit

Address Data Data
10H 0051H Query Unique ASCII string “QRY”
11H 0052H
12H 0059H
13H 0001H Primary OEM command set
14H 0007H
15H 0000H Address for Primary Extended Table
16H 0000H
17H 0000H Alternate OEM command set (00H = none exists)
18H 0000H
19H 0000H Address for Alternate OEM extended Table (00H = none exits)
1AH 0000H

1BH 0027H1 VDD Min (Program/Erase)0030H1 DQ7-DQ4: Volts, DQ3-DQ0: 100 millivolts
1CH 0036H VDD Max (Program/Erase)DQ7-DQ4: Volts, DQ3-DQ0: 100 millivolts
1DH 0000H VPP min (00H = no VPP pin)
1EH 0000H VPP max (00H = no VPP pin)
1FH 0004H Typical time out for Word-Program 2N μs (24 = 16 μs)
20H 0000H Typical time out for min size buffer program 2N μs (00H = not supported)
21H 0004H Typical time out for individual Sector/Block-Erase 2N ms (24 = 16 ms)
22H 0006H Typical time out for Chip-Erase 2N ms (26 = 64 ms)
23H 0001H Maximum time out for Word-Program 2N times typical (21 x 24 = 32 μs)
24H 0000H Maximum time out for buffer program 2N times typical
25H 0001H Maximum time out for individual Sector/Block-Erase 2N times typical (21 x 24 = 32 ms)
26H 0001H Maximum time out for Chip-Erase 2N times typical (21 x 26 = 128 ms)

27H 0014H Device size = 2N Bytes (14H = 20; 220 = 1 MByte)
28H 0001H Flash Device Interface description; 0001H = x16-only asynchronous interface
29H 0000H
2AH 0000H Maximum number of bytes in multi-byte write = 2N (00H = not supported)
2BH 0000H
2CH 0002H Number of Erase Sector/Block sizes supported by device
2DH 00FFH Sector Information (y + 1 = Number of sectors; z x 256B = sector size)
2EH 0000H y = 255 + 1 = 256 sectors (00FFH = 255)
2FH 0010H
30H 0000H z = 16 x 256 Bytes = 4 KByte/sector (0010H = 16)
31H 000FH Block Information (y + 1 = Number of blocks; z x 256B = block size)
32H 0000H y = 15 + 1 = 16 blocks (000FH = 15)
33H 0000H
34H 0001H z = 256 x 256 Bytes = 64 KByte/block (0100H = 256)


   4.Program/Erase Cycle Timing Parameters
    Word-Program Time                 20 μs
    Software ID Access and Exit Time 150 ns
    Sector-Erase                      25 ms
    Block-Erase                       25 ms
    Chip-Erase                       100 ms

**************************************************/
// error enum
#include <stdlib.h>
#include "Errors.h"

// #defines
#define TRUE			0x1
#define FALSE			0x0
#define BUFFER_SIZE		0x600
#define	NUM_SECTORS 	256				// number of sectors in the flash device

// structure for flash sector information
typedef struct _SECTORLOCATION{
	long lStartOff;
	long lEndOff;
}SECTORLOCATION;


// Flash Programmer commands
typedef enum
{
	NO_COMMAND,		// 0
	GET_CODES,		// 1
	RESET,			// 2
	WRITE,			// 3
	FILL,			// 4
	ERASE_ALL,		// 5
	ERASE_SECT,		// 6
	READ,			// 7
	GET_SECTNUM,	// 8
	GET_SECSTARTEND	// 9
}enProgCmds;

// #defines for the assembler
asm ("#define FLASH_START_L 0x0000");
asm ("#define FLASH_START_H 0x2000");

// function prototypes
//库函数
ERROR_CODE ReadFlash( unsigned long ulOffset, int *pnValue );
ERROR_CODE WriteFlash( unsigned long ulOffset, int nValue );
ERROR_CODE PollToggleBit(unsigned long ulOffset);
ERROR_CODE UnlockFlash(unsigned long ulOffset);
//功能函数
ERROR_CODE SetupForFlash(void);
ERROR_CODE GetCodes(void);
ERROR_CODE ResetFlash(void);
ERROR_CODE EraseFlash(void);
ERROR_CODE EraseBlock( int nBlock );
ERROR_CODE WriteData( unsigned long ulStart, long lCount, long lStride, int *pnData );
ERROR_CODE FillData( unsigned long ulStart, long lCount, long lStride, int *pnData );
ERROR_CODE ReadData( unsigned long ulStart, long lCount, long lStride, int *pnData );

ERROR_CODE GetSectorNumber( unsigned long ulOffset, int *pnSector );
ERROR_CODE GetSectorStartEnd( long *lStartOff, long *lEndOff, int nSector );

// global data for use with the VisualDSP++ plug-in
char 			*AFP_Title = "TAP WATCH";
char 			*AFP_Description = "SST 39VF800A";
enProgCmds 		AFP_Command = NO_COMMAND;
int 			AFP_ManCode = -1;				// 0xBF = SST
int 			AFP_DevCode = -1;				// 0x2781 = 39VF800A
unsigned long 	AFP_Offset = 0x0;               // Flash Start
int 			*AFP_Buffer;                    //       从GUI中取数
long 			AFP_Size = BUFFER_SIZE;         //       供GUI使用
long 			AFP_Count = -1;                 // 无效, 从GUI中取数
long 			AFP_Stride = -1;                // 无效, 从GUI中取数
int 			AFP_NumSectors = NUM_SECTORS;
//long 			AFP_SectorSize1 = 0x10000;
//int 			AFP_SectorSize2 = 0x2000;
long 			AFP_SectorSize = 0x1000;           //4K BYTES

int 			AFP_Sector = -1;                // 无效, 从GUI中取数
int 			AFP_Error 			= 0;			// contains last error encountered
bool 			AFP_Verify 			= FALSE;		// verify writes or not
long 			AFP_StartOff 		= 0x0;			// sector start offset
long 			AFP_EndOff 			= 0x0;			// sector end offset
int				AFP_FlashWidth		= 0x10;			// width of the flash device
int 			*AFP_SectorInfo;
SECTORLOCATION SectorInfo[NUM_SECTORS];



// flag telling us that the flash had to be reset
char reset = 0x0;

// exit flag
bool bExit = FALSE;

// *********************
// Map of flash sectors
// *********************

// FLASH

// 		Type			START ADDR    	END ADDR		SECTOR NUM
// 		-------			----------		--------		----------
// 		Main Flash		0x20000000		0x200FFFFF		00 - 255



main()
{
	int i = 0;
	// by making AFP_Buffer as big as possible the plug-in can send and
	// receive more data at a time making the data transfer quicker
	//
	// by allocating it on the heap the compiler does not create an
	// initialized array therefore making the driver image smaller
	// and faster to load
	//
	// we have modified the linker description file (LDF) so that the heap
	// is large enough to store BUFFER_SIZE elements at this point
	AFP_Buffer = (int *)malloc(BUFFER_SIZE);

	// AFP_Buffer will be NULL if we could not allocate storage for the
	// buffer
	if ( AFP_Buffer == NULL )
	{
		// tell GUI that our buffer was not initialized
		AFP_Error = BUFFER_IS_NULL;
	}

	//initiate sector information structures
	for(i=0;i<AFP_NumSectors; i++)
	{
		GetSectorStartEnd(&SectorInfo[i].lStartOff, &SectorInfo[i].lEndOff, i);
	}

	AFP_SectorInfo = (int*)&SectorInfo[0];

	// setup the flash so the DSP can access it
	SetupForFlash();

	//setup code so that flash programmer can just read memory instead of call GetCodes().
	GetCodes();

	// command processing loop
	while ( !bExit )
	{
		// the plug-in will set a breakpoint at "AFP_BreakReady" so it knows
		// when we are ready for a new command because the DSP will halt
		//
		// the jump is used so that the label will be part of the debug
		// information in the driver image otherwise it may be left out
		// since the label is not referenced anywhere
		asm("AFP_BreakReady:");
		if ( FALSE )
			asm("jump AFP_BreakReady;");

		// switch on the command
		switch ( AFP_Command )
		{
			// get manufacturer and device codes
			case GET_CODES:
				AFP_Error = GetCodes();
				break;

			// reset
			case RESET:
				AFP_Error = ResetFlash();
				break;

			// write
			case WRITE:
				AFP_Error = WriteData( AFP_Offset, AFP_Count, AFP_Stride, AFP_Buffer );
				break;

			// fill
			case FILL:
				AFP_Error = FillData( AFP_Offset, AFP_Count, AFP_Stride, AFP_Buffer );
				break;

			// erase all
			case ERASE_ALL:
				AFP_Error = EraseFlash();
				break;

			// erase sector
			case ERASE_SECT:
				AFP_Error = EraseBlock( AFP_Sector );
				break;

			// read
			case READ:
				AFP_Error = ReadData( AFP_Offset, AFP_Count, AFP_Stride, AFP_Buffer );
				break;

			// get sector number based on address
			case GET_SECTNUM:
				AFP_Error = GetSectorNumber( AFP_Offset, &AFP_Sector );
				break;

			// get sector number start and end offset
			case GET_SECSTARTEND:
				AFP_Error = GetSectorStartEnd( &AFP_StartOff, &AFP_EndOff, AFP_Sector );
				break;

			// no command or unknown command do nothing
			case NO_COMMAND:
			default:
				// set our error
				AFP_Error = UNKNOWN_COMMAND;
				break;
		}

		// clear the command
		AFP_Command = NO_COMMAND;
	}

	// free the buffer if we were able to allocate one
	if ( AFP_Buffer )
		free( AFP_Buffer );


	// all done
	return 0;
}


//////////////////////////////////////////////////////////////
// ERROR_CODE SetupForFlash()
//
// Perform necessary setup for the processor to talk to the
// flash such as external memory interface registers, etc.
//
//////////////////////////////////////////////////////////////

ERROR_CODE SetupForFlash()
{
	asm("#define EBIU_AMGCTL 0xFFC00A00");

	// setup EBIU_AMGCTL reg (enable all banks)
	asm("p0.l = EBIU_AMGCTL & 0xFFFF;");
	asm("p0.h = (EBIU_AMGCTL >> 16) & 0xFFFF;");
	asm("r0 = 0x0f;");
	asm("w[p0] = r0;");

	return NO_ERR;
}


//////////////////////////////////////////////////////////////
// ERROR_CODE WriteData()
//
// Write a buffer to flash.
//
// Inputs:	unsigned long ulStart - offset in flash to start the writes at
//			long lCount - number of elements to write, in this case bytes
//			long lStride - number of locations to skip between writes
//			int *pnData - pointer to data buffer
//
//////////////////////////////////////////////////////////////

ERROR_CODE WriteData( unsigned long ulStart, long lCount, long lStride, int *pnData )
{
    //Word-Program
    //             5555H AAH 2AAAH 55H 5555H A0H WA3 Data
	long i = 0;						// loop counter
	int j = 0;						// inner loop counter
	unsigned long ulOffset = ulStart;// current offset to write
	int iShift = 0;					// shift value by iShift bits
	int iNumWords = 2;				// number of words in a long
	int nLeftover = lCount % 4;		// how much if any do we have leftover to write
	ERROR_CODE ErrorCode = NO_ERR;	// tells whether there was an error trying to write
	int nCompare = 0;				// value that we use to verify flash
	bool bVerifyError = FALSE;		// lets us know if there was a verify error
	int nSector = 0;

	// if the user wants to verify then do it
	if( AFP_Verify == TRUE )
	{
		// write the buffer up to BUFFER_SIZE items
		for (i = 0; (i < lCount/4) && (i < BUFFER_SIZE); i++)
		{
			for (iShift = 0, j = 0; ( ( j < iNumWords ) && ( ErrorCode == NO_ERR ) ); j++, ulOffset += (lStride * 2))
			{
				// check to see that the address is within a valid sector
				ErrorCode = GetSectorNumber( ulOffset, &nSector );
				if( NO_ERR == ErrorCode )
				{
					// unlock the flash, do the write, increase shift, and wait for completion
					UnlockFlash(ulOffset);
					WriteFlash( ulOffset, (pnData[i] >> iShift) );  //iShift=0写低16位
					                                                //iShift=16写高16位
					ErrorCode = PollToggleBit(ulOffset);
					ReadFlash( ulOffset, &nCompare );
					if( nCompare != ( (pnData[i]  >> iShift) & 0x0000FFFF ) )
					{
						bVerifyError = TRUE;
						break;
					}
					iShift += 16;
				}
				else
				{	// handle error
					bVerifyError = TRUE;
					return ErrorCode;
				}
			}
		}

		// because of the way our ldr file is built, we will always have
		// 2 bytes leftover if there is leftover, because the flash is 16 bit
		// that will mean only one write to do.
		if( ( nLeftover > 0 ) && ( ErrorCode == NO_ERR ) && bVerifyError == FALSE )
		{
			// check to see that the address is within a valid sector
			ErrorCode = GetSectorNumber( ulOffset, &nSector );
			if( NO_ERR == ErrorCode )
			{
				// unlock the flash, do the write, increase shift, and wait for completion
				UnlockFlash(ulOffset);
				WriteFlash( ulOffset, pnData[i] );
				ErrorCode = PollToggleBit(ulOffset);
				ReadFlash( ulOffset, &nCompare );
				if( nCompare != ( pnData[i] & 0x0000FFFF ) )
				{
					bVerifyError = TRUE;
				}
			}
			else
			{
				return ErrorCode;
			}
		}

		// return appropriate error code if there was a verification error
		if( bVerifyError == TRUE )
			return VERIFY_WRITE;
	}
	// the user does not want to verify
	else
	{
		// write the buffer up to BUFFER_SIZE items
		for (i = 0; (i < lCount/4) && (i < BUFFER_SIZE); i++)
		{
			for (iShift = 0, j = 0; ( ( j < iNumWords ) && ( ErrorCode == NO_ERR ) ); j++, ulOffset += (lStride * 2))
			{

				// check to see that the address is within a valid sector
				ErrorCode = GetSectorNumber( ulOffset, &nSector );
				if( NO_ERR == ErrorCode )
				{
					// unlock the flash, do the write, increase shift, and wait for completion
				    UnlockFlash(ulOffset);
					WriteFlash( ulOffset, (pnData[i] >> iShift) );//iShift=0写低16位
					                                              //iShift=16写高16位
					ErrorCode = PollToggleBit(ulOffset);
					iShift += 16;
				}
				else
				{
					return ErrorCode;
				}
			}
		}

		// because of the way our ldr file is built, we will always have
		// 2 bytes leftover if there is leftover, because the flash is 16 bit
		// that will mean only one write to do.
		if( ( nLeftover > 0 ) && ( ErrorCode == NO_ERR ) )
		{

			// check to see that the address is within a valid sector
			ErrorCode = GetSectorNumber( ulOffset, &nSector );
			if( NO_ERR == ErrorCode )
			{
				// unlock the flash, do the write, increase shift, and wait for completion
				UnlockFlash(ulOffset);
				WriteFlash( ulOffset, pnData[i] );
				ErrorCode = PollToggleBit(ulOffset);
			}
			else
			{
				return ErrorCode;
			}
		}

	}

	// return the appropriate error code
	return ErrorCode;
}


//////////////////////////////////////////////////////////////
// ERROR_CODE FillData()
//
// Fill flash with a value.
//
// Inputs:	unsigned long ulStart - offset in flash to start the writes at
//			long lCount - number of elements to write, in this case bytes
//			long lStride - number of locations to skip between writes
//			int *pnData - pointer to data buffer
//
//////////////////////////////////////////////////////////////

ERROR_CODE FillData( unsigned long ulStart, long lCount, long lStride, int *pnData )

⌨️ 快捷键说明

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