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

📄 amd29f010.c

📁 motorola自己开发的针对coldfire 5272的Dbug bootloader程序
💻 C
字号:
/*
 * File:		amd29f010.c
 * Purpose:		Device driver for the AMD 29F010 Flash.
 *
 * Notes:		This driver supports a single type (AMD29F010) and
 *				width of FLASH.  The width support is done during
 *				compilation.  It can support multiple banks of
 *				same-width ADM29F010 FLASH.
 *
 *				If different types and width of FLASH are required,
 *				see driver amd29f0x0.c.
 *
 * Author:		Eric DeVolder
 * Date:		7-8-96
 *
 * Modifications:
 *
 */

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

/*
 * The AMD29F010 FLASH devices.  These devices are 128K x 8 devices.
 *
 * Note:  This driver supports one of the following configurations
 * for these devices.  Possible configurations are:
 *
 *      1 AMD29F010  as a single  8-bit memory device
 *      2 AMD29F010s as a single 16-bit memory device
 *      4 AMD29F010s as a single 32-bit memory device
 *
 * One of the following C pre-processor define statements must
 * exist prior to compilation:
 *
 * #define FLASH_8BIT_WIDE
 * #define FLASH_16BIT_WIDE
 * #define FLASH_32BIT_WIDE
 *
 * 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 must be executed out of
 * DRAM.
 */

/*
 * WARNING:  To eliminate playing alot of games with the linker
 * to properly treat this PIC driver, the two routines/symbols
 * amd29f010_start and amd29f010_end are used to determine the 
 * start and end of the FLASH PIC driver in ROM/FLASH so that it
 * can be copied out to DRAM and then executed.  In other words,
 * any modifications/additions must be between these two functions!
 */
/*****************************************************************/
void
amd29f010_start (void)
{
}

/*****************************************************************/
void
amd29f010_read (AMD29F010 *amd29f010)
{
	/*
	 * This routine places the FLASH in the read/reset mode.
	 */
	amd29f010->device.cmdreg1 = AMD29F010_READ_CMD1;
	amd29f010->device.cmdreg2 = AMD29F010_READ_CMD2;
	amd29f010->device.cmdreg1 = AMD29F010_READ_CMD3;
}

/*****************************************************************/
int
amd29f010_sector_erase (AMD29F010 *amd29f010, AMD29F010_SECTOR sector)
{
	/*
	 * This routine erases one sector in the FLASH.
	 */
	AMD29F010_CELL	*s;

	s = (AMD29F010_CELL *)&(amd29f010->sector[sector]);

	/*
	 * Perform the Sector Erase command sequence.
	 */
	amd29f010->device.cmdreg1 = AMD29F010_SECTORERASE_CMD1;
	amd29f010->device.cmdreg2 = AMD29F010_SECTORERASE_CMD2;
	amd29f010->device.cmdreg1 = AMD29F010_SECTORERASE_CMD3;
	amd29f010->device.cmdreg1 = AMD29F010_SECTORERASE_CMD4;
	amd29f010->device.cmdreg2 = AMD29F010_SECTORERASE_CMD5;
	*s = AMD29F010_SECTORERASE_CMD6;

	/*
	 * Wait for the device to erase the sector
	 */

	while ((*s & AMD29F010_SECTORERASE_DONE) != AMD29F010_SECTORERASE_DONE)
		;

	/*
	 * Place the device back in the Read/Reset mode.
	 */
	amd29f010_read (amd29f010);

	return 1;
}


/*****************************************************************/
int
amd29f010_id (AMD29F010 *amd29f010)
{
	/*
	 * This routine extracts from the FLASH the manufacturer and
	 * and device code.  If the codes match those for the AMD29F010,
	 * then 1 is returned, else 0.
	 */
	volatile unsigned int manuf, device;

	/*
	 * Perform the Autoselect command sequence.
	 */
	amd29f010->device.cmdreg1 = AMD29F010_AUTOSELECT_CMD1;
	amd29f010->device.cmdreg2 = AMD29F010_AUTOSELECT_CMD2;
	amd29f010->device.cmdreg1 = AMD29F010_AUTOSELECT_CMD3;

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

	/*
	 * Place the device back in the Read/Reset mode.
	 */
	amd29f010_read (amd29f010);

	/*
	 * Determine if an AMD29F010 or not.
	 */
	if (device == AMD29F010_DEVICE_CODE)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}


/*****************************************************************/
int
amd29f010_write (AMD29F010 *amd29f010,
	void *data, unsigned length, AMD29F010_SECTOR sector, void (*func)(void))
{
	/*
	 * This routine programs the device beginning at 'sector' with
	 * 'data' for 'length' bytes.  This routine is capable of
	 * programming multiple consecutive sectors.
	 */
	int index, written, done;
	AMD29F010_CELL *source;
	AMD29F010_CELL *target;
	AMD29F010_CELL rdata;

	/*
	 * Step 1)  ID the flash as a AMD29F010.
	 */
	if (!amd29f010_id(amd29f010))
		return 0;

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

	done = 0;
	written = 0;
	while (!done)
	{
		/*
		 * Step 3)  Erase the sector.
		 */
		if (!amd29f010_sector_erase (amd29f010, sector))
			return -1;

		/*
		 * Step 5)  Program the FLASH with the sector(s) contained in RAM.
		 */
		for (index = 0; (index < AMD29F010_SECTOR_SIZE) && (written < length);
			++index)
		{
			/*
			 * Perform the Byte Program command sequence.
			 */
			amd29f010->device.cmdreg1 = AMD29F010_BYTEPROG_CMD1;
			amd29f010->device.cmdreg2 = AMD29F010_BYTEPROG_CMD2;
			amd29f010->device.cmdreg1 = AMD29F010_BYTEPROG_CMD3;
			*target = *source;

			/*
			 * Poll to make sure it is done before continuing...
			 */
			while (1)
			{
				int timeouts;

				timeouts = 0;

				rdata = *(volatile AMD29F010_CELL *)target;

				if ((rdata & AMD29F010_DATA_POLL_MASK) ==
					(*source & AMD29F010_DATA_POLL_MASK))
				{
					break;
				}
				else
				{
					rdata = *(volatile AMD29F010_CELL *)target;

					if (rdata & AMD29F010_TIME_EXCEEDED)
					{
						rdata = *(volatile AMD29F010_CELL *)target;

						if ((rdata & AMD29F010_DATA_POLL_MASK) ==
							(*source & AMD29F010_DATA_POLL_MASK))
						{
							break;
						}

						if (++timeouts > 1024)
						{
							amd29f010_read (amd29f010);
							break;
						}
					}
				}
			}

			/*
			 * Verify write and increment bytes written counter.
			 */
			amd29f010_read (amd29f010);
			if (*target == *source)
			{
				written += sizeof(AMD29F010_CELL);

				++target;
				++source;
			}
			else
			{
				done = 1;
				break;
			}
		}

		if (++sector >= AMD29F010_SECTORS)
			done = 1;

		if (written >= length)
			done = 1;
	}

	/*
	 * Step 6)  Place the device back in the read mode.
	 */
	amd29f010_read (amd29f010);

	if (func != NULL)
	{
		func();
	}

	return written;
}

void
amd29f010_end(void)
{
	/*
	 * This function is empty and at the END of all code so that it
	 * can be used to compute the size of the code contained in this
	 * driver.
 	 */
}

⌨️ 快捷键说明

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