📄 sst39vf800a.c
字号:
/**************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 + -