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

📄 flashpic_strata.c

📁 umon bootloader source code, support mips cpu.
💻 C
字号:
/* flashpic_strata.c:
 * This file contains the portion of the flash driver code that can be
 * relocated (pic =  position independent code) to RAM space so that it
 * is not executing out of the same flash device that it is operating on.
 *
 * This code is written for 2 Strata devices in 16-bit mode in parallel.
 * This forms one 32-bit wide flash bank.
 */
#include "config.h"
#if INCLUDE_FLASH
#include "genlib.h"
#include "stddefs.h"
#include "flashdev.h"
#include "flash.h"
#include "flash_strata.h"

#define USE_WRITE_BUFFER 1

/* When this is used in an environment where it is NOT relocated, 
 * then it is safe to turn on trace and call printf for debugging.
 * This can be changed to a #define initialized to zero to save
 * space if printf is not going to be used.
 */
int STRATA_TRACE;

/* Flasherase():
 * Based on the 'snum' value, erase the appropriate sector(s).
 * Write the "Erase Setup" and "Erase Confirm" commands...
 * Return 0 if success, else -1.
 */
int
FlasheraseStrata_32(struct flashinfo *fdev,int snum)
{
	ftype			stat;
	volatile ulong	add, *lp, *lp1;
	volatile int	ret, sector, outofrange;

	ret = 0;
	outofrange = 1;
	add = (ulong)(fdev->base);

	if (STRATA_TRACE)
		printf("erase(%d)\n",snum);


	/* Start operation off by clearing the status register. */
	Write_50_to_base();	

	/* Erase the request sector(s): */
	for (sector=0;sector<fdev->sectorcnt;sector++) {
		if ((snum == ALL_SECTORS) || (snum == sector)) {

			/* Skip sector if it is protected.
			 */
			if ((!FlashProtectWindow) &&
			    (fdev->sectors[sector].protected)) {
				add += fdev->sectors[sector].size;
				continue;
			}

			/* As long as we enter this block of code once, we know
			 * that the sector number requested was within the range
			 * of the specified bank.
			 */
			outofrange = 0;

			/* If the space within the sector is all FF, then it
			 * doesn't need to be erased, so don't...
			 */
			lp = (ulong *)fdev->sectors[sector].begin; 
			lp1 = (ulong *)((char *)lp + fdev->sectors[sector].size - 1); 
			while(lp <= lp1) {
				if (*lp++ != 0xffffffff) {		/* Erased? */
					Write_20_to_base();			/* setup */
					Write_d0_to_(add);			/* confirm */
					WAIT_FOR_WSMS_READY();		/* Wait for WSMS ready */
					stat = Read_0000();
					if (stat & ECLBS) {			/* Check for error */
						Write_50_to_base();		/* Clear status register */
						printf("Eerr 0x%lx\n",(ulong)stat);
						Write_ff_to_base();		/* Go to read-array mode */
						return(-1);
					}
					Write_ff_to_base();			/* Go to read-array mode */
					WAIT_FOR_FF(add);			/* Wait for read == 0xff */
					break;
				}
			}
			
			if (ret == -1)
				break;
		}
		add += fdev->sectors[sector].size;
	}
	if (outofrange)
		ret = -1;
	return(ret);
}

/* EndFlasherase():
 *	Function place holder to determine the "end" of the
 *	sectorerase() function.
 */
void
EndFlasheraseStrata_32()
{
}


/* Flashwrite():
 * This device has a 32-byte write buffer.  The only gotcha for this is 
 * that the destination address into the flash must be on a 32-byte boundary,
 * so we an only use the buffer when the destination address has the lower 5
 * bits clear.  To do this, we do however many "individual" writes are
 * necessary to get the destination address 32-byte aligned; then, if there
 * are at least 32 bytes left, we use the write-buffer mechanism for each
 * remaining block of 32 bytes.
 */
