📄 sst_flash_routines.c
字号:
/***************************************************************************
Copyright ARM Limited 1998 - 2003. All rights reserved.
****************************************************************************
SST_Flash_Routines.c
Flash routines for SST Flash devices
Written for and tested on SST39VF400A Flash devices on an ARM Evaluator-7T
****************************************************************************/
#include "Evaluator.h"
// Various constants
#define TRUE 1
#define FALSE 0
#define PASS 0
#define FAIL -1
// Command Set Commands
// For erase operations, 6 data values must be written to correct 6 address in sequence.
// For word write, a 3 word sequence is used, followed by the address/data to be written.
#define CMD_ADDR_CYCLE_1 (unsigned int *)((int)FLASH_BASE+(0x5555<<1))
#define CMD_DATA_CYCLE_1 0xAAAA
#define CMD_ADDR_CYCLE_2 (unsigned int *)((int)FLASH_BASE+(0x2AAA<<1))
#define CMD_DATA_CYCLE_2 0x5555
#define CMD_ADDR_CYCLE_3 (unsigned int *)((int)FLASH_BASE+(0x5555<<1))
#define ERASE_DATA_CYCLE_3 0x8080
#define PROG_DATA_CYCLE_3 0xA0A0
#define ERASE_ADDR_CYCLE_4 (unsigned int *)((int)FLASH_BASE+(0x5555<<1))
#define ERASE_DATA_CYCLE_4 0xAAAA
#define ERASE_ADDR_CYCLE_5 (unsigned int *)((int)FLASH_BASE+(0x2AAA<<1))
#define ERASE_DATA_CYCLE_5 0x5555
#define ESECTOR_DATA_CYCLE_6 0x3030
#define EBLOCK_DATA_CYCLE_6 0x5050
#define ECHIP_DATA_CYCLE_6 0x1010
// SST Status masks
#define INVERT_BIT 0x80
#define TOGGLE_BIT 0x40
static int ReadyWait(volatile unsigned int*);
// This issues a (short sized) command to the Flash device.
// If multiple parrallel devices are used (eg 2 * 16 bit Flash parts providing 32 bit memory)
// The command is issued to all devices
static int command(unsigned short command, unsigned int *address)
{
#ifdef fc16x2
{
*(volatile unsigned int *)address = ((unsigned int)command | (unsigned int)command<<16);
}
#endif
#ifdef fc16x1
{
*(volatile unsigned short *)address = (unsigned short)command;
}
#endif
#ifdef fc32x1
{
*(volatile unsigned int *)address = (unsigned int)command;
}
#endif
#ifdef fc8x1
{
*(volatile unsigned char *)address = (unsigned char)command;
}
#endif
#ifdef fc8x2
{
*(volatile unsigned short *)address = ((unsigned short)command | (unsigned short)command<<8);
}
#endif
#ifdef fc8x4
{
*(volatile unsigned short *)address = ((unsigned int)command | (unsigned int)command<<8 | (unsigned int)command<<16 | (unsigned int)command<<24);
}
#endif
return PASS;
}
// This routine writes a single 32 bit word to Flash. On entry, it assumes the
// For 16-bit access flash, Little Endian is presumed.
int Flash_Write_Word(unsigned int *address, unsigned int data)
{
#ifdef fc32x1 // Enter Write mode, then simply write the word.
command(CMD_DATA_CYCLE_1, CMD_ADDR_CYCLE_1);
command(CMD_DATA_CYCLE_2, CMD_ADDR_CYCLE_2);
command(PROG_DATA_CYCLE_3, CMD_ADDR_CYCLE_3);
*(volatile unsigned int*)address = data; // Write data
ReadyWait(address); // Wait for write to complete.
#endif
#ifdef fc16x2 // Enter Write mode, then both devices are ready for the data, so simply write the word.
command(CMD_DATA_CYCLE_1, CMD_ADDR_CYCLE_1);
command(CMD_DATA_CYCLE_2, CMD_ADDR_CYCLE_2);
command(PROG_DATA_CYCLE_3, CMD_ADDR_CYCLE_3);
*(volatile unsigned int*)address = data; // Write data
ReadyWait(address);
#endif
#ifdef fc16x1 // ***ASSUMES LITTLE ENDIAN***
int i;
short shdata;
for (i=0;i<2;i++)
{
shdata=(short)data;
command(CMD_DATA_CYCLE_1, CMD_ADDR_CYCLE_1);
command(CMD_DATA_CYCLE_2, CMD_ADDR_CYCLE_2);
command(PROG_DATA_CYCLE_3, CMD_ADDR_CYCLE_3);
*((volatile unsigned short*)address+i) = shdata;// Write 16 bits of data
ReadyWait(address); // Wait for write to complete.
data=data>>16;
}
#endif
#ifdef fc8x4
int i;
signed char chdata;
for (i=0;i<4;i++)
{
chdata=(unsigned char)data;
command(CMD_DATA_CYCLE_1, CMD_ADDR_CYCLE_1);
command(CMD_DATA_CYCLE_2, CMD_ADDR_CYCLE_2);
command(PROG_DATA_CYCLE_3, CMD_ADDR_CYCLE_3);
*((volatile unsigned char*)address+i) = chdata;// Write 16 bits of data
ReadyWait(address); // Wait for write to complete.
data=data>>8;
}
#endif
#ifdef fc8x2
#error ("8x2 code not written");
#endif
#ifdef fc8x1
#error ("8x1 code not written");
#endif
if (*address != data) // Read word back to verify
return FAIL;
else
return PASS;
}
// This function returns base and size to cover all blocks required to hold size bytes from address.
int Flash_Calc_Blocks(unsigned int **address, int *size)
{
int *endadd;
int temp;
int blockmask;
blockmask=(FLASH_BLOCK<<2)-1;
temp=(int)(*address+*size/4);
temp=temp & ~blockmask;
endadd=(int *)(temp + FLASH_BLOCK);
*address=(unsigned int *)((int)*address & ~blockmask);
*size=((int)endadd-(int)*address);
return PASS;
}
// This function writes an arbitary area of flash.
// It first verfies that the data will fit within the flash address space,
// Then Flash_Write_Word to perform the write.
int Flash_Write_Area(unsigned int *address, int *data, int size)
{
size=size>>2; // Convert number of bytes to number of words.
if ((address >= FLASH_BASE) && ((address+size) <= (FLASH_BASE + FLASH_SIZE)))
{
for (;size>0;size--)
Flash_Write_Word(address++, *(data++));
return PASS;
}
else
{
return FAIL;
}
}
// This function erases a single block, specified by it's base address
// In fact, at the moment 4K "Sectors" are used instead of 64K "Blocks"
static int Flash_Erase_Block(unsigned int *address)
{
command(CMD_DATA_CYCLE_1, CMD_ADDR_CYCLE_1);
command(CMD_DATA_CYCLE_2, CMD_ADDR_CYCLE_2);
command(ERASE_DATA_CYCLE_3, CMD_ADDR_CYCLE_3);
command(ERASE_DATA_CYCLE_4, ERASE_ADDR_CYCLE_4);
command(ERASE_DATA_CYCLE_5, ERASE_ADDR_CYCLE_5);
command(ESECTOR_DATA_CYCLE_6, address);
ReadyWait(address); // Wait for erase attempt to complete
return (PASS);
}
// This function erases all blocks overlapping specified region (via calls to Flash_Erase_Block)
int Flash_Erase_Blocks(unsigned int *address, int size)
{
unsigned int* limit=address+size/4-1;
for(;address<=limit;address+=FLASH_BLOCK/4)
Flash_Erase_Block(address);
return PASS;
}
// This checks the status register, and loops untill the Flash device is 'ready'
static int ReadyWait(volatile unsigned int* address)
{
unsigned short value1;
unsigned short value2;
value1 = *(volatile unsigned short*)address & TOGGLE_BIT;
do
{
value2 = value1;
value1 = *(volatile unsigned short*)address & TOGGLE_BIT;
}
while(value1!=value2);
return PASS;
}
int Flash_Init ()
{
return PASS;
}
int Flash_Close ()
{
return PASS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -