---------------------------------------
sst39vf160.h
---------------------------------------
#ifndef __FLASH_H__
#define __FLASH_H__
/* Define the specific for the flash memory system */
#define MANU_ID 0xBF
#define TARGET_ID "S3CEV40"
#define FLASH_TYPE "SST39VF160"
#define FLASH_ID 0x2782
#define SECTOR_SIZE 4096
// FLASH 起始地址
#define FLASH_BASE_ADDRESS 0x02000000
/* FLASH Mask */
#define FLASH_MASK 0x00FFFFFF
#define SECTOR_MASK 0xFFFFF000
/* Local routine defines for the flashwrt.c module */
#define MIN_NO_OF_ARGS 3
#define FILL_PATTERN 0x5a
/* Timeout loop count */
#define TIME_OUT 100000
/* command word */
// 左移一位从A[20..1]上发出,因为A[1]对应FLASH的A[0]
#define FLASH_SEQ_ADD_1 (0x5555 << 1)
#define FLASH_SEQ_ADD_2 (0x2AAA << 1)
#define FLASH_WORD_COM_1 ((short)0xAAAA)
#define FLASH_WORD_COM_2 ((short)0x5555)
#define WRITE_WORD_COM ((short)0xA0A0)
#define ID_IN_WORD_COM ((short)0x9090)
#define ID_OUT_WORD_COM ((short)0xF0F0)
#define ERASE_SECTOR_CODE1 ((short)0x8080)
#define CHIP_SECTOR_CODE1 ((short)0x1010)
#define ERASE_SECTOR_CODE2 ((short)0x3030)
/********************************/
/* DEFINE BANK 0 DATA BUS WIDTH */
/********************************/
#define B0SIZE_BYTE 0x1
#define B0SIZE_SHORT 0x2
#define B0SIZE_WORD 0x3
#define _B0SIZE B0SIZE_SHORT // Select Bank0 bus width
#if _B0SIZE == B0SIZE_BYTE
typedef unsigned char pB0SIZE;
#elif _B0SIZE == B0SIZE_SHORT
typedef unsigned short pB0SIZE;
#elif _B0SIZE == B0SIZE_WORD
typedef unsigned long pB0SIZE;
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*****************************************/
/* Functions for SST SST39VF160D */
/*****************************************/
//extern int Program(int addr_base, char* pData, int data_size);
//extern int erase_flash(int base_addr);
//extern void SST_SectorErase(unsigned long addr);
//extern void SST_BlockErase(unsigned long addr);
extern int SST_WordProg(unsigned long addr,unsigned short dat);
extern int SST_Identify(void);
extern int SST_SectorProg(unsigned long addr,pB0SIZE *data,int size);
//extern int SST_Identify(void);
#endif /* __FLASH_H__ */
---------------------------------------
sst39vf160.c
---------------------------------------
#include "sst39vf160.h"
#include "ucUart.h"
#include "hmi.h"
#include "Error.h"
#include "bar.h"
#define WRITE_FLASH(addr,dat) *((volatile unsigned short *)(addr)) = (unsigned short)dat
#define READ_FLASH(addr) (*((volatile unsigned short *)(addr)))
#define SST_WAIT_TIME 10000
static void WaitForEndOfPrg(void)
{
volatile unsigned int old_status,new_status;
int i = SST_WAIT_TIME;
old_status = READ_FLASH(FLASH_BASE_ADDRESS + 0); // Read data from anyhere
while(i--)
{
new_status = READ_FLASH(FLASH_BASE_ADDRESS + 0);
// 读取 BIT6 位,检测擦写是否结束
// 编程过程中,BIT6 在‘0’、‘1’交替
if((old_status & 0x40) == (new_status & 0x40))
break;
else
old_status = new_status;
}
if(i == 0) // 超时结束
{
SysError.error_no = ERROR_HMI_FLASH;
GUI_EndDialog(HMI_GetCurCenterWindow(),0);
HMI_StateSet(HMI_SYS_ERROR); // 显示错误界面
}
}
// 扇区擦除函数
void SST_SectorErase(unsigned long addr)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
// 擦除过程关中断
OS_ENTER_CRITICAL();
// 擦除指令顺序,将相应命令字送入相应地址
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,FLASH_WORD_COM_1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_2,FLASH_WORD_COM_2);
// 写入擦除命令字
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,ERASE_SECTOR_CODE1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,FLASH_WORD_COM_1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_2,FLASH_WORD_COM_2);
// 擦除相应地址扇区
WRITE_FLASH(addr,ERASE_SECTOR_CODE2);
OS_EXIT_CRITICAL();
// 等待擦除结束
WaitForEndOfPrg();
}
// 块擦除
void SST_BlockErase(unsigned long addr)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_ENTER_CRITICAL();
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,FLASH_WORD_COM_1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_2,FLASH_WORD_COM_2);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,ERASE_SECTOR_CODE1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,FLASH_WORD_COM_1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_2,FLASH_WORD_COM_2);
WRITE_FLASH(addr,ERASE_SECTOR_CODE2);
OS_EXIT_CRITICAL();
WaitForEndOfPrg();
}
// 整片擦除
void SST_ChipErase(void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_ENTER_CRITICAL();
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,FLASH_WORD_COM_1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_2,FLASH_WORD_COM_2);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,ERASE_SECTOR_CODE1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,FLASH_WORD_COM_1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_2,FLASH_WORD_COM_2);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,CHIP_SECTOR_CODE1);
OS_EXIT_CRITICAL();
WaitForEndOfPrg();
}
// 字编程
int SST_WordProg(unsigned long addr,unsigned short dat)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_ENTER_CRITICAL();
// 执行命令字
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,FLASH_WORD_COM_1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_2,FLASH_WORD_COM_2);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,WRITE_WORD_COM);
// 写入数据
WRITE_FLASH(addr,dat);
OS_EXIT_CRITICAL();
WaitForEndOfPrg();
return 0;
}
// 读取扇区
// 传入参数:起始地址,存放数据首址
int SST_ReadSector(unsigned long addr,pB0SIZE *data)
{
int i;
// 将无符号长整型转化为地址指针,付给局部指针p_addr
pB0SIZE * p_addr = (pB0SIZE *)addr;
// pB0SIZE是外部FLASH的宽度,对于大小为SECTOR_SIZE的数据
// 类型为pB0SIZE,需要读取SECTOR_SIZE / sizeof(pB0SIZE)次
// 程序这样写具有通用性,只要修改硬件连接,可以自适应8BIT,16BIT,32BIT
for(i=0; i<(SECTOR_SIZE / sizeof(pB0SIZE)); i++)
{
*data++ = *p_addr++;
}
return 0;
}
// 设置缓冲区,数组大小为SECTOR_SIZE / sizeof(pB0SIZE)
// 数组的数据类型为pB0SIZE,对应存储器宽度
static pB0SIZE buffer[SECTOR_SIZE / sizeof(pB0SIZE)];
// 写入数据
// 参数:起始地址,数据首址,size为数据区长度
int SST_SectorProg(unsigned long addr,pB0SIZE *data,int size)
{
int i;
unsigned long base_addr = addr & SECTOR_MASK;
if(addr + size > (addr & SECTOR_MASK) + SECTOR_SIZE)
{
Comm2_Printf("Error!\n");
return RE_ERROR;
}
// 写入前要先擦除
SST_ReadSector(addr & SECTOR_MASK,buffer);
SST_SectorErase(addr & SECTOR_MASK);
// 更新缓冲区(在SDRAM中)
for(i=addr; i< base_addr + SECTOR_SIZE; i+= sizeof(pB0SIZE)) // Upadata buff
{
buffer[(i - base_addr) / sizeof(pB0SIZE)] = *data;
data++;
}
// 将缓冲区数据(在SDRAM中)写入FLASH
for(i=0; i<SECTOR_SIZE; i+=sizeof(pB0SIZE)) // Write all the sector
{
SST_WordProg(base_addr + i,buffer[i / sizeof(pB0SIZE)]);
}
// 写入成功返回
return RE_SUCCESS;
}
int SST_Identify(void)
{
int manuf_code,device_code;
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,FLASH_WORD_COM_1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_2,FLASH_WORD_COM_2);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,ID_IN_WORD_COM);
WaitForEndOfPrg();
manuf_code = READ_FLASH(FLASH_BASE_ADDRESS + 0);
device_code = READ_FLASH(FLASH_BASE_ADDRESS + 2);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,FLASH_WORD_COM_1);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_2,FLASH_WORD_COM_2);
WRITE_FLASH(FLASH_BASE_ADDRESS + FLASH_SEQ_ADD_1,ID_OUT_WORD_COM);
WaitForEndOfPrg();
Comm2_Printf("manuf is: %x\tdevice is: %x\n",manuf_code,device_code);
return device_code;
}