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

📄 intel_flash_routines.c

📁 An111 is a quite old flashing equipment. It s the source code to drive old equipment.
💻 C
字号:
/***************************************************************************
   Copyright ARM Limited 1998 - 2003.  All rights reserved.
****************************************************************************

   Intel_Flash_Routines.c

   Flash routines for Intel Flash devices using the 'Basic Command Set'

****************************************************************************/

#include "integrator.h"

// Various constants
#define TRUE	1
#define FALSE	0
#define PASS	0
#define FAIL	-1

// Intel Basic Command Set Commands
#define PROGRAM_COMMAND		0x10
#define PROGRAM_VERIFY		0xD0
#define READ_STATUS			0x70
#define CLEAR_STATUS		0x50
#define READ_ARRAY			0xFF
#define BLOCK_ERASE			0x20
#define BLOCK_WRITE_MODE	0xE8
#define BLOCK_LOCK_BITS		0x60
#define BLOCK_LOCK_CONFIRM	0x01
#define CFI_QUERY_COMMAND	0x98
#define CFI_DATA_OFFS		0x20

// Intel Status masks
#define STATUS_READY		0x80
#define STATUS_LOCKED		0x01
#define LOCK_ERROR			0x10
#define ERASE_ERROR			0x20

#define MAX_WRITE_BUFF		0x0F

static int Flash_Unlock_Block(unsigned int*);
static int ReadyWait(volatile unsigned int*);

//  This issues a (byte sized) command to the Flash device.
//  If multiple parrallel devices are used (eg 2 * 16 bit Flash parts providing 32 bit memory)
//  The command is issued to all devices
static int command(unsigned char command, unsigned int *address)
{
#ifdef fc16x2
    {
		*(volatile unsigned int *)address = ((unsigned int)command | (unsigned int)command<<16);
    }
#endif

#ifdef fc16x1
    {
		*(volatile unsigned short *)address = (unsigned short)command;
    }
#endif

#ifdef fc32x1
    {
		*(volatile unsigned int *)address = (unsigned int)command;
    }
#endif

#ifdef fc8x1
    {
		*(volatile unsigned char *)address = (unsigned char)command;
    }
#endif

#ifdef fc8x2
    {
		*(volatile unsigned short *)address = ((unsigned short)command | (unsigned short)command<<8);
    }
#endif

#ifdef fc8x4
    {
		*(volatile unsigned short *)address = ((unsigned int)command | (unsigned int)command<<8 | (unsigned int)command<<16 | (unsigned int)command<<24);
    }
#endif

    return PASS;
}

// This routine writes a single 32 bit word to Flash.  On entry, it assumes the
// Flash is in READ-ARRAY mode (which it is following reset, or exit from any other
// non-static function in this source file.
// For 16-bit access flash, Little Endian is presumed.
// This function checks whether the block is locked before attempting the write.

