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

📄 flash.c

📁 可移到ucos上的文件系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* flashcom.c:
 *	This file contains the portions of the flash code that are device
 *	independent.  Refer to the appropriate device sub-directory for the
 *	code that is specific to the flash device on the target.
 *
 *	General notice:
 *	This code is part of a boot-monitor package developed as a generic base
 *	platform for embedded system designs.  As such, it is likely to be
 *	distributed to various projects beyond the control of the original
 *	author.  Please notify the author of any enhancements made or bugs found
 *	so that all may benefit from the changes.  In addition, notification back
 *	to the author will allow the new user to pick up changes that may have
 *	been made by other users after this version of the code was distributed.
 *
 *	Author:	Ed Sutter
 *	email:	esutter@lucent.com		(home: lesutter@worldnet.att.net)
 *	phone:	908-582-2351			(home: 908-889-5161)
 */
#include "config.h"

#if INCLUDE_FLASH
#include "cpu.h"
#include "flashdev.h"
#include "flash.h"
#include "genlib.h"
#include "ctype.h"

#define printf mprintf	//m

typedef unsigned char uchar;
typedef unsigned long ulong;

extern struct flashdesc FlashNamId[];

int		FlashCurrentBank;
int		sectortoaddr(int,int *,uchar **);

extern	int FlashInit(void);

#define	SRANGE_ERROR	-1
#define	SRANGE_SINGLE	1
#define	SRANGE_RANGE	2
#define	SRANGE_ALL		3
	
/* FlashProtectWindow:
 *	Must be set to allow any flash operation to be done on space assumed
 *	to be software protected.
 */
int FlashProtectWindow;

/* FlashBank[]:
 *	This table contains all of the information that is needed to keep the
 *	flash code somewhat generic across multiple flash devices.
 */
extern struct	flashinfo FlashBank[FLASHBANKS];

#ifdef DISABLE_INTERRUPTS_DURING_FLASHOPS
#define FLASH_INTSOFF()				intsoff()
#define FLASH_INTSRESTORE(ival)		intsrestore(ival)
#else
#define FLASH_INTSOFF()				0
#define FLASH_INTSRESTORE(ival)
#endif

/* showflashtype():
 *	Find a match between the incoming id and an entry in the FlashNamId[]
 *	table.  The FlashNamId[] table is part of the device-specific code.
 */
int
showflashtype(ulong id)
{
	struct flashdesc *fdp;

	fdp = FlashNamId;
	while(fdp->desc) {
		if (id == fdp->id) {
			printf("Device = %s\n",fdp->desc);
			return(0);
		}
		fdp++;
	}
	printf("Flash id 0x%lx not recognized\n",id);
	return(-1);
}

int
showflashinfo(struct flashinfo *fdev)
{
	int	i;

	if (showflashtype(fdev->id) < 0)
		return(-1);

	printf("  Base addr   : 0x%08lx\n",(ulong)(fdev->base));
	printf("  Sectors     : %d\n",fdev->sectorcnt);
	printf("  Bank width  : %d\n",fdev->width);
	printf("  Sector     Begin       End        Size     SW-Protected?\n");
	for(i=0;i<fdev->sectorcnt;i++) {
		printf("    %2d    0x%08lx  0x%08lx  0x%06lx      %s\n",
		    fdev->sectors[i].snum,
			(ulong)(fdev->sectors[i].begin),
			(ulong)(fdev->sectors[i].end),
		    fdev->sectors[i].size,
		    fdev->sectors[i].protected ? "yes" : " no");
	}
	return(0);
}

/* flashopload():
 *	Copy flash operation to ram space.  
 *	Note that this function assumes that cache is disabled at this point.
 *	This is important because we are copying text into bss space and if
 *	cache was on, there could be a coherency problem.
 */
int
flashopload(ulong *begin,ulong *end,ulong *copy,int size)
{
	volatile ulong	*bp;
	int	ret;

	/* Verify space availability: */
	if (((int)end - (int)begin) >= size) {
		printf("flashopload overflow ((0x%lx-0x%lx) > 0x%x)\n",
			(ulong)end,(ulong)begin,size);
		return(-1);
	}

	ret = 0;
	/* Copy function() to RAM, then verify: */
	bp = begin;
	while(bp <= end) {
		*copy = *bp;
		if (*copy++ != *bp++) {
			printf("flashopload failed\n");
			ret = -1;
			break;
		}
	}

	return(ret);
}

