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

📄 according.c

📁 flash驱动程序
💻 C
字号:

#include "stdio.h"
#include "stdlib.h"

/*intel 28F128 driver*/

#define FLASH_CMD_RESET				0x00ff
#define FLASH_CMD_BLOCK_ERASE		0x0020
#define FLASH_CMD_ERASE_CONFIRM		0x00D0
#define FLASH_CMD_CLEAR_STATUS		0x0050
#define FLASH_CMD_SUSPEND_ERASE		0x00B0
#define FLASH_CMD_WRITE				0x0040
#define FLASH_CMD_PROTECT			0x0060
#define FLASH_CMD_PROTECT_SET		0x0001
#define FLASH_CMD_PROTECT_CLEAR		0x00D0
#define FLASH_STATUS_DONE			0x0080

/*--------------------------------------------------------------------*
* CPU 时钟周期:  400 Mhz 8270 -- 2.5ns -> 3ns
*---------------------------------------------------------------------*/
#define FS_FLASH_CPU_CLOCK 					(8)

#define fs_flash_disable_interrupts()	(0)
#define fs_flash_enable_interrupts()	

static void flashDelay( unsigned long Tns )
{
    unsigned long i;
    for (i=0; i<Tns/FS_FLASH_CPU_CLOCK; i++)
      ;
}

/* 1000 纳秒:  写FALSH 时延*/
#define FS_FLASH_DELAY_TIME 			20

/* program/erase operation inner algorithm be in progress or have been completed */
/* 最大轮询时间: 将近118 秒*/
#define FS_FLASH_POLL_TIME 			10000

#define FS_WRITE_OPT

/*1Mbits/sector*/
#define	FS_FLASH_SECTOR_SIZE  (128 * 1024)
/*128 sector*/
#define FS_FLASH_SECTOR_COUNT (128)
#define FS_FLASH_SIZE (FS_FLASH_SECTOR_SIZE * FS_FLASH_SECTOR_COUNT)
/*start address*/
#define FS_FLASH_START_ADDRESS (0xFE000000)
/**/
#define FS_FLASH_SECTOR_ADDRESS(sn) (FS_FLASH_START_ADDRESS + (sn) * FS_FLASH_SECTOR_SIZE)

/*对指定的段进行保护处理, 返回0成功*/
static int i28f128_sector_protect(long sector, int prot)
{
	volatile unsigned short *addr;
	unsigned long start;

	addr = (volatile unsigned short*)(FS_FLASH_SECTOR_ADDRESS(sector));
	addr[0] = FLASH_CMD_CLEAR_STATUS;
	addr[0] = FLASH_CMD_PROTECT;

	if(prot) 
	{
		addr[0] = FLASH_CMD_PROTECT_SET;
	} 
	else 
	{
		addr[0] = FLASH_CMD_PROTECT_CLEAR;
	}
	start = FS_FLASH_POLL_TIME;
    flashDelay(FS_FLASH_DELAY_TIME*10000);
	while(!(addr[0] & FLASH_STATUS_DONE))
	{
        flashDelay(FS_FLASH_DELAY_TIME*10000);

		if (start-- == 0) 
		{
			printf("Flash protect timeout at sector %d\n",  sector);
			addr[0] = FLASH_CMD_RESET;
			return (-1);
		}
	}
	addr[0] = FLASH_CMD_RESET;
	return (0);
}

/*擦除指定段*/
static int i28f128_sector_erase(int sector)
{
	int start, last, flag;
	unsigned long status;
	volatile unsigned short *addr;

	start = FS_FLASH_POLL_TIME*10000;
	last  = start;

	addr = (volatile unsigned short *)FS_FLASH_SECTOR_ADDRESS(sector);

	/* Disable interrupts which might cause a timeout here */
	flag = fs_flash_disable_interrupts();

	*addr = FLASH_CMD_CLEAR_STATUS;
	*addr = FLASH_CMD_BLOCK_ERASE;
	*addr = FLASH_CMD_ERASE_CONFIRM;

	/* re-enable interrupts if necessary */
	if (flag)
		fs_flash_enable_interrupts();

	/* wait at least 80us - let's wait 1 ms */
	taskDelay (1);
    flashDelay(FS_FLASH_DELAY_TIME*10000);

	while (((status = *addr) & FLASH_STATUS_DONE) != FLASH_STATUS_DONE) 
	{
		flashDelay(FS_FLASH_DELAY_TIME*10000);

        if (start-- == 0) 
		{
			printf("Flash erase timeout at sector %d\n", sector);
			*addr = FLASH_CMD_SUSPEND_ERASE;
			*addr = FLASH_CMD_RESET;
			return -1;
		}
	}
	*addr = FLASH_CMD_RESET;
	return 0;
}

