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

📄 flash.c

📁 基于LPC2478硬件平台的IAP和远程WEB应用。 系统共分为三个部分
💻 C
字号:
/****************************************Copyright (c)****************************************************
**                         ZhangZhou KENENG electronics Co.,LTD.                               
**                                     
**
**
**--------------File Info---------------------------------------------------------------------------------
** File name:			flash.c
** Last modified Date:  2009-01-15
** Last Version:		1.0
** Descriptions:		提供操作片外NOR FLASH的接口,当前主要用到初始化函数
			同时提供其他操作,以备将来BOOTLOADER功能扩展需要。
**		此驱动专针对SST39VF1601芯片,它是1Mx16宽的芯片。
**--------------------------------------------------------------------------------------------------------
** Created by:			heshusheng
** Created date:		2009-01-15
** Version:				1.0
** Descriptions:		The original version
**
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
*********************************************************************************************************/
#include "flash.h"

#define  FLASH_ADDR			0x81000000  	                            /* FLASH的起始地址(分配为Bank1块)*/
#define  FLASH_END			0x81200000									/*FLASH的结束地址*/
#define  FLASH_SECTOR		0x1000										/*扇区宽度(字节)*/
#define  FLASH_BLOCK		0X10000										/*块长度(字节)*/

/********************************************************************************************************
* 转换地址。将要发送给SST39VF1601的地址值进行转换,以便于LPC2210输出。
* 由于SST39VF1601的A0是与LPC2470的A1相连,所以addr要左移1位。
*********************************************************************************************************/
#define  GetAddr(addr)	(volatile uint16  *)(FLASH_ADDR|(addr<<1))

/********************************************************************************************************
*将16位的前后两个字节进行颠倒处理
*
*********************************************************************************************************/
#define SWAP_16(x) ((uint16)( \
		(((uint16)(x) & (uint16)0x00ffU) << 8) |
		(((uint16)(x) & (uint16)0xff00U) >> 8)
		))
		
/********************************************************************************************************
*将16位的前后两个字节进行颠倒处理

**********************************************************************************************************/
#define SWAP_32(x) ((uint32)( \
			(((uint32)(x) & (uint32)0x000000ffU) 	 ) | 
			(((uint32)(x) & (uint32)0x0000ff00U) << 8 ) | 
			(((uint32)(x) & (uint32)0x00ff0000U) << 8) | 
			(((uint32)(x) & (uint32)0xff000000U) >> 8)
			))

/*********************************************************************************************************
* 名    称:WordProgram()
* 功    能:半字(16位)数据编程。
* 入口参数:Addr		编程地址(SST39VF1601内部地址)	
*           Data		编程数据
* 出口参数:返回TRUE表示操作成功,返回FALSE表示操作失败
**********************************************************************************************************/
uint8  WordProgram(uint32 iAddr, uint16 iData) 
{  
    volatile uint16  *ipTmp;
    uint16  itemp1,itemp2;

    ipTmp = GetAddr(0x5555);	                                        /* 转换地址0x5555                */
    ipTmp[0] = 0xaaaa;			                                        /* 第一个周期,地址0x5555,数据0xAA*/
    ipTmp = GetAddr(0x2aaa);
    ipTmp[0] = 0x5555;			                                        /* 第二个周期,地址0x2aaa,数据0x55*/
    ipTmp = GetAddr(0x5555);
    ipTmp[0] = 0xa0a0;			                                        /* 第三个周期,地址0x5555,数据0xA0*/
    
   // ipTmp = (volatile uint16  *)(FLASH_ADDR|(iAddr&0x1FFFFF));
    ipTmp = (volatile uint16 *)iAddr;
    *ipTmp = iData;				                                        /* 第四个周期,地址Addr,数据Data  */
   
   /*
    *  等待操作完成 (若编程操作没有完成,每次读操作DQ6会跳变)
    */
    while (1) { 
        itemp1 = *ipTmp;			
        itemp2 = *ipTmp;
        if (itemp1 == itemp2) {  
		 itemp1 = *ipTmp;			
		 itemp2 = *ipTmp;
            if (itemp1 != iData) {  
                return(FALSE);
            }
            else { 
                return(TRUE);
            }
        }
    }
    return(TRUE);
}

/*********************************************************************************************************
* 名    称:flash_erase_sector
* 功    能:擦除指定的扇区 4Kbyte
* 入口参数:Addr		编程地址
*           no		扇区数目
* 出口参数:返回TRUE表示操作成功,返回FALSE表示操作失败
**********************************************************************************************************/
int flash_erase_sector(long addr, int no)
{
	volatile uint16  *ipTmp;
	uint16  itemp1,itemp2;
	int i;
	for (i = 0; i < no; i++)
	{
		if (addr <= FLASH_END )
		{
			ipTmp = GetAddr(0x5555);
			ipTmp[0] = 0xaaaa;
			ipTmp = GetAddr(0x2aaa);
			ipTmp[0] = 0x5555;	
			ipTmp = GetAddr(0x5555);
			ipTmp[0] = 0x8080;	
			ipTmp = GetAddr(0x5555);
			ipTmp[0] = 0xaaaa;
			ipTmp = GetAddr(0x2aaa);
			ipTmp[0] = 0x5555;
			ipTmp = (volatile uint16 *)addr;
	    		*ipTmp = 0x3030;
			/*
		    *  等待操作完成 (若编程操作没有完成,每次读操作DQ6会跳变)
		    */
			while (1) 
			{ 
				itemp1 = *ipTmp;			
				itemp2 = *ipTmp;
				if (itemp1 == itemp2) 
					if (itemp1 != 0xffff) 
						return 0;
					else
						break;
			}		
			addr += FLASH_SECTOR;
		}
		else
			return 1;
	}
	return 1;
}

/*********************************************************************************************************
* 名    称:flash_erase_block
* 功    能:擦除指定的块64Kbyte
* 入口参数:Addr		编程地址
*           no		块数目
* 出口参数:返回TRUE表示操作成功,返回FALSE表示操作失败
**********************************************************************************************************/
int flash_erase_block(long addr, int no)
{
	volatile uint16  *ipTmp;
	uint16  itemp1,itemp2;
	int i;
	for (i = 0; i < no; i++)
	{
		if (addr <= FLASH_END )
		{
			ipTmp = GetAddr(0x5555);
			ipTmp[0] = 0xaaaa;
			ipTmp = GetAddr(0x2aaa);
			ipTmp[0] = 0x5555;	
			ipTmp = GetAddr(0x5555);
			ipTmp[0] = 0x8080;	
			ipTmp = GetAddr(0x5555);
			ipTmp[0] = 0xaaaa;
			ipTmp = GetAddr(0x2aaa);
			ipTmp[0] = 0x5555;
			ipTmp = (volatile uint16 *)addr;
	    		*ipTmp = 0x5050;
			/*
		    *  等待操作完成 (若编程操作没有完成,每次读操作DQ6会跳变)
		    */
			while (1) 
			{ 
				itemp1 = *ipTmp;			
				itemp2 = *ipTmp;
				if (itemp1 == itemp2) 
					if (itemp1 != 0xffff) 
						return 0;
					else
						break;
			}		
			addr += FLASH_BLOCK;
		}
		else
			return 1;
	}
	return 1;
}