/* flashtype():
 *	Use the device-specific function pointer to call the routine
 *	relocated to RAM space.
 */
int
flashtype(fdev)
struct flashinfo *fdev;
{
	return(fdev->fltype(fdev));
}

/* flasherase():
 *	Use the device-specific function pointer to call the routine
 *	relocated to RAM space.
 *	Note that flasherase() is called with a sector number.  The sector
 *	number is relative to the entire system, not just the particular device.
 *	This means that if there is more than one flash device in the system that
 *	the actual sector number (relative to the device) may not be the same
 *	value.  This adjustment is made here so that the underlying code that is
 *	pumped into ram for execution does not have to be aware of this.
 */
int
flasherase(fdev,snum)
struct	flashinfo *fdev;
int	snum;
{
	int	size;
	unsigned char *base, *end;

	if (fdev->id == FLASHRAM) {
		if (snum == ALL_SECTORS) {
			size = fdev->end - fdev->base;
			base = fdev->base;
		}
		else {
			sectortoaddr(snum,&size,&base);
		}
		end = base+size;
		while(base < end) {
			*base = 0xff;
			if (*base++ != 0xff)
				return(-1);
		}
		return(0);
	}

	if ((snum != ALL_SECTORS) && (fdev->sectors[0].snum != 0)) {
/*		printf("Adjusting snum from %d to",snum); */
		snum -= fdev->sectors[0].snum;
/*		printf(" %d.\n",snum); */
	}
	return(fdev->flerase(fdev,snum));
}

/* flashwrite():
 *	Use the device-specific function pointer to call the routine
 *	relocated to RAM space.
 *	First make a few checks on the request, then write to flash if all
 *	checks succeed.
 */
int
flashwrite(struct flashinfo *fdev,uchar *dest,uchar *src,long bytecnt)
{
	int	j, lowsector, highsector;
	register uchar	*dp, *sp, *edp;

	if (fdev->id == FLASHRAM) {
		uchar *sp, *dp, *end;
		sp = src;
		dp = dest;
		end = dp+bytecnt;
		while(dp < end) {
			*dp = *sp;
			if (*dp != *sp)
				return(-1);
			dp++; sp++;
		}
		return(0);
	}

	dp = dest;
	sp = src;
	edp = (dest + bytecnt) - 1;

	/* If outside the devices space, return failed.. */
	if ((edp < fdev->sectors[0].begin) ||
	    (dp > fdev->sectors[fdev->sectorcnt-1].end)) {
		printf("flashwrite() failed: dest out of flash range\n");
		return(-1);
	}

	/* Make sure the destination is not within a protected sector */
	if (FlashProtectWindow == FLASH_PROTECT_WINDOW_CLOSED) {

		/* First determine the sectors that overlap with the
		 * flash space to be written...
		 */

		lowsector = highsector = -1;
		for(j=0;j<fdev->sectorcnt;j++) {
			if ((dp >= fdev->sectors[j].begin) &&
			    (dp <= fdev->sectors[j].end))
				lowsector = j;
		}
		for(j=0;j<fdev->sectorcnt;j++) {
			if ((edp >= fdev->sectors[j].begin) &&
			    (edp <= fdev->sectors[j].end))
				highsector = j;
		}
		if ((lowsector == -1) || (highsector == -1)) {
			printf("flashwrite() failed: can't find sector\n");
			return(-1);
		}

		/* Now that the range of affected sectors is known,
		 * verify that those sectors are not protected...
		 */
		for(j=lowsector;j<=highsector;j++) {
			if (fdev->sectors[j].protected) {
				printf("flashwrite() failed: sector protected\n");
				return(-1);
			}
		}
	}

	/* Now make sure that there is no attempt to transition a bit
	 * in the affected range from 0 to 1...  A flash write can only
	 * bring bits low (erase brings them  high).
	 */
	while(dp < edp) {
		if ((*dp & *sp) != *sp) {
			printf("flashwrite() failed: bit 0->1 rqst denied.\n");
			return(-1);
		}
		dp++; 
		sp++;
	}
	return(fdev->flwrite(fdev,dest,src,bytecnt));
}