/*
 * Write 16 bit (short) to flash
 */

static int i28f128_write_short (unsigned long dest, unsigned short data)
{
	volatile unsigned short *addr;
	unsigned long start;
	int flag;
	
	/* Check if Flash is (sufficiently) erased */
	if ((*((volatile unsigned short *)dest) & data) != data) {
		return (-2);
	}

	addr = (volatile unsigned short*)(FS_FLASH_SECTOR_ADDRESS(0));

	/* Disable interrupts which might cause a timeout here */
	flag = fs_flash_disable_interrupts();

	*addr = FLASH_CMD_ERASE_CONFIRM;
	*addr = FLASH_CMD_WRITE;

	*((volatile unsigned short *)dest) = data;

	/* re-enable interrupts if necessary */
	if (flag) 
	{
		fs_flash_enable_interrupts();
	}

	/* data polling for D7 */
	start = FS_FLASH_POLL_TIME;

	/* wait for error or finish */
	while(!(addr[0] & FLASH_STATUS_DONE))
	{
		flashDelay(FS_FLASH_DELAY_TIME);
		if (start-- == 0) 
		{
			addr[0] = FLASH_CMD_RESET;
			return (-1);
		}
	}
	*addr = FLASH_CMD_RESET;
	return (0);
}

/*
 * Copy memory to flash, returns:
 * 0 - OK
 * 1 - write timeout
 * 2 - Flash not erased
 * 4 - Flash not identified
 */

static int i28f128_sector_writedata(unsigned char *src, int sector)
{
	unsigned long addr;
	unsigned short data;
	int i, rc;
	addr = FS_FLASH_SECTOR_ADDRESS(sector);

	for (i = 0;i<FS_FLASH_SECTOR_SIZE;i += 2)
	{
		data = (unsigned short)src[i];
		data <<= 8;
		data |= (unsigned short)src[i+1];
		rc = i28f128_write_short(addr, data);
		if (rc != 0) 
		{
			return (rc);
		}
		addr += 2;
	}
	return 0;
}

static int i28f128_sector_write(int sectorno, unsigned char *pBuf)
{
	int ret;
#ifdef DEBUG_FLASH
	printf("  write sector %d\n", sectorno);
#endif
	ret = 0;
	/*取消段保护*/
	i28f128_sector_protect(sectorno, 0);

	/*擦除段*/
	if (i28f128_sector_erase(sectorno) != 0)
		ret = -1;
	else
	/*写数据*/
	if (i28f128_sector_writedata(pBuf, sectorno) != 0)
		ret = -2;
	
	/*恢复段保护*/
	i28f128_sector_protect(sectorno, 1);
	return ret;
}

static char * pflashTempBuffer = NULL;
static int currentsector = -1;

static int UpdateBuffer()
{
	if (currentsector < 0)
		return 0;
	if (pflashTempBuffer == NULL)
		return 0;
  i28f128_sector_write(currentsector, pflashTempBuffer);
  currentsector = -1;
  return 0;
}

static int UpdateSector(int newSector)
{
	if (newSector != currentsector)
		UpdateBuffer();
	else
		return 0;
	if (pflashTempBuffer == NULL)
		pflashTempBuffer = (char *)malloc(FS_FLASH_SECTOR_SIZE);
	if (pflashTempBuffer == NULL)
		return -1;
	memcpy(pflashTempBuffer, FS_FLASH_SECTOR_ADDRESS(newSector), FS_FLASH_SECTOR_SIZE);
	currentsector = newSector;
	return 0;
}

static int i28f128_read(unsigned char * dst, unsigned char * src, unsigned long count)
{
	UpdateBuffer();
	memcpy(dst, src, count);
}

