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

📄 flash.c

📁 VxWorks平台下的Intel的28F320C3 Flash的初始化、读写等源代码。
💻 C
字号:
/**********************************************************************
 chengjy@felab, copyright 2002-2004
 flash.c
 flash操作部分。提供FLASH的写入和读出,暂时不支持锁定.
 函数:
			void flashInit();
			char flashIDCheck();
			char flashDataSet(int dataNum,char *pBuff,int buffLen);
			char flashDataGet(int dataNum,char *pBuff,int buffLen);
			char flashDataErase(int dataNum, int eraseLen);
			char flashUnLock(int dataNum, int unLockLen);
			void flashShutDown();
 调用:			无
 被调用:	
 		netTask.c
 			STATUS t0x1600(char*pBuff);
 		BSP bootConfig.c
 			LOCAL char autoboot (int timeout);
 说明:	现有的配置模式是基于如下地址处理方式的:
        	对单片flash,地址增加1,可以获取到16bit数据,而这个
        	地址的提供必须是cpu地址+8,相当于cpu地址+8,用
       	 unsigned short型可以获取2byte数据。使用在board.h中定义的
        	FLASH2CPU_ADDR(flashAddr)宏来转换地址。
 **********************************************************************/
#include "vxworks.h"
#include "semLib.h"
#include "taskLib.h"
#include "logLib.h"
#include "stdio.h"
#include "string.h"

#include "board.h"

void flashInit();
char flashIDCheck();
char flashDataSet(int dataNum,char *pBuff,int buffLen);
char flashDataGet(int dataNum,char *pBuff,int buffLen);
char flashDataErase(int dataNum, int eraseLen);
char flashUnLock(int dataNum, int unLockLen);
void flashShutDown();

extern struct BoardWorkEnv	boardWorkEnv;

SEM_ID semFlash;	/*flash保护信号灯,在对flash操作前获取,操作结束释放*/

/**********************************************************************
 void flashInit()
 函数描述:	Flash初始化。使用boardWorkEnv.boardInit和BOARD_FLASH_INITED
 				控制重新初始化。首先检查flash的ID,然后创建信号灯。
 参数:		无
 返回:		无
 调用:	
 			char flashIDCheck()
 被调用:
 		netTask.c
 			STATUS t0x1600(char*pBuff);
 **********************************************************************/
void flashInit()
{
	if(!(boardWorkEnv.boardInit&BOARD_FLASH_INITED))	/*如果已经初始化了,不再重复进行*/
	{
		/*创建信号灯*/
		semFlash = semBCreate(SEM_Q_FIFO,SEM_EMPTY);
		if(semFlash == NULL)
		{
			logMsg("flashInit: unable to create semFlash\n",0,0,0,0,0,0);
			return;
		}

	 	/*检查芯片类型*/
	 	if(flashIDCheck()!=STATUS_NORMAL)
	 	{
	 		logMsg("flashInit: only 28F320C3 is acceptable\n",0,0,0,0,0,0);
	 		semDelete(semFlash);
			return;
	 	}
	 	
		/*设置为read array模式*/
		*FLASH2CPU_ADDR(0) = FLASH_CC_READ_ARRAY;

		/*释放flash控制权*/
		semGive(semFlash);
		
		boardWorkEnv.boardInit = boardWorkEnv.boardInit | BOARD_FLASH_INITED;
	}
}

/**********************************************************************
 char flashDataSet(int dataNum,char *pBuff,int buffLen);
 函数描述:	将从pBuff开始的buffLen长度的数据写入Flash 中dataNum
 				对应的地址。使用datatNum对应FLASH 的块号。如果
 				buffLen 不是4的整数倍, 则将最后的数据填在高位上。
 				在写之前必须保证对应的块已经经过了解锁和擦除。
 参数:		dataNum,	flash的块序号,取值范围从1~63
 			pBuff,	需要写到flash的数据的内存首地址
 			buffLen,	需要写到flash的数据的长度,单位byte
 返回:		如果成功写入返回STATUS_NORMAL,否则返回对应的出错标志。
 调用:		无
 被调用:
  		netTask.c
 			STATUS t0x1600(char*pBuff);
 **********************************************************************/