int
FlashwriteStrata_32(struct flashinfo *fdev,uchar *dest,uchar *src,long bytecnt)
{
	ftype			stat;
	volatile long	cnt, buf4[1];
	volatile int	i, tot, ret, delta;
	volatile uchar	*bp4;
#if USE_WRITE_BUFFER
	volatile uchar	*block, *bp64;
	volatile long	buf64[16];
#endif

	/* Start operation off by clearing the status register. */
	Write_50_to_base();	

	/* If the destination address is not properly aligned, then build a
	 * fake source buffer using bytes below dest.  Then call this function
	 * recursively to do that operation.
	 */
	if (Not32BitAligned(dest)) {
		uchar	*tmpdest;

		delta = (long)dest & 3;
		tmpdest = dest - delta;

		bp4 = (uchar *)buf4;
		for(i=0;delta>0;i++,delta--) {
			*bp4++ = *(dest-delta);
		}
		for(;i<4;i++) {
			*bp4++ = *src++;
			bytecnt--;
			dest++;
		}
		if (STRATA_TRACE)
			printf("pre-align:  0x%lx = %08lx\n",(ulong)tmpdest,buf4[0]);

		if (FlashwriteStrata_32(fdev,tmpdest,(uchar *)buf4,4) == -1)
			return(-1);
	}

	/* This device supports a write-buffer mode.  The buffer is 32 bytes
	 * (16 words) and greatly speeds up the programming process.  This
	 * This function starts up with the word-at-a-time mode and uses it
	 * until the destination address is mod32.  Then for each successive
	 * 32-byte block, the write buffer is used. When there is less than 32
	 * bytes left, the algorithm falls back to the one-word-at-a-time mode
	 * to finish up.
	 */
	ret = 0;
	cnt = bytecnt & ~3;

	for (tot=0;tot<cnt;tot+=4) {
#if USE_WRITE_BUFFER
		if (((ulong)dest & 0x3f) == 0)	/* Break out when 6 LSBs are zero */
			break;
#endif

		bp4 = (uchar *)buf4;
		*bp4++ = *src++;				/* Just in case src is not aligned... */
		*bp4++ = *src++;				
		*bp4++ = *src++;				
		*bp4++ = *src++;				

		if (STRATA_TRACE)
			printf("fwrite1:    0x%lx = %08lx\n",(ulong)dest,buf4[0]);

		Write_40_to_(dest);				/* Flash program setup command */
		Fwrite(dest,buf4);				/* Write the value */
		WAIT_FOR_WSMS_READY();			/* Wait for WSMS ready */
		stat = Read_0000();
		if (stat & PSLBS) {				/* Check for error */
			Write_50_to_base();			/* Clear status register */
			Write_ff_to_base();			/* Go to read-array mode */
			printf("Werr1 0x%lx\n",(ulong)stat);
			return(-1);
		}
		do {
			Write_ff_to_base();				/* Go to read-array mode */
		} WAIT_FOR_WRITE(dest,buf4);		
		dest += 4; 
	}

#if USE_WRITE_BUFFER
	/* If tot is less than cnt, then the upper loop reached a point where
	 * the destination address had the 5 LSBs low.  This means that we can
	 * use the write-buffer for all remaining 32-byte blocks...  Note that
	 * each 32-byte block is actually 64 because we have two devices in
	 * parallel.
	 */
	if ((cnt-tot) >= 64) {
		while((cnt-tot) >= 64) {
	
			Write_ff_to_base();			/* Go to read-array mode */

			bp64 = (uchar *)buf64;		/* Copy next buffer's worth of data */
			for(i=0;i<64;i++)			/* into local buffer just in case */
				*bp64++ = *src++;		/* the source is this flash device. */
			bp64 = (uchar *)buf64;
	
			do {
				Write_e8_to_(dest);	
			} while (WBUF_NOT_AVAIL(dest));

			block = dest;
			Write_0f_to_(dest);	
			for(i=0;i<16;i++) {
				bp4 = (uchar *)buf4;
				*bp4++ = *bp64++;		/* Just in case src is not aligned... */
				*bp4++ = *bp64++;				
				*bp4++ = *bp64++;				
				*bp4++ = *bp64++;				
				if (STRATA_TRACE)
					printf("fwrite2:    0x%lx = %08lx\n",(ulong)dest,buf4[0]);

				Fwrite(dest,buf4);		/* Write the value */
				dest += 4; 
			}
			Write_d0_to_(block);		/* Write-confirm command */
			tot += 64;
			Write_70_to_base();			/* Read Status Register */
			WAIT_FOR_WSMS_READY();		/* Wait for idle state machine */
		}
		stat = Read_0000();				/* Check for error */
		if (stat & PSLBS) {		
			Write_50_to_base();			/* Clear status register */
			Write_ff_to_base();			/* Go to read-array mode */
			printf("Werr2 0x%lx\n",stat);
			return(-1);
		}
		Write_ff_to_base();				/* Go to read-array mode */
	}
#endif

onemore:
	for (;tot<cnt;tot+=4) {
		bp4 = (uchar *)buf4;
		*bp4++ = *src++;				/* Just in case src is not aligned... */
		*bp4++ = *src++;
		*bp4++ = *src++;
		*bp4++ = *src++;

		if (STRATA_TRACE)
			printf("fwrite3:    0x%lx = %08lx\n", (ulong)dest,buf4[0]);

		Write_40_to_(dest);				/* Flash program setup command */
		Fwrite(dest,buf4);				/* Write the value */
		WAIT_FOR_WSMS_READY();			/* Wait for WSMS ready */
		stat = Read_0000();
		if (stat & PSLBS) {				/* Check for error */
			Write_50_to_base();			/* Clear status register */
			Write_ff_to_base();			/* Go to read-array mode */
			printf("Werr3 0x%lx\n",stat);
			return(-1);
		}
		do {
			Write_ff_to_base();				/* Go to read-array mode */
		} WAIT_FOR_WRITE(dest,buf4);		
		dest += 4; 
	}
	/* If cnt != bytecnt then bytecnt is not mod4, so one more write must be
	 * be done.  To do this, we must combine the source data with data that
	 * is already in the flash above the intended final address...
	 */
	if (cnt != bytecnt) {
		bp4 = (uchar *)buf4;
		for(delta=0;cnt != bytecnt;delta++,cnt++)
			*bp4++ = *src++;
		for(;delta != 4;delta++)
			*bp4++ = *(dest+delta);
		src = (uchar *)buf4;
		if (STRATA_TRACE)
			printf("post-align: 0x%lx = %08lx\n",(ulong)dest,buf4[0]);

		tot = cnt-1;
		goto onemore;
	}
	return(ret);
}

