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

📄 sst39vf160.c

📁 SST39VF160在uC/OS2系统中的驱动程序。支持延缓写入功能。开发环境:ads1.2
💻 C
📖 第 1 页 / 共 2 页
字号:
#include  "config.h"

#define	  BEEPCON  0x00000080		/* P0.7引脚控制B1,低电平蜂鸣 */

#define   FLASH_SECTOR_BIT  0xFFFFF800
#define   FLASH_SECTOR_STEP 0x800

#define   FLASH_BLOCK_BIT  0xFFFF8000
#define   FLASH_BLOCK_STEP 0x8000

#ifndef NULL
#define NULL (void *) 0x00;
#endif

#define FLASH_OK 0
#define FLASH_NG 1

typedef enum {
	FLASH_INFO_MEMO_SIZE	= 0X27,		//存储器大小
	FLASH_INFO_SECTOR_NUM	= 0x2D,		//扇区数
	FLASH_INFO_SECTOR_SIZE  = 0x2F,		//扇区大小
	FLASH_INFO_BLOCK_NUM	= 0x31,		//块数
	FLASH_INFO_BLOCK_SIZE	= 0X33		//块大小
}flashInfo;

typedef enum {
	ERASE_ALL,
	ERASE_SECTOR,
	ERASE_BLOCK
}eraseType;

static uint16 flashBlockNum;
static uint16 flashSectorNum;
static uint16 flashBlockSize;
static uint16 flashSectorSize;

static uint16 *flashStaDataBack;
static uint16 *flashEndDataBack;

static uint16 startDataBuff[1024 * 2];
static uint16 endDataBuff[1024 * 2];


//*************************函数申明******************************************

//从aAddr地址获取2个字节的数据,用于获取Flash的容量、块大小、块数目、扇区大小、扇区数目等内容
uint16 readCFI(uint16 aAddr);

//循环延时:延时dly×5000次空循环
void  DelayNS(uint32  dly);

//根据aFlashInfo枚举变量不同,返回Flash的容量、块大小、块数目、扇区大小、扇区数目等信息。
//注意,当使用FLASH_INFO_MEMO_SIZE(存储器大小)为参数时,返回以兆为单位的存储器总容量(小数部分被忽略)
uint16 getFlashInfo(flashInfo aFlashInfo);

//获取Flash信息,并初始化相关全局变量。
//注意:使用相关外部接口之前必须调用本初始化函数
void flashInitial(void);

//向aAddr地址写入2个字节
//返回值:FLASH_OK表示成功,FLASH_NG表示失败
//注意:本函数目前永远返回成功。
uint16 writeFlashWord(volatile uint16 *aAddr, uint16 Data);

//从aAddr地址写入2个字节
//返回值:读取到的数据
uint16 readFlashWord(uint16 aAddr);

//向aAddr地址写入aLength个字(2个字节)的数据,写入数据存储在aData缓存之中。
//返回值:FLASH_OK表示成功,FLASH_NG表示失败
uint16 writeFlashBuff(uint16 aAddr, uint16 *aData, uint16 aLength); 

//从aAddr地址读取aLength个字(2个字节),存储到aData缓存中
//返回值:读取到的长度(单位:字)
uint16 readFlashBuff(uint16 aAddr, uint16 *aData, uint16 aLength);

//写入芯片插除前缀数据
void preEraseChip(void);

//根据清除类型aFlag(芯片、块、扇区),清除完整芯片或清除从指定地址开始的aNumber个字(16bits)
uint16 eraseChip(eraseType aFlag, volatile uint16 *aAddr, uint16 aNumber);

//进入CFI模式:在查询芯片序列号、容量大小、块大小等信息时,必须先进入CFI模式。
void enterCFISatus(void);

//进入普通模式(即:退出CFI模式)
void enterNormalSatus(void);




// FLASH的起始地址(分配为Bank1块)
#define  FLASH_ADDR		0x81000000