int Flash_Write_Word(unsigned int *address, unsigned int data)
{

#ifdef fc32x1
    	command(PROGRAM_COMMAND, address);		//  Writing 0x10 puts devices into write mode.
		*(volatile unsigned int*)address = data;						//  Write data
   		command (READ_STATUS, address);			// Put device into 'READ STATUS MODE'.
		ReadyWait(address);						//  Wait for write to complete.
		while(*(volatile unsigned int*)address & 0x00000002)			// Block was locked (if should suffice, but while good for debug).
		{
			Flash_Unlock_Block(address);		// re-issue program command 0x10 (word)
			command(PROGRAM_COMMAND, address);	//  address simply needs to be in the correct device
			*(volatile unsigned int*)address = data;					// Write required word to required address
   			command (READ_STATUS, address);		// Put device into 'READ STATUS MODE'.
			ReadyWait(address);		
		}
#endif	

#ifdef fc16x2
   		command(PROGRAM_COMMAND, address);		//  Writing 0x10 puts devices into write mode.
		*(volatile unsigned int*)address = data;						//  Write data
   		command (READ_STATUS, address);			// Put device into 'READ STATUS MODE'.
		ReadyWait(address);						//  Wait for write to complete.
		while(*(volatile unsigned int*)address & 0x00020002)			// Block was locked (if should suffice, but while good for debug).
		{
			Flash_Unlock_Block(address);		// re-issue program command 0x10 (word)
			command(PROGRAM_COMMAND, address);	//  address simply needs to be in the correct device
			*(volatile unsigned int*)address = data;					// Write required word to required address
   			command (READ_STATUS, address);		// Put device into 'READ STATUS MODE'.
			ReadyWait(address);		
		}
#endif		

#ifdef fc16x1		// ***ASSUMES LITTLE ENDIAN***
   		int i;
   		short shdata;
   		for (i=0;i<2;i++)
   		{
	   		shdata=(short)data;
	   		command(PROGRAM_COMMAND, address);				//  Writing 0x10 puts devices into write mode.
			*((volatile unsigned short*)address+i) = shdata;//  Write data
	   		command (READ_STATUS, address);					// Put device into 'READ STATUS MODE'.
			ReadyWait(address);								//  Wait for write to complete.
			while(*(volatile unsigned short*)address & 0x0002)			// Block was locked (if should suffice, but while good for debug).
			{
				Flash_Unlock_Block(address);				// re-issue program command 0x10 (word)
				command(PROGRAM_COMMAND, address);			//  address simply needs to be in the correct device
				*((volatile unsigned short*)address+i) = shdata;	// Write required word to required address
	   			command (READ_STATUS, address);				// Put device into 'READ STATUS MODE'.
				ReadyWait(address);		
			}
			data=data>>16
		}
#endif		

#ifdef fc8x4
   		command(PROGRAM_COMMAND, address);		//  Writing 0x10 puts devices into write mode.
		*(volatile unsigned int*)address = data;//  Write data
   		command (READ_STATUS, address);			// Put device into 'READ STATUS MODE'.
		ReadyWait(address);						//  Wait for write to complete.
		while(*(volatile unsigned int*)address & 0x02020202)			// Block was locked (if should suffice, but while good for debug).
		{
			Flash_Unlock_Block(address);		// re-issue program command 0x10 (word)
			command(PROGRAM_COMMAND, address);	//  address simply needs to be in the correct device
			*(volatile unsigned int*)address = data;					// Write required word to required address
   			command (READ_STATUS, address);		// Put device into 'READ STATUS MODE'.
			ReadyWait(address);		
		}
#endif

#ifdef fc8x2
   		int i;
   		short shdata;
   		for (i=0;i<2;i++)
   		{
	   		shdata=(short)data;
	   		command(PROGRAM_COMMAND, address);				//  Writing 0x10 puts devices into write mode.
			*((volatile unsigned short*)address+i) = shdata;//  Write data
	   		command (READ_STATUS, address);					// Put device into 'READ STATUS MODE'.
			ReadyWait(address);								//  Wait for write to complete.
			while(*(volatile unsigned short*)address & 0x0202)			// Block was locked (if should suffice, but while good for debug).
			{
				Flash_Unlock_Block(address);				// re-issue program command 0x10 (word)
				command(PROGRAM_COMMAND, address);			//  address simply needs to be in the correct device
				*((volatile unsigned short*)address+i) = shdata;	// Write required word to required address
	   			command (READ_STATUS, address);				// Put device into 'READ STATUS MODE'.
				ReadyWait(address);		
			}
			data=data>>16
		}
#endif

#ifdef fc8x1
   		int i;
   		char chdata;
   		for (i=0;i<4;i++)
   		{
	   		chdata=(char)data;
	   		command(PROGRAM_COMMAND, address);				//  Writing 0x10 puts devices into write mode.
			*((volatile unsigned char*)address+i) = shdata; //  Write data
	   		command (READ_STATUS, address);					// Put device into 'READ STATUS MODE'.
			ReadyWait(address);								//  Wait for write to complete.
			while(*(volatile unsigned char*)address & 0x02)			// Block was locked (if should suffice, but while good for debug).
			{
				Flash_Unlock_Block(address);				// re-issue program command 0x10 (word)
				command(PROGRAM_COMMAND, address);			//  address simply needs to be in the correct device
				*((volatile unsigned short*)address+i) = shdata;	// Write required word to required address
	   			command (READ_STATUS, address);				// Put device into 'READ STATUS MODE'.
				ReadyWait(address);		
			}
			data=data>>8
		}
#endif

    command(READ_ARRAY, address);	// Reset for Read operation
    if (*address != data)  				// Read word back to verify
    	return FAIL;
    else	
    	return PASS;
}