/* EndFlashwrite():
 * Function place holder to determine the "end" of the
 * Flashwrite() function.
 */
void
EndFlashwriteStrata_32()
{
}

/* Ewrite():
 * Erase all sectors that are part of the address space to be written,
 * then write the data to that address space.  This is basically a
 * concatenation of flasherase and flashwrite done in one step.  This is
 * necessary primarily for re-writing the bootcode; because after the boot
 * code is erased, there is nowhere to return so the re-write must be done
 * while executing out of ram also.
 */

int
FlashewriteStrata_32(struct flashinfo *fdev,ftype *dest,ftype *src,int bytecnt)
{
	return(-1);
}

/* EndFlashewrite():
 * Function place holder to determine the "end" of the
 * FlashEraseAndWrite() function.
 */
void
EndFlashewriteStrata_32()
{
}

/* FlashlockStrata_32():
 */
int
FlashlockStrata_32(struct flashinfo *fdev,int snum,int operation)
{
	ulong	add;
	int	sector;

	add = (ulong)(fdev->base);

	/* Lock the requested sector(s): */
	for (sector=0;sector<fdev->sectorcnt;sector++) {
		if ((snum == ALL_SECTORS) || (snum == sector)) {
			/* Issue the appropriate command sequence: */
			Write_60_to_base();	
			switch(operation) {
			case FLASH_UNLOCK:
				Write_d0_to_(add);
				break;
			case FLASH_LOCK:
				Write_01_to_(add);
				break;
			case FLASH_LOCKDWN:
				Write_2f_to_(add);
				break;
			}
		}
		add += fdev->sectors[sector].size;
	}
	Write_ff_to_base();		/* Go to read-array mode */
	return(0);
}

/* EndFlashlock():
 * Function place holder to determine the "end" of the
 * Flashlock() function.
 */
void
EndFlashlockStrata_32()
{
}

/* Flashtype():
 * Use the ReadConfiguration command (90H) to read manufacturer code (0000)
 * and device id code (0001).
 */

int
FlashtypeStrata_32(struct flashinfo *fdev)
{
	ushort	man, dev;
	ulong	id;

	/* Start operation off by clearing the status register. */
	Write_50_to_base();	

	/* Issue the read array command: */
	Write_ff_to_base();

	/* Issue the read configuration command: */
	Write_90_to_base();

	man = (ushort)Read_0000();	/* manufacturer ID */
	dev = (ushort)Read_0001();	/* device ID */
	if (STRATA_TRACE)
		printf("Strata man-id/dev-id: 0x%x 0x%x\n",man,dev);

	id = man;
	id <<= 16;
	id |= dev;

	fdev->id = id;

	/* Issue the read array command: */
	Write_ff_to_base();
	return((int)(fdev->id));
}

/* EndFlashtype():
 * Function place holder to determine the "end" of the
 * Flashtype() function.
 */
void
EndFlashtypeStrata_32()
{
}
#endif

⌨️ 快捷键说明

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