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

📄 flash_lpc.c

📁 lpc-h22xx.zip 一款LPC2214开发板的代码。功能是测试开发板
💻 C
字号:
/*
 * $Revision: 1.0 $
 */

#include "flash_lpc.h"

// Intel Basic Command Set Commands
#define	READ_ID			0x90
#define PROGRAM_COMMAND		0x40		//or 0x10 both are valid
#define PROGRAM_VERIFY		0xD0
#define READ_STATUS		0x70
#define CLEAR_STATUS		0x50
#define READ_ARRAY		0xFF
#define BLOCK_ERASE		0x20
#define	PROG_ERASE_SUSPEND	0xB0
#define	PPROG_ERASE_RESUME	0xD0
#define BLOCK_LOCK_BITS		0x60
#define	PROT_PRG		0xC0
#define BLOCK_LOCK_CONFIRM	0x01
#define CFI_QUERY_COMMAND	0x98
#define CFI_DATA_OFFS		0x20
#define RESET_DEV		0xF0

// Word access
#define FIRST_KEY_ADD   	(0x555<<1)
#define SECOND_KEY_ADD   	(0x2AA<<1)
#define THIRD_KEY_ADD   	(0x555<<1)

#define KEY_AA           	0xAA
#define KEY_55           	0x55

#define BIT_PASS_W              0x00000080

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


int command(unsigned char command, unsigned short *address)
{
  *address = (unsigned short)command;
  return PASS;
}

int ReadyWait(unsigned short* address,unsigned short data, FLASH_DEV_MANUFACTURER_ID_DEF DevID)
// This checks the status register, and loops untill the Flash device is 'ready'
{
  if (DevID == INTEL_MAN_ID)
  {
    while((*address & STATUS_READY)!=STATUS_READY);
    return PASS;
  }
  else if (DevID == MXID_MAN)
  {
    while ((data ^ *address) & BIT_PASS_W);
    if ((data ^ *address) & BIT_PASS_W)
      return(FAIL);
    return(PASS);
  }
  return(FALSE);
}

int FlashID(unsigned short* address)
{
unsigned int hold;
  // Put device into 'READ_ID'.
  command(KEY_AA,(unsigned short*)(FIRST_KEY_ADD+FLASH_BEGIN));
  command(KEY_55,(unsigned short*)(SECOND_KEY_ADD+FLASH_BEGIN));
  command(READ_ID,(unsigned short*)(THIRD_KEY_ADD+FLASH_BEGIN));
  hold = *address;                // Read Data
  command (RESET_DEV, address);   // Reset 26LVXXXX
  command (READ_ARRAY, address);  // C3 Put device back into read mode.
// Return Item
  return(hold);
}

unsigned short status;
int Flash_Unlock_Block(unsigned short *address, FLASH_DEV_MANUFACTURER_ID_DEF DevID)
{
//  do
//  {
    command (READ_ARRAY, address);		// Put device back into read mode.
    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_ID, address);    	        // Confirm action by writing 0xD0 within the device address space
//    status = *(volatile unsigned short*)(address + BLOCK_LOCK_STATUS);
//  }
//  while(status);
//  ReadyWait(address,0xFFFF,DevID);   		// Wait for write to complete.
  command (READ_ARRAY, address);		// Put device back into read mode.
  return PASS;
}