/*
	将src开始的count个字节写到dst开始的flash地址中去
	返回值:
	0 : 成功
	-1: 参数错误
	-2:内存错误
*/
static int i28f128_write(unsigned char *src, unsigned char *dst, unsigned long count)
{
	unsigned long sectno;

	if (count == 0)
		return 0;

	if (((unsigned long)dst) < FS_FLASH_SECTOR_ADDRESS(0) )
		return -1;
	if (((unsigned long)dst) + count > FS_FLASH_SECTOR_ADDRESS(FS_FLASH_SECTOR_COUNT) )
		return -1;

#ifdef DEBUG_FLASH
	printf("write %08X --> %08X, count=%d\n", (unsigned long)src, (unsigned long)dst, count);
#endif
	
	sectno = (((unsigned long)dst) - FS_FLASH_START_ADDRESS) / FS_FLASH_SECTOR_SIZE;

	/*第一块,需要特别处理吗*/
	if ( (((unsigned long)dst) != FS_FLASH_SECTOR_ADDRESS(sectno) ) ||
		 ( (((unsigned long)dst) + count) < FS_FLASH_SECTOR_ADDRESS(sectno + 1) ) 
	   )
	{
		/*
		              dst              dst+count
		     |________:________________:____________________|
			 sectno                                        sectno+1
		*/
		unsigned long firstsegbytes;
		char * pBuf;
		int rc;
		firstsegbytes = FS_FLASH_SECTOR_SIZE - (((unsigned long)dst) - FS_FLASH_SECTOR_ADDRESS(sectno));
		if (firstsegbytes > count)
			firstsegbytes = count;
#ifndef FS_WRITE_OPT 
		/*需要进行读改写操作*/
		pBuf = (char *)malloc(FS_FLASH_SECTOR_SIZE);
		if (pBuf == NULL)
			return -2;
		/*读*/
		memcpy(pBuf, (char *)FS_FLASH_SECTOR_ADDRESS(sectno), FS_FLASH_SECTOR_SIZE);
		/*改*/
		memcpy(pBuf + (((unsigned long)dst) - FS_FLASH_SECTOR_ADDRESS(sectno)), src, firstsegbytes);
		/*写*/
		rc = i28f128_sector_write(sectno, pBuf);
		free(pBuf);
#else
		if ((rc = UpdateSector(sectno)) != 0)
			return -1;
		memcpy(pflashTempBuffer + (((unsigned long)dst) - FS_FLASH_SECTOR_ADDRESS(sectno)), src, firstsegbytes);
#endif		
		if (rc != 0)
			return rc;
		sectno++;
		count -= firstsegbytes;
		src += firstsegbytes;
	}
	/*中间段*/
	while (count >= FS_FLASH_SECTOR_SIZE)
	{
		int rc;
#ifndef FS_WRITE_OPT 
		rc = i28f128_sector_write(sectno, src);		
#else
		rc = UpdateSector(sectno);
		if (rc == 0)
		{
			memcpy(pflashTempBuffer, src, FS_FLASH_SECTOR_SIZE);
	  }
#endif		
		if (rc != 0)
			return rc;
		src += FS_FLASH_SECTOR_SIZE;
		sectno ++;
		count -= FS_FLASH_SECTOR_SIZE;
	}
	/*最后一段*/
	if (count > 0)
	{
		char * pBuf;
		int rc;
#ifndef FS_WRITE_OPT 
		/*需要进行读改写操作*/
		pBuf = (char *)malloc(FS_FLASH_SECTOR_SIZE);
		if (pBuf == NULL)
			return -2;
		/*读*/
		memcpy(pBuf, (char *)FS_FLASH_SECTOR_ADDRESS(sectno), FS_FLASH_SECTOR_SIZE);
		/*改*/
		memcpy(pBuf, src, count);
		/*写*/
		rc = i28f128_sector_write(sectno, pBuf);

		free(pBuf);
#else
		if ((rc = UpdateSector(sectno)) != 0)
			return -1;
		memcpy(pflashTempBuffer, src, count);
#endif		

		if (rc != 0)
			return rc;

	}
	return 0;
}

⌨️ 快捷键说明

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