Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1049996
  • 博文数量: 178
  • 博客积分: 10222
  • 博客等级: 上将
  • 技术积分: 2215
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-03 11:27
个人简介

有所追求

文章分类

全部博文(178)

文章存档

2012年(1)

2011年(5)

2010年(3)

2009年(78)

2008年(91)

我的朋友

分类:

2008-01-28 11:05:01

 
---------------------------------------
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;
}

阅读(3618) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~