char flashDataSet(int dataNum,char *pBuff,int buffLen)
{
	char stateReturn=STATUS_NORMAL;
	int iBuff,iBuffEnd;
	
	FLASH_VALUE *addr;
	FLASH_VALUE value;


	/*获取flash控制权*/
 	if(semTake(semFlash,100)==ERROR)
	{
		printf("flashDataSet: unable to get semFlash\n");
		return(STATUS_ERROR);
	}

	/*计算是否过界,如果过界取到最后一个字节*/
	iBuffEnd = (FLASH_DATA_BLOCK_NUM-dataNum)*FLASH_DATA_BLOCK_SIZE_W*2;
	if(buffLen> iBuffEnd)
	{
		printf("flashDataSet: no enough place for write\n");
		stateReturn = STATUS_WARNING;
	}
	else
		iBuffEnd = buffLen;
 	 
	if(stateReturn == STATUS_NORMAL)
 	{
 		iBuffEnd = ((unsigned int)(buffLen/2))*2;	/*填充长度取整*/

		printf("flashDataSet: addr 0x        ");

		/*首次的地址和数据*/
		addr = FLASH2CPU_ADDR(dataNum*FLASH_DATA_BLOCK_SIZE_W);
		value = pBuff[0]*0x0100+pBuff[1];
		iBuff=0;
		while(iBuff<buffLen)
		{
			/*设置为program格式*/
			*addr = FLASH_CC_PROGRAM_SETUP;
			*addr = value;
				
			/*计算下一次的地址和数据*/
			iBuff=iBuff+2;
			value = pBuff[iBuff]*0x0100+pBuff[iBuff+1];
			addr = addr+4;

			if(((UINT)addr&0xFFFF)==0)
				printf("\b\b\b\b\b\b\b\b%8x",(UINT)addr);
				
			/*检查状态*/
			*addr = FLASH_CC_READ_STATUS;
			while(!((*addr)&FLASH_CC_SET_CHECK1))
			{
				*addr = FLASH_CC_READ_STATUS;
			}
			if(((*addr)&FLASH_CC_SET_CHECK2)!=0x0000)
			{
				printf("\nflashDataSet: error in set set addr %x value %x in time\n",(int)addr,value);
				stateReturn = STATUS_ERROR;	/*出错,停止配置,跳出*/
				break;
			}
		}

		printf("\n");
		if(stateReturn==STATUS_NORMAL)
			printf("flashDataSet: finished\n");
	}
 	else
 	{
 		printf("\nflashDataSet: no enough place for file,quit\n");
 		stateReturn = STATUS_ERROR;
 	}

	/*配置为array read*/
	*FLASH2CPU_ADDR(0) = FLASH_CC_READ_ARRAY;
	
 	/*释放FLASH控制权*/
	semGive(semFlash);
	return(stateReturn);
}

/**********************************************************************
 char flashDataGet(int dataNum,char *pBuff,int buffLen)
 函数描述:	从Flash中dataNum对应地址开始读取buffLen个字节到pBuff。
 参数:		dataNum,	flash的块序号,取值范围从1~63
 			pBuff,	从flash 读取到的数据存储的内存首地址
 			buffLen,	从flash 读取的数据的长度,单位byte
 返回:		如果成功读取返回STATUS_NORMAL,否则返回对应的出错标志。
 调用:		无
 被调用:
 		BSP bootConfig.c
 			LOCAL char autoboot (int timeout)
 **********************************************************************/
char flashDataGet(int dataNum,char *pBuff,int buffLen)
{
	char stateReturn=STATUS_NORMAL;
	int iBuff,iBuffEnd;
	FLASH_VALUE * addr;
	FLASH_VALUE value;

	/*获取flash控制权*/
 	if(semTake(semFlash,100)==ERROR)
	{
		printf("flashDataGet: unable to get semFlash\n");
		return(STATUS_ERROR);
	}

	/*计算是否过界,如果过界取到最后一个字节*/
	iBuffEnd = (FLASH_DATA_BLOCK_NUM-dataNum)*FLASH_DATA_BLOCK_SIZE_W*2;
	
	if(buffLen> iBuffEnd)
	{
		printf("flashDataGet: no enough place for read\n");
		stateReturn = STATUS_WARNING;
	}
	else
		iBuffEnd = buffLen;
	
	if(stateReturn!= STATUS_ERROR)
	{

		/*读数据*/
		for(iBuff=0;iBuff<iBuffEnd;iBuff=iBuff+2)
		{

			addr = FLASH2CPU_ADDR(dataNum*FLASH_DATA_BLOCK_SIZE_W+iBuff/2);

			/*设置为read array, 然后读数据*/
			*(addr) = FLASH_CC_READ_ARRAY;
			value = *addr;		/*因为是直接付值,读取时也直接读取,保证字序一致*/

			if(iBuffEnd-iBuff>=2)	/* 普通情况*/
			{
				pBuff[iBuff]	= (char)((value>>8) &0xFF);
				pBuff[iBuff+1]	= (char)(value&0xFF);
			}
			else	/*不是整块情况,取高位*/
			{
				pBuff[iBuff] 	= (char)((value>>8) &0xFF);
			}
		}
		/*设置为read array状态*/
		*FLASH2CPU_ADDR(0) = FLASH_CC_READ_ARRAY;
	}

	/*释放flash控制权*/
	semGive(semFlash);

	return (stateReturn);
}