/* flashewrite():
 *	Use the device-specific function pointer to call the routine
 *	relocated to RAM space.
 */
int
flashewrite(struct flashinfo *fdev,uchar *dest,uchar *src,long bytecnt)
{
	int	i;

	/* Source and destination addresses must be long-aligned. */
	if (((int)src & 3) || ((int)dest & 3))
		return(-1);

	/* If the protection window is closed, then verify that no protected
	 * sectors will be written over...
	 */
	if (FlashProtectWindow == FLASH_PROTECT_WINDOW_CLOSED) {
		for (i=0;i<fdev->sectorcnt;i++) {
			if((((uchar *)dest) > (fdev->sectors[i].end)) ||
			    (((uchar *)dest+bytecnt) < (fdev->sectors[i].begin)))
				continue;
			else
				if (fdev->sectors[i].protected)
					return(-1);
		}
	}
	return(fdev->flewrite(fdev,dest,src,bytecnt));
}

/* addrtosector():
 *	Incoming address is translated to sector number, size of sector
 *	and base of sector.
 *	Return 0 if successful; else -1.
 */
int
addrtosector(uchar *addr,int *sector,int *size,uchar **base)
{
	struct flashinfo *fbnk;
	struct	sectorinfo *sinfo;
	int		dev, sec, i;

	sec = 0;
	for(dev=0;dev<FLASHBANKS;dev++) {
		fbnk = &FlashBank[dev];
		for(i=0;i<fbnk->sectorcnt;i++,sec++) {
			sinfo = &fbnk->sectors[i];
			if ((addr >= sinfo->begin) && (addr <= sinfo->end)) {
				if (sector) {
					*sector = sec;
				}
				if (base) {
					*base = sinfo->begin;
				}
				if (size) {
					*size = sinfo->size;
				}
				return(0);
			}
		}
	}
	printf("addrtosector(0x%lx) failed\n",(ulong)addr);
	return(-1);
}

/* addrtobank():
 *	From the incoming address, return a pointer to the flash bank that
 *	this address is within.
 */
struct flashinfo *
addrtobank(uchar *addr)
{
	struct flashinfo *fbnk;
	int		dev;

	for(dev=0;dev<FLASHBANKS;dev++) {
		fbnk = &FlashBank[dev];
		if ((addr >= fbnk->base) && (addr <= fbnk->end))
			return(fbnk);
	}
	printf("addrtobank(0x%lx) failed\n",(ulong)addr);
	return(0);
}

int
sectortoaddr(int sector,int *size,uchar **base)
{
	struct flashinfo *fbnk;
	struct	sectorinfo *sinfo;
	int		dev, sec, i;

	sec = 0;
	for(dev=0;dev<FLASHBANKS;dev++) {
		fbnk = &FlashBank[dev];
		for(i=0;i<fbnk->sectorcnt;i++,sec++) {
			if (sec == sector) {
				sinfo = &fbnk->sectors[i];
				if (base) *base = sinfo->begin;
				if (size) *size = sinfo->size;
				return(0);
			}
		}
	}
	printf("sectortoaddr(%d) failed\n",sector);
	return(-1);
}

/* flashbankinfo():
 *	Based on the incoming bank number, return the beginning, end and
 *	number of sectors within that bank.
 */
int
flashbankinfo(int bank,uchar **begin,uchar **end,int *sectorcnt)
{
	struct flashinfo *fbnk;

	if (bank >= FLASHBANKS)
		return(-1);

	fbnk = &FlashBank[bank];
	if (begin)
		*begin = fbnk->base;
	if (end)
		*end = fbnk->end;
	if (sectorcnt)
		*sectorcnt = fbnk->sectorcnt;
	return(0);
}

/* lastlargesector():
 *	Incoming bank number is used to populate the sector information
 *	(sector number, sector size and address) of the last large sector
 *	in the specified bank.
 *	Return 0 if successful; else -1.
 */
int
lastlargesector(int bank,int *sector,int *size,uchar **base)
{
	struct flashinfo	*fbnk;
	struct sectorinfo	*sinfo;
	uchar				*largest_sbase;
	int					i, largest_ssize, largest_snum;

⌨️ 快捷键说明

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