// 转换地址。将要发送给SST39VF160的地址值进行转换,以便于LPC2210输出。
// 由于SST39VF160的A0是与LPC2210的A1相连,所以addr要左移1位。
#define GetAddr(addr)	(volatile uint16  *)(FLASH_ADDR|(addr << 1))
#define getSectorAddr(addr) (volatile uint16 *)((FLASH_ADDR | (addr << 1)) & FLASH_SECTOR_BIT)
#define getBlockAddr(addr) (volatile uint16 *)((FLASH_ADDR | (addr << 1)) & FLASH_BLOCK_BIT) 




/****************************************************************************
* 名称:DelayNS()
* 功能:长软件延时。
* 入口参数:dly		延时参数,值越大,延时越久
* 出口参数:无
****************************************************************************/
void  DelayNS(uint32  dly)
{  uint32  i;

   for(; dly > 0 ; dly--) 
      for(i = 0; i < 5000; i++);
}


uint16 getFlashInfo(flashInfo aFlashInfo)
{
	uint16 uTmpDataH   = 0;
	uint16 uTmpDataL   = 0;
	uint16 uTmpData    = 0;
	uint16 uIndex      = 0;
	uint32 uRetCode    = 0;
	uint32 uTmpMemSize = 0;
	
	switch (aFlashInfo)
	{
	case FLASH_INFO_BLOCK_NUM:
	case FLASH_INFO_SECTOR_NUM:
		enterCFISatus();
		uTmpDataL = readCFI(aFlashInfo);
		uTmpDataH = readCFI(aFlashInfo + 1);
		enterNormalSatus();
		uTmpData  = (((uTmpDataH & 0xFF) << 8) | (uTmpDataL & 0xFF));
		uRetCode  = uTmpData + 1;
		break;
		
	case FLASH_INFO_BLOCK_SIZE:
	case FLASH_INFO_SECTOR_SIZE:
		enterCFISatus();
		uTmpDataL = readCFI(aFlashInfo);
		uTmpDataH = readCFI(aFlashInfo + 1);
		enterNormalSatus();
		uTmpData  = (((uTmpDataH & 0xFF) << 8) | (uTmpDataL & 0xFF));
		uRetCode  = (uTmpData * 256)/2;          //字为单位
		break;
		
	case FLASH_INFO_MEMO_SIZE:
		enterCFISatus();
		uTmpData = readCFI(aFlashInfo);
		enterNormalSatus();
		if ((uTmpData > 32) || (uTmpData < 1)) {
			uRetCode = 0;
			break;
		}
		uTmpMemSize = 2;
		for (uIndex = 1; uIndex < uTmpData; uIndex++) {
			uTmpMemSize = uTmpMemSize * 2;
		}
		uRetCode = uTmpMemSize / (1024 * 1024);
		break;
	}
	return uRetCode;
}


void flashInitial(void)
{
	flashInfo mFlashInfo;
	mFlashInfo = FLASH_INFO_BLOCK_NUM;
	flashBlockNum = getFlashInfo(mFlashInfo);

	mFlashInfo = FLASH_INFO_SECTOR_NUM;
	flashSectorNum = getFlashInfo(mFlashInfo);

	mFlashInfo = FLASH_INFO_BLOCK_SIZE;
	flashBlockSize = getFlashInfo(mFlashInfo);

	mFlashInfo = FLASH_INFO_SECTOR_SIZE;
	flashSectorSize = getFlashInfo(mFlashInfo);

	//flashStaDataBack = (uint16 *)malloc(flashSectorSize * sizeof(uint16));
	//flashEndDataBack = (uint16 *)malloc(flashSectorSize * sizeof(uint16));
	flashStaDataBack = startDataBuff;
	flashEndDataBack = endDataBuff;
}