/**********************************************************************
 char flashDataErase(int dataNum,int eraseLen)
 函数描述:	将从dataNum开始的地址擦除,如果eraseLen不是
				 块长度的整数倍,仍然将最后一块整体擦除。
 参数:		dataNum,		flash的块序号,取值范围从1~63
 			eraseLen,	需要擦除的总长度,和将要写flash的长度对应相等
 返回:		如果成功擦除返回STATUS_NORMAL,否则返回对应的出错标志。
 调用:		
 			char flashUnLock(int dataNum, int unLockLen)
 被调用:
    		netTask.c
 			STATUS t0x1600(char*pBuff);
  **********************************************************************/
char flashDataErase(int dataNum, int eraseLen)
{
	FLASH_VALUE *addr;
	FLASH_VALUE value;
	int iBlock,lenBlock,endBlock;
	int eraseTime = 0;
	char stateReturn = STATUS_NORMAL;
	int eraseDelay;

	/*因为解锁函数内部调用了semTake和semGive,
	 因此必须放在flashDataErase函数调用semTake前*/
	if(flashUnLock(dataNum,eraseLen)!=STATUS_NORMAL)
	{
		printf("unable to unlock block from %d for %d bytes\n",dataNum,eraseLen);
		return(STATUS_ERROR);
	}

	/*获取flash控制权*/
 	if(semTake(semFlash,100)==ERROR)
	{
		printf("flashDataErase: unable to get semFlash\n");
		return(STATUS_ERROR);
	}

	/*计算需要擦除的块数量*/
	lenBlock = (eraseLen-1)/(FLASH_DATA_BLOCK_SIZE_W*2)+1;

	endBlock = dataNum+lenBlock;
	if(endBlock>FLASH_DATA_BLOCK_NUM)	/*超过范围,擦除到最后一块为止*/
	{
		printf("flashDataErase: no more place for erase %d blocks\n",lenBlock);
		endBlock = FLASH_DATA_BLOCK_NUM;
		stateReturn = STATUS_WARNING;
	}

	printf("flashDataErase: block number 0x  ");

	/*逐块擦除*/
	for(iBlock=dataNum;iBlock<endBlock;iBlock++)
	{
		printf("\b\b%2x",iBlock);
		addr = FLASH2CPU_ADDR((FLASH_VALUE*)((UINT)iBlock*FLASH_DATA_BLOCK_SIZE_W));
		/*开始擦除*/
		*addr = FLASH_CC_ERASE_SETUP;
		*addr = FLASH_CC_ERASE_CONFIRM;

		eraseTime = 0;
		/*读取状态*/
		while(1)
		{
			/*不断检查是否擦除完毕*/
			*addr = FLASH_CC_READ_STATUS;
			value = *addr;
			if((value & FLASH_CC_ERASE_CHECK1) == FLASH_CC_ERASE_CHECK1)		/*擦除完毕*/
				break;
			else
			{
				eraseTime++;
				for(eraseDelay=0;eraseDelay<10000;eraseDelay++);
				if(eraseTime ==FLASH_ERASE_BLOCK_TIME)	/*操作超时*/
				{
					printf("\nflashDataErase: can't erase block %d in time\n",iBlock);
					stateReturn = STATUS_ERROR;
					break;
				}
			} 				
		}
		if(stateReturn==STATUS_NORMAL)
		{
		/*检查是否正确擦除*/
			if((value & FLASH_CC_ERASE_CHECK2) != 0x0000)			/*擦除出错*/
			{
				printf("\nflashDataErase: error in erase block %d, value =%x\n",iBlock,value);
				stateReturn = STATUS_ERROR;
			}
			/*正确擦除,回到read array状态*/
			*FLASH2CPU_ADDR(0) = FLASH_CC_READ_ARRAY;
		}
		else
		{
			break;
		}
	}
	printf("\n");
	printf("flashDataErase: erase finished\n");
	/*无论是否正确擦除,都回到read array状态*/
	*FLASH2CPU_ADDR(0) = FLASH_CC_READ_ARRAY;

	/*释放flash控制权*/
	semGive(semFlash);

	/*全部擦除完毕*/
	return(stateReturn);		
}


