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

📄 amd29lv004.c

📁 motorola自己开发的针对coldfire 5272的Dbug bootloader程序
💻 C
字号:
/*****************************************************************************
*										
*  File:		amd29lv004.c
*  Date:		19 December 1997
*  Purpose:	Device driver for the AMD 29LV004 Flash.
*
*  Notes:	This driver supports a single width of the 512K x 8 AMD29LV004
*			FLASH: 8-bit, 16-bit, or 32-bit.  The width support is declared
*			during compilation, and is implemented with either 1, 2, or 4
*			AMD29LV004s, respectively.
*****************************************************************************/

/*****************************************************************************
*
*  IMPORTANT:  It is not possible to execute any of these routines if the code 
*  for these routines is in the FLASH itself.  This is because these routines
*  change the mode of the device so that reads from it are not always possible.
*  The code mustbe executed out of RAM.
*****************************************************************************/

/*****************************************************************************
*
*  WARNING:  The two routines/symbols amd29lv004_start and amd29lv004_end are 
*  used to determine the start and end of the FLASH PIC driver in ROM/FLASH so
*  that it can becopied out to DRAM and then executed.  In other words, any 
*  modifications/additions must be between these two functions!
*
*****************************************************************************/

#include "src/include/dbug.h"
#include "src/dev/flash/amd29lv004.h"

/*****************************************************************************/
void
amd29lv004_start (void) {}
/*****************************************************************************/
void
amd29lv004_read (AMD29LV004 *amd29lv004)
{
	/************************************************************************/
	/*  This routine places the FLASH in the read/reset mode.				*/
	/************************************************************************/

	amd29lv004->device.cmdreg1 = AMD29LV004_READ_CMD;
}
/*****************************************************************************/
int
amd29lv004_sector_erase (AMD29LV004 *amd29lv004, AMD29LV004_SECTOR sector)
{
	/************************************************************************/
	/*  This routine erases one sector in the Flash.						*/
	/************************************************************************/

	/*  Setup pointer to the sector to be erased  */
	AMD29LV004_CELL	*s;
	s = (AMD29LV004_CELL *)&(amd29lv004->sector[sector]);

	/*  Perform the Sector Erase command sequence  */
	amd29lv004->device.cmdreg1 = AMD29LV004_UNLOCK_CMD1;
	amd29lv004->device.cmdreg2 = AMD29LV004_UNLOCK_CMD2;
	amd29lv004->device.cmdreg1 = AMD29LV004_ERASE_CMD;
	amd29lv004->device.cmdreg1 = AMD29LV004_UNLOCK_CMD1;
	amd29lv004->device.cmdreg2 = AMD29LV004_UNLOCK_CMD2;
	*s = AMD29LV004_SECTORERASE_CMD;

	/*  Wait for the device to finish erasing the chip  */
	while (1)
	{
		/*  Flash has been erased  */
		if ((*s & AMD29LV004_ERASE_DONE) == AMD29LV004_ERASE_DONE)
		{
			return 1;
		}
	}
}
/*****************************************************************************/