/*********************************************************************************************************
* 名    称:flash_erase_chip()
* 功    能:提供接口供给外部调用,擦除全片数据
* 入口参数:
* 出口参数:返回TRUE表示操作成功,返回FALSE表示操作失败
**********************************************************************************************************/
int flash_erase_chip( void )
{
	volatile uint16  *ipTmp;
	uint16  itemp1,itemp2;

	ipTmp = GetAddr(0x5555);
	ipTmp[0] = 0xaaaa;			                                        /* 第一个周期,地址0x5555,数据0xAA*/
	ipTmp = GetAddr(0x2aaa);
	ipTmp[0] = 0x5555;			                                        /* 第二个周期,地址0x2aaa,数据0x55*/
	ipTmp = GetAddr(0x5555);
	ipTmp[0] = 0x8080;			                                        /* 第三个周期,地址0x5555,数据0x80*/
	ipTmp = GetAddr(0x5555);
	ipTmp[0] = 0xaaaa;			                                        /* 第四个周期,地址0x5555,数据0xAA*/
	ipTmp = GetAddr(0x2aaa);
	ipTmp[0] = 0x5555;			                                        /* 第五个周期,地址0x2aaa,数据0x55*/
	ipTmp = GetAddr(0x5555);
	ipTmp[0] = 0x1010;			                                        /* 第六个周期,地址0x5555,数据0x10*/

	/* 
	*  等待操作完成 (若擦除操作没有完成,每次读操作DQ6会跳变) 
	*/
	while (1)				
	{  
	  itemp1 = *ipTmp;
	  itemp2 = *ipTmp;
	  if (itemp1 == itemp2)
	  {  
	      if (itemp1 != 0xffff)
	      {  
	          return(FALSE);
	      }
	      else
	      {  
	          return(TRUE);
	      }
	  }
	}
	return(TRUE);
}

/*********************************************************************************************************
* 名    称:flash_write()
* 功    能:提供接口供给外部调用,按字节进行编程。
* 入口参数:src		写入的数据缓存
*		 addr : 写入的地址,使用0x81******开头的地址		
*           cnt	:写入的数据长度
* 出口参数:返回TRUE表示操作成功,返回FALSE表示操作失败
**********************************************************************************************************/
int flash_write(char *src,long addr,long cnt)
{
	long cp, wp;
	uint16 data;
	int count, i, l, rc, port_width;

	wp = (addr & ~1);
	port_width = 2;

	/*处理非16位对齐的起始地址*/
	if ((l = addr - wp) != 0) {
		data = 0;
		for (i = 0, cp = wp; i < l; ++i, ++cp) {
			data = (data << 8) | (*(char *) cp);
		}
		for (; i < port_width && cnt > 0; ++i) {
			data = (data << 8) | *src++;
			--cnt;
			++cp;
		}
		for (; cnt == 0 && i < port_width; ++i, ++cp) {
			data = (data << 8) | (*(char *) cp);
		}

		if ((rc = WordProgram( wp, SWAP_16 (data))) == 0) {
			return (rc);
		}
		wp += port_width;
	}

	/*处理对齐后的数据部分*/
	count = 0;
	while (cnt >= port_width) {
		data = 0;
		for (i = 0; i < port_width; ++i) {
			data = (data << 8) | *src++;
		}
		if ((rc = WordProgram( wp, SWAP_16 (data))) == 0) {
			return (rc);
		}
		wp += port_width;
		cnt -= port_width;
		if (count++ > 0x800) {
			count = 0;
		}
	}

	if (cnt == 0) {
		return (1);
	}

	/*处理非16位对齐的结尾地址*/
	data = 0;
	for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) {
		data = (data << 8) | *src++;
		--cnt;
	}
	for (; i < port_width; ++i, ++cp) {
		data = (data << 8) | (*(char *) cp);
	}

	return (WordProgram ( wp, SWAP_16 (data)));
}

/*********************************************************************************************************
* 名    称:flash_init()
* 功    能:提供接口供给外部调用,NORFLASH 初始化函数
* 入口参数:无
* 出口参数:无
**********************************************************************************************************/
void flash_init( void )
{
	PINSEL6 = 0x55555555;
	//PINSEL8 = 0x55555554;
	PINSEL8 = 0x55555555;
	PINSEL9 |= 0x40050155;

	EMCControl = 0x01;
	EMCStaticConfig1 = 0x00000081;
	EMCStaticWaitRd1 = 0x04;
	EMCStaticWaitOen1 = 0x01;

	EMCStaticWaitWen1 = 0x00;
	EMCStaticWaitWr1 = 0x02;
}

⌨️ 快捷键说明

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