/**********************************************************************
 char flashUnLock(int dataNum, int unLockLen)
 函数描述:	将从dataNum开始的地址解锁,如果eraseLen不是
				 块长度的整数倍,仍然将最后一块解锁。
 参数:		dataNum,		flash的块序号,取值范围从1~63
 			unLockLen,	需要解锁的总长度,和将要写flash的长度对应相等
 返回:		如果成功解锁返回STATUS_NORMAL,否则返回对应的出错标志。
 调用:		无
 被调用:
 			char flashDataErase(int dataNum, int eraseLen)
 **********************************************************************/
char flashUnLock(int dataNum, int unLockLen)
{
	FLASH_VALUE *addr;
	int iBlock,lenBlock,endBlock;
	char stateReturn = STATUS_NORMAL;

	/*获取flash控制权*/
 	if(semTake(semFlash,100)==ERROR)
	{
		printf("flashUnLock: unable to get semFlash\n");
		return(STATUS_ERROR);
	}

	/*计算需要解锁的块数量*/
	lenBlock = (unLockLen-1)/(FLASH_DATA_BLOCK_SIZE_W*2)+1;
	endBlock = dataNum+lenBlock;
	if(endBlock>FLASH_DATA_BLOCK_NUM)	/*超过范围,解锁到最后一块为止*/
	{
		printf("flashUnLock: no more place for unlock %d blocks\n",lenBlock);
		endBlock = FLASH_DATA_BLOCK_NUM;
		stateReturn = STATUS_WARNING;
	}
	
	/*逐块解锁*/
	for(iBlock=dataNum;iBlock<endBlock;iBlock++)
	{
		addr = FLASH2CPU_ADDR((FLASH_VALUE*)((UINT)iBlock*FLASH_DATA_BLOCK_SIZE_W));
		/*开始解锁*/
		*addr = FLASH_CC_CONFIG_SETUP;
		*addr = FLASH_CC_CONFIG_CONFIRM;
		/*恢复到read array状态*/
		*addr = FLASH_CC_READ_ARRAY;
	}
	
	/*释放信号灯*/
	semGive(semFlash);
	return(stateReturn);
}

/**********************************************************************
 char flashIDCheck()
 函数描述:	检查flash 芯片类型
 参数:		无
 返回:		如果是软件要求的flash,返回STATUS_NORMAL,否则返回STATUS_ERROR
 调用:		无
 被调用:
 			void flashInit()
 **********************************************************************/
char flashIDCheck()
{
	FLASH_VALUE id1,id2;
	
	/*设置为read identify 模式*/
	*FLASH2CPU_ADDR(0) = FLASH_CC_READ_IDENTIFY;
	
 	/*读芯片代号*/
 	id1  = *FLASH2CPU_ADDR(0);
 	id2  = *FLASH2CPU_ADDR(1);

 	/*根据芯片是否是28F320B3做出返回值*/
 	if( (id1==FLASH_28F320C3_ID) && ((id2==FLASH_28F320C3_IDENT_T)||(id2==FLASH_28F320C3_IDENT_B)) )
	 	return(STATUS_NORMAL);
 	else
 		return(STATUS_ERROR);
}

/**********************************************************************
 void flashShutDown()
 函数描述:	关闭FLASH的操作,主要是解决一些在SHELL 下重复
                		使用flashInit()的信号灯没有删除的问题,在这里
                		删除信号灯,并将flash重新置到read array状态。
 参数:		无
 返回:		无
 调用:		无
 被调用:	
     		netTask.c
 			STATUS t0x1600(char*pBuff);
 **********************************************************************/
void flashShutDown()
{
	if(boardWorkEnv.boardInit&BOARD_FLASH_INITED)
	{
		/*恢复成read array 状态*/
		*FLASH2CPU_ADDR(0) = FLASH_CC_READ_ARRAY;
		/*删除flash信号灯*/
		semDelete(semFlash);
		boardWorkEnv.boardInit = boardWorkEnv.boardInit & (~(BOARD_FLASH_INITED));		
	}
}

⌨️ 快捷键说明

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