// This function writes an area of flash contained within a single block.
// This is quicker than individual word writes, as it only checks the block is unlocked once,
// And doesn't return to READ_ARRAY mode after each write.  This also allows the
// Flash device's built in write buffer to be used effectively.
// This function DOES NOT CHECK the area to be programmed lies within a single block.

static int Flash_Write_Block(unsigned int *address, int *data, unsigned int size)
{
    int n;
    int *end=data+size/4;
    int done = FALSE;
    int s_reg;

	Flash_Unlock_Block(address);
	
    while (done != TRUE)
    {
		do
		{
			command(BLOCK_WRITE_MODE, address); // Write E8
			s_reg=*address;
		} while((s_reg & (STATUS_READY | (STATUS_READY<<16)))!=(STATUS_READY | (STATUS_READY<<16)));

		n = (size/4) - 1;			// Generate the number to write maximum of 16 words
		if ((n+1) >= MAX_WRITE_BUFF)   // maximum of 16 words
		    n = MAX_WRITE_BUFF;

		command(n, address);  //write word count

		/* write 16 bus-width words of data (32 bytes/chip) */
		for ( ; n >= 0; n--)
		#if (defined fc32x1) | (defined fc16x2) | (defined fc8x4)
				    *(volatile unsigned int*)address++ = *data++;
		#endif
		#if (defined fc16x1) | (defined fc8x2)
				    *(volatile unsigned short*)address++ = *(unsigned short*)data++;
		#endif
		#if (defined fc8x1)
				    *(volatile unsigned char*)address++ = *(unsigned char*)data++;
		#endif

		/* write confirm */
		command(PROGRAM_VERIFY, address);
		ReadyWait(address);
		/* advance pointers */
		if (data >= end)
		    done = TRUE;
    }
    ReadyWait(address);
	command(READ_ARRAY, address);	// Switch back to READ ARRAY mode
    return PASS;
}


// This function returns base and size to cover all blocks required to hold size bytes from address.
int Flash_Calc_Blocks(unsigned int **address, int *size)
{
	int *endadd;
	int temp;
	int blockmask;
	
	blockmask=(FLASH_BLOCK<<2)-1;
	temp=(int)(*address+*size/4);
	temp=temp & ~blockmask;
	
	endadd=(int *)(temp + FLASH_BLOCK);
	*address=(unsigned int *)((int)*address & ~blockmask);
	*size=((int)endadd-(int)*address);
	
	return PASS;


}