uint16 writeFlashWord(volatile uint16 *aAddr, uint16 Data) 
{  
	uint16  temp1 = 0;
	uint16  temp2 = 0;
	uint16  uRetCode = FLASH_OK;
	volatile uint16  *addr;

	addr = GetAddr(0x5555);		// 转换地址0x5555
	addr[0] = 0xaaaa;			// 第一个写周期,地址0x5555,数据0xAA

	addr = GetAddr(0x2aaa);
	addr[0] = 0x5555;			// 第二个写周期,地址0x2aaa,数据0x55

	addr = GetAddr(0x5555);
	addr[0] = 0xa0a0;			// 第三个写周期,地址0x5555,数据0xA0
    
	*aAddr = Data;				// 第四个写周期,地址aAddr,数据Data

	while (1) {					// 等待操作完成 (若编程操作没有完成,每次读操作DQ6会跳变)
		temp1 = *addr;			
		temp2 = *addr;
		if (temp1 == temp2) {
// 			if (temp1 != Data) {
// 				uRetCode = FLASH_NG;
// 			} 
			break;
		}
	}
   
	return uRetCode;
}


uint16 readFlashWord(uint16 aAddr) 
{
	volatile uint16 *tmpAddr;
	uint16 uTmpData = 0;

	tmpAddr = GetAddr(aAddr);
	uTmpData = *tmpAddr;
	return uTmpData;
}


volatile uint16 *tmpData;
volatile uint16 *sectorAddr;		//扇区起始地址
volatile uint16 *lastSectorAddr;
volatile uint16 *blockAddr;			//块起始地址
volatile uint16 *dataAddr;			//数据起始地址
volatile uint16 *endPoint;			//数据末尾地址
volatile uint16 *tmpAddr;			//临时地址
uint16 writeFlashBuff(uint16 aAddr, uint16 *aData, uint16 aLength) 
{
	uint16  uRetCode	   = FLASH_OK;  //返回值
	uint16  uIndex		   = 0;		  
	uint16  uTmpAddr	   = 0;			//要写入的数据地址
	uint16  uBakStaDataCnt = 0;			//记录扇区起始地址到写入地址的大小,即要备分数据的个数
	uint16  uBakEndDataCnt = 0;			//记录写入数据的结束地址到下一个扇区的大小,即要备分数据的个数

	tmpData		   = NULL;
	sectorAddr	   = NULL;
	lastSectorAddr = NULL;
	dataAddr	   = NULL;
	blockAddr	   = NULL;
	endPoint	   = NULL;
	tmpAddr		   = NULL;
	
	sectorAddr = getSectorAddr(aAddr);	
	blockAddr  = getBlockAddr(aAddr);
	dataAddr   = GetAddr(aAddr);
	endPoint   = sectorAddr + aLength;
	lastSectorAddr = getSectorAddr(aAddr + aLength) + flashSectorSize;


	//备份扇区起始数据
	if (sectorAddr < dataAddr) {                   
		tmpAddr = sectorAddr;
		tmpData = flashStaDataBack;
		while (tmpAddr < dataAddr) {
			*tmpData  = *tmpAddr;
			tmpData   = tmpData + 1;
			tmpAddr   = tmpAddr + 1;
			uBakStaDataCnt = uBakStaDataCnt + 1;
		}
	}

	//备份扇区末尾的数据
	tmpAddr = endPoint;
	tmpData = flashEndDataBack;
	while (tmpAddr < lastSectorAddr) {
		*tmpData = *tmpAddr;
		tmpData = tmpData + 1;
		tmpAddr = tmpAddr + 1;
		uBakEndDataCnt = uBakEndDataCnt + 1;
	}

	//删除扇区
	if ((dataAddr == sectorAddr) && (sectorAddr == blockAddr) && (aLength > flashBlockSize)) {
		eraseChip(ERASE_BLOCK, blockAddr, 1);
		sectorAddr = sectorAddr + flashBlockSize;
		blockAddr = blockAddr + flashBlockSize;
	} else {
		while ((sectorAddr < endPoint) && (sectorAddr < (blockAddr + flashBlockSize))) {
			eraseChip(ERASE_SECTOR, sectorAddr, 1);

⌨️ 快捷键说明

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