int
amd29lv004_chip_erase (AMD29LV004 *amd29lv004)
{
	/************************************************************************/
	/*  This function will erase all of the sectors in the Flash.			*/
	/************************************************************************/

	/*  Setup pointer to any sector to read status information  */
	AMD29LV004_CELL *s;
	s = (AMD29LV004_CELL *)&(amd29lv004->sector[AMD29LV004_SECTOR_0]);

	/*  Perform the Chip Erase command sequence  */
	amd29lv004->device.cmdreg1 = AMD29LV004_UNLOCK_CMD1;
	amd29lv004->device.cmdreg2 = AMD29LV004_UNLOCK_CMD2;
	amd29lv004->device.cmdreg1 = AMD29LV004_ERASE_CMD;
	amd29lv004->device.cmdreg1 = AMD29LV004_UNLOCK_CMD1;
	amd29lv004->device.cmdreg2 = AMD29LV004_UNLOCK_CMD2;
	amd29lv004->device.cmdreg1 = AMD29LV004_CHIPERASE_CMD;

	/*  Wait for the device to finish erasing the chip  */
	while (1)
	{
		int timeouts;
		timeouts = 0;

		/*  Flash has been erased  */
		if ((*s & AMD29LV004_ERASE_DONE) == AMD29LV004_ERASE_DONE)
		{
			return 1;
		}

		/*  Error has been noticed by the chip  */
		if (*s & AMD29LV004_TIME_EXCEEDED)
		{
			amd29lv004_read (amd29lv004);
			return -1;
		}

		/*  Timeout has been called by the program  */
		if (++timeouts > 1024)
		{
			amd29lv004_read (amd29lv004);
			return -2;
		}
	}
}
/*****************************************************************************/
int
amd29lv004_id (AMD29LV004 *amd29lv004)
{
	/************************************************************************/
	/*  This routine extracts from the FLASH the manufacturer and device	*/
	/*  code.  If the codes match those for the AMD29LV004, then 1 is		*/
	/*  returned, else 0.													*/
	/************************************************************************/

	unsigned int manuf, device;

	/*  Perform the Autoselect command sequence.  */
	amd29lv004->device.cmdreg1 = AMD29LV004_UNLOCK_CMD1;
	amd29lv004->device.cmdreg2 = AMD29LV004_UNLOCK_CMD2;
	amd29lv004->device.cmdreg1 = AMD29LV004_AUTOSELECT_CMD;

	/*  Read the manufacturer and device id codes.  */
	manuf = amd29lv004->device.manuf;
	device = amd29lv004->device.id;

	/*  Place the device back in the Read/Reset mode.  */
	amd29lv004_read (amd29lv004);

	/*  Determine if an AMD29LV004 or not.  */
	if ((manuf == AMD29LV004_AMD_CODE) & (device == AMD29LV004_DEVICE_CODE))
		return 1;
	else
		return -1;
}
/*****************************************************************************/
int
amd29lv004_write (AMD29LV004 *amd29lv004,
	void *data, unsigned length, AMD29LV004_SECTOR sector, 
	void (*func)(void),int updbug)
{
	/************************************************************************/
	/* This routine programs the device beginning at 'sector' with			*/
	/* 'data' for 'length' bytes.  This routine is capable of				*/
	/* programming multiple consecutive sectors.							*/
	/************************************************************************/

	int written = 0, done = 0, hash1 = 0, hash2 = 0;
	int i, sector_size, timeouts;
	AMD29LV004_CELL *source, *target, rdata;

	/*  Step 1)  ID the flash as a AMD29LV004.  */
	if (!amd29lv004_id(amd29lv004))
		return -1;

	/*  Step 2)  Point to the beginning sector.  */
	target = (AMD29LV004_CELL *)&(amd29lv004->sector[sector]);
	source = (AMD29LV004_CELL *)data;

	/*  Loop if writing across different sectors.  */
	while (!done)
	{
		/* Step 3) Determine the size of the sector and divide by (8 * 1024) */
		/* This will depend on the type of Flash */
		switch(sector)
		{
			case AMD29LV004_SECTOR_0:	sector_size = (8); break;
			case AMD29LV004_SECTOR_1:	sector_size = (8); break;
			case AMD29LV004_SECTOR_2:	sector_size = (8); break;
			case AMD29LV004_SECTOR_3:	sector_size = (8); break;
			case AMD29LV004_SECTOR_4:	sector_size = (8); break;
			case AMD29LV004_SECTOR_5:	sector_size = (8); break;
			case AMD29LV004_SECTOR_6:	sector_size = (8); break;
			case AMD29LV004_SECTOR_7:	sector_size = (4); break;
			case AMD29LV004_SECTOR_8:	sector_size = (1); break;
			case AMD29LV004_SECTOR_9:	sector_size = (1); break;
			case AMD29LV004_SECTOR_10:	sector_size = (2); break;
			default:					sector_size = (8); break;
		}

		/*  Step 4)  Erase the sector.  */
		if (!amd29lv004_sector_erase (amd29lv004, sector))
			return -2;

		/* Step 5) Program the FLASH with the sector(s) contained in RAM. */
		for (i = 0; (i < (sector_size * 8 * 1024)) && (written < length); ++i)
		{
			if (!updbug)
			{
				/* Hash marks to indicate progress */
                if (hash1 == 2000)
                {
					printf(".");
					hash1 = -1;
					if (hash2++ == 52)		/* 52 characters */
					{
						printf("\n");
						hash2 = 0;
					}
                }
				hash1++;	
			}

			/* Perform the Byte Program command sequence */
			amd29lv004->device.cmdreg1 = AMD29LV004_UNLOCK_CMD1;
			amd29lv004->device.cmdreg2 = AMD29LV004_UNLOCK_CMD2;
			amd29lv004->device.cmdreg1 = AMD29LV004_BYTEPROG_CMD;
			*target = *source;

			/*  Poll to make sure it is done before continuing...  */
			timeouts = 0;
			while (1)
			{
				/*  Read the data from the Flash.  */
				rdata = *(volatile AMD29LV004_CELL *)target;

				/*
				 * If the Polling bit of the Flash is the same as the polling
				 * bit of the last data written, then the write is complete.
				 */

				/* PASS */
				if ((rdata & AMD29LV004_DATA_POLL_MASK) == 
					(*source & AMD29LV004_DATA_POLL_MASK))
					break;

				/*  
				 * If the status bits have not changed for too long, timeout.
				 */
				if (++timeouts > 1024)
				{
					amd29lv004_read (amd29lv004);
					break;
				}
			}

			/*  Verify write and increment bytes written counter.  */
			amd29lv004_read (amd29lv004);
			if (*target == *source)
			{
				written += sizeof(AMD29LV004_CELL);
				++target; ++source;
			}
			else
			{
				done = 1;
				break;
			}
		}

		/*
		 * Point to the next sector.  If there are bytes left to write, and	
		 * the current sector was not the last, then continue in the next 
		 * sector.
		 */
		sector += (sector_size);
		if ((sector > AMD29LV004_BLOCKS) || (written >= length))
			done = 1;
	}

	/*  Step 6)  Place the device back in the read mode.  */
	amd29lv004_read (amd29lv004);

	/*  Step 7)  Run any function passed in by the caller before returning.
	 * In the case that updbug is the caller, the address of the new ROM
	 * Monitor's entrance point is passed in and execution of the new Monitor
	 * begins
	 */
	if ((func != NULL))
		func();

	return written;
}
/*****************************************************************************/
void
amd29lv004_end(void)
{ }
/*****************************************************************************/

⌨️ 快捷键说明

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