// This function writes an arbitary area of flash.
// It first verfies that the data will fit within the flash address space,
// Then divides the operation into calls to Flash_Write_Block, which writes
// data areas contained within a single block.
int Flash_Write_Area(unsigned int *address, int *data, int size)
{
	int	bytesinfirstblock;
	int byteswritten;
	
	if ((address >= FLASH_BASE) && ((address+size/4) <= (FLASH_BASE + FLASH_SIZE)))
	{
		bytesinfirstblock = FLASH_BLOCK - ((int)address - ((int)address & ~(FLASH_BLOCK-1)));
		if (bytesinfirstblock > size) bytesinfirstblock=size;
		Flash_Write_Block(address, data, bytesinfirstblock);
		byteswritten=bytesinfirstblock;
		address += byteswritten/4;
		data += byteswritten/4;
		
		while (size > byteswritten)
		{
			if ((size-byteswritten) < FLASH_BLOCK)
			{
				Flash_Write_Block(address, data, size-byteswritten);
				byteswritten = size;
			}
			else
			{
				Flash_Write_Block(address, data, FLASH_BLOCK);
				byteswritten += FLASH_BLOCK;
				address += FLASH_BLOCK/4;
				data += FLASH_BLOCK/4;
			}
		}
		return PASS;
	}
	else
	{
		return FAIL;
	}
}


// This function erases a single block, specified by it's base address
static int Flash_Erase_Block(unsigned int *address)
{
    int result;
    unsigned int s_reg;
	Flash_Unlock_Block(address);
	do
    {
		result = PASS;
		command(BLOCK_ERASE, address);		// Issue single block erase command
		command(PROGRAM_VERIFY, address);	// Confirm Action 0xd0 with block address
		command(READ_STATUS, address);
		ReadyWait(address);					// Wait for erase attempt to complete
		s_reg = *(volatile unsigned int*)address;  // This results in reading s_reg twice (first time in readywait), so Intel errata does not cause problem.
	        if (s_reg & (ERASE_ERROR | (ERASE_ERROR<<16)))
	        {
	    		command(CLEAR_STATUS, address);
				result = FAIL;
			}

	// Reset for Read operation
	command(READ_ARRAY, address);
    }    while (result == FAIL);

    return (result);
}

// This function erases all blocks overlapping specified region (via calls to Flash_Erase_Block)
int Flash_Erase_Blocks(unsigned int *address, int size)
{
	unsigned int* limit=address+size/4-1;
	for(;address<=limit;address+=FLASH_BLOCK/4)
		Flash_Erase_Block(address);
	return PASS;
}


// This checks the status register, and loops untill the Flash device is 'ready'
static int ReadyWait(volatile unsigned int* address)
{
	#ifdef fc32x1
		while((*address & STATUS_READY )!=STATUS_READY);
	#endif

	#ifdef fc16x2
		while((*address & (STATUS_READY | (STATUS_READY<<16)))!=(STATUS_READY | (STATUS_READY<<16)));
	#endif

	#ifdef fc16x1
		while((*(volatile unsigned short*)address & STATUS_READY)!=STATUS_READY);
	#endif

	#ifdef fc8x4
		while((*address & (STATUS_READY | (STATUS_READY<<8) | (STATUS_READY<<16) | (STATUS_READY<<24)))!=(STATUS_READY | (STATUS_READY<<8) | (STATUS_READY<<16) | (STATUS_READY<<24)));
	#endif

	#ifdef fc8x2
		while((*(volatile unsigned short*)address & (STATUS_READY | (STATUS_READY<<8)))!=(STATUS_READY | (STATUS_READY<<8)));
	#endif

	#ifdef fc8x1
		while((*(volatile unsigned char*)address & STATUS_READY)!=STATUS_READY);
	#endif
	return PASS;
}

static int Flash_Unlock_Block(unsigned int *address)
{
    command (BLOCK_LOCK_BITS, address);   	// Clear lock bits write 0x60 within the device address space
    command (PROGRAM_VERIFY, address);    	// Confirm action by writing 0xD0 within the device address space
    command (READ_STATUS, address);		  	// Put device into 'READ STATUS MODE'.
	ReadyWait(address);						// Wait for write to complete.
    command (READ_ARRAY, address);			// Put device back into read mode.
    return PASS;
}

int Flash_Init ()
{
	return PASS;
}

int Flash_Close ()
{
	return PASS;
}


⌨️ 快捷键说明

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