int Flash_Write_Word(unsigned long *address, unsigned long data, FLASH_DEV_MANUFACTURER_ID_DEF DevID)
// 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.
{
  // ***LPC2214 IS LITTLE ENDIAN***

int i;
unsigned short shdata;
  shdata=(short)data;
  if(DevID == INTEL_MAN_ID)
  {
    for (i=0;i<2;i++)
    {
      command(PROGRAM_COMMAND,(unsigned short*)address);	// Writing 0x40 puts devices into write mode.
      *((volatile unsigned short*)address+i) = shdata;    // Write data
      command (READ_STATUS,(unsigned short*)address);	// Put device into 'READ STATUS MODE'.
      ReadyWait((unsigned short*)address,0,INTEL_MAN_ID);	// Wait for write to complete.
      while(*(volatile unsigned short*)address & STATUS_LOCKED) // Block was locked (if should suffice, but while good for debug).
      {
        Flash_Unlock_Block((unsigned short*)address,INTEL_MAN_ID);     // re-issue program command 0x10 (word)
        command(CLEAR_STATUS, (unsigned short*)address);  // clear status error
        command(PROGRAM_COMMAND, (unsigned short*)address+i);// address simply needs to be in the correct device
        *((volatile unsigned short*)address+i) = shdata;	// Write required word to required address
        command (READ_STATUS, (unsigned short*)address);	// Put device into 'READ STATUS MODE'.
        ReadyWait((unsigned short*)address,0,INTEL_MAN_ID);		
      }
      shdata = data >> 16;
    }
  
    command(READ_ARRAY, (unsigned short*)address);	// Reset for Read operation
    if (*address != data)                                 // Read word back to verify
      return FAIL;
  }
  else if (DevID == MXID_MAN)
  {
    for (i=0;i<2;i++)
    {
      /* Flash Write Command */
      command(KEY_AA,(unsigned short*)(FIRST_KEY_ADD+FLASH_BEGIN));
      command(KEY_55,(unsigned short*)(SECOND_KEY_ADD+FLASH_BEGIN));
      command(0xA0,(unsigned short*)(THIRD_KEY_ADD+FLASH_BEGIN));
      *((volatile unsigned short*)address+i) = shdata;	// Write required word to required address
      if(ReadyWait((unsigned short*)address+i,shdata,MXID_MAN) != PASS){	/* Check Write End */
        return FAIL;
      }
      shdata = data >> 16;
    }
  }
  else
    return FALSE;
  return PASS;
}

int Flash_Write_Area(unsigned long *address, long *data, long size, FLASH_DEV_MANUFACTURER_ID_DEF DevID)
// 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_Word, which writes
// data areas contained within a single block.
{
  if ((address >= (unsigned long*)FLASH_BASE) && ((address+size/4) <= (unsigned long*)(FLASH_BASE + FLASH_SIZE)))
  {
    for (unsigned i = 0; i!=size; ++i)
    {
      if(Flash_Write_Word(address,*(data+i),DevID)!=PASS) return FAIL;
    }
  }
  else
  {
    return FAIL;
  }
  return PASS;
}


int Flash_Erase_Block(unsigned long *address, FLASH_DEV_MANUFACTURER_ID_DEF DevID)
// This function erases a single block, specified by it's base address
{
int result;
unsigned int s_reg;
  if (DevID == INTEL_MAN_ID)
  {
    Flash_Unlock_Block((unsigned short*)address,INTEL_MAN_ID);
    do
    {
      result = PASS;
      command(BLOCK_ERASE, (unsigned short*)address);	        // Issue single block erase command
      command(PROGRAM_VERIFY, (unsigned short*)address);	// Confirm Action 0xd0 with block address
      command(READ_STATUS, (unsigned short*)address);
      ReadyWait((unsigned short*)address,0xFFFF,INTEL_MAN_ID);	// 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, (unsigned short*)address);
        result = FAIL;
      }
      // Reset for Read operation
      command(READ_ARRAY, (unsigned short*)address);
    } while (result == FAIL);
  }
  else
  {
    command(KEY_AA,(unsigned short*)(FIRST_KEY_ADD+FLASH_BEGIN));
    command(KEY_55,(unsigned short*)(SECOND_KEY_ADD+FLASH_BEGIN));
    command(0x80,(unsigned short*)(THIRD_KEY_ADD+FLASH_BEGIN));
    command(KEY_AA,(unsigned short*)(FIRST_KEY_ADD+FLASH_BEGIN));
    command(KEY_55,(unsigned short*)(SECOND_KEY_ADD+FLASH_BEGIN));
    command(0x30,(unsigned short*)address);
    result = ReadyWait((unsigned short*)address,0xFFFF,MXID_MAN);
  }
  return (result);
}

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



⌨️ 快捷键说明

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