📄 flash.c
字号:
#include "config.h"
//P0
#define FALE 1<<12
#define FCLE 1<<21
#define FCE 1<<22
#define FRE 1<<16
#define FRB 1<<15
//P1
#define FWE 1<<24
/*Flash 数据线号线定义*/
#define FIO (16) //P0.16~P0.23
/*控制信号线操作宏定义*/
#define SET_FALE() IO0SET=IO0SET|FALE //FALE
#define CLR_FALE() IO0CLR=IO0CLR|FALE
#define SET_FCLE() IO0SET=IO0SET|FCLE //FCLE
#define CLR_FCLE() IO0CLR=IO0CLR|FCLE
#define SET_FCE() IO0SET=IO0SET|FCE //FCE
#define CLR_FCE() IO0CLR=IO0CLR|FCE
#define SET_FWE() IO1SET=IO1SET|FWE //FWE
#define CLR_FWE() IO1CLR=IO1CLR|FWE
#define SET_FRE() IO0SET=IO0SET|FRE //FRE
#define CLR_FRE() IO0CLR=IO0CLR|FRE
#define SET_FRB() IO0SET=IO0SET|FRB //FRB
#define CLR_FRB() IO0CLR=IO0CLR|FRB
/************************************************************************
//delay,小延时函数!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*************************************************************************/
static void delay(void) //LPC2136的IO口进行In/Out变换时需要反应时间,否则会发生反应来不及的情况,实践所得!!!
{ //因此凡是在涉及到IO口方向变化时必须调用本函数,实践得这个循环输至少为30,我们这取80
uint8 dly=80;
while(dly--);
}
/*数据信号线操作宏定义*/
#define SETFI() {IO1DIR=IO1DIR&(~(0xFF<<FIO));delay();} //Set P0.16~P0.23 as input
#define SETFO() {IO1DIR=IO1DIR|(0xFF<<FIO);delay();} //Set P0.16~P0.23 as output
#define WFIO(dat) IO1PIN=(IO1PIN&(~(0xFF<<FIO)))|((dat)<<FIO) //向数据口写字节dat
#define RFIO(dat) (dat)=(IO1PIN>>FIO)&0xFF //从数据口读字节到dat
/*我们采用40MHz主频,每执行一条指令25ns,故本内嵌函数相当于延时
25ns.一般情况下Flash需要的时间延时<100ns,nop()几次就足够了*/
#define nop() __asm \
{ \
NOP \
}
/*Status命令字*/
#define SPstatusCMD 0x70 //signal plane status command
#define MPstatusCMD 0x71 //multi plane status command
/*Flash功能函数*/
static void WriteCmd(uint8 cmd); //向Flash写命令字节
static void WriteData(uint8 data);
static void WriteByteAddr(uint8 ByteAddr); //向Flash写地址字节
static void WriteAddr(uint32 addr); //向Flash写地址(26bits--64M)
/************************************************************************
//InitFlash,初始化控制信号
*************************************************************************/
void InitFlash(void)
{
IO0DIR=IO0DIR | FALE | FCLE | FCE | FRE; //Config P0.28,29,30 as output
IO1DIR=IO1DIR | FWE; //Cofig P1.21,22,23 as output
//IO0DIR=IO0DIR & ( ~FRB ); //Cofig P1.24 as input
SETFO(); //Config P0.16~23 as output
/*控制信号初始态,除写保护信号有效,其余信号均为其无效电平*/
//CLR_FWP(); //WP=0,write protected
CLR_FCLE(); //CLE=0
CLR_FALE(); //ALE=0
SET_FCE(); //CE=0
SET_FRE(); //RE=1
SET_FWE(); //WE=1
}
/************************************************************************
//WriteCmd,写命令
*************************************************************************/
static void WriteCmd(uint8 cmd)
{
SET_FCLE(); //CLE=1,锁入的是命令
CLR_FWE(); //WE=0,以便生成一个上升沿发送命令
WFIO(cmd); //送出数据
SET_FWE(); //恢复所有信号为初始化状态,上升沿锁存命令至Flash
CLR_FCLE();
}
/************************************************************************
//WriteData
*************************************************************************/
void WriteData(uint8 data)
{
CLR_FWE();
WFIO(data);
SET_FWE(); //上升沿送出数据
}
/************************************************************************
//一个字节一个字节地写地址
*************************************************************************/
static void WriteByteAddr(uint8 ByteAddr)
{
SET_FALE(); //ALE=1,is address
CLR_FWE();
WFIO(ByteAddr);
SET_FWE(); //Rising edage
CLR_FALE();
}
/************************************************************************
//WriteAddr,写26位地址
*************************************************************************/
static void WriteAddr(uint32 addr)
{
SET_FALE();
CLR_FWE();
WFIO(addr&0xFF); //A0-A7,Column addr
SET_FWE();
CLR_FWE();
WFIO((addr>>8)&0x0F); //A8-A11,the following is Page addr
SET_FWE();
CLR_FWE();
WFIO((addr>>12)&0xFF); //A12-A19
SET_FWE();
CLR_FWE();
WFIO((addr>>20)&0xff); //A20-A27
SET_FWE();
CLR_FALE();
}
/************************************************************************
//ReadID
*************************************************************************/
uint32 ReadID(void)////////////////////
{
uint32 ID;
uint8 a,b,c,d;
CLR_FCE();
WriteCmd(0x90);
WriteByteAddr(0);
SETFI();
//*****Read ID start
/*Make Code*/
CLR_FRE();
nop();
SET_FRE();
RFIO(a);
/*Device Code*/
CLR_FRE();
nop();
SET_FRE();
RFIO(b);
/*Reserved Code*/
CLR_FRE();
nop();
SET_FRE();
RFIO(c);
/*Multi-Plane Code*/
CLR_FRE();
nop();
SET_FRE();
RFIO(d);
//*****Read ID end
SETFO();
ID = (a << 24) + (b << 16) + (c << 8) + d;
SET_FCE();
return ID;
}
/************************************************************************
//ReadStatus()
*************************************************************************/
uint8 ReadStatus(uint8 cmd)///////////////////////////////////////////////
{
uint8 status;
WriteCmd(cmd);
SETFI();
CLR_FRE(); //CE下降沿读状态数据
nop();
nop();
RFIO(status);
SETFO();
SET_FRE();
return(status);
}
/************************************************************************
//ReadNameData,读取Data空间指定地址指定数量字节
*************************************************************************/
BOOL ReadNameData(uint32 PageAddr,uint16 offset,uint16 num,uint8 *buf)
{
uint8 data;
uint16 i;
CLR_FCE();
if(offset>2048 || (offset+num)>2112)
{
SET_FCE();
return(false);
}
WriteCmd(0x00); //Read1 operation
WriteAddr((PageAddr<<12) | offset);
WriteCmd(0x30);
while(!(FRB & IO0PIN));
SETFI(); //data口为输入口
for(i=0;i<num;i++)
{
CLR_FRE(); //read data
RFIO(data);
*buf++ =data;
SET_FRE(); //increased data pointer
}
SETFO(); //恢复data为输出口
SET_FCE();
return(true);
}
/************************************************************************
//ReadOneData,读取data空间一个字节
*************************************************************************/
uint8 ReadOneData(uint32 PageAddr,uint16 offset)
{
uint8 buf;
ReadNameData(PageAddr,offset,1,&buf);
return(buf);
}
/************************************************************************
//ReadData,读取data空间512字节
*************************************************************************/
BOOL ReadData(uint32 PageAddr,uint8 *buf)
{
return(ReadNameData(PageAddr,0,2048,buf));
}
/************************************************************************
//ReadOneSpace,读取space空间一个字节
*************************************************************************/
uint8 ReadOneSpace(uint32 PageAddr,uint8 offset)////////////////////////////
{
uint8 buf;
ReadNameData(PageAddr,offset + 2048,1,&buf);
return(buf);
}
/************************************************************************
//ReadSpace,读取space空间16字节
*************************************************************************/
BOOL ReadSpace(uint32 PageAddr,uint8 *buf)
{
return(ReadNameData(PageAddr,2048,64,buf));
}
/************************************************************************
//ProData,data空间页编程2048字节
*************************************************************************/
BOOL ProData(uint32 PageAddr,uint8 *buf)
{
uint16 i;
CLR_FCE();
WriteCmd(0x80); //数据输入指令
WriteAddr(PageAddr<<12); //地址输入
for(i=0;i<2048;i++)
WriteData(*buf++);
WriteCmd(0x10); //自动编程命令
while(!(ReadStatus(SPstatusCMD)&(1<<6))); //wait for read page completed
if(ReadStatus(SPstatusCMD)&0x01) //编程错误
{
SET_FCE();
return(false);
}
SET_FCE();
return(true);
}
BOOL CopyBackProData(uint32 SPageAddr,uint32 DPageAddr)
{
CLR_FCE();
WriteCmd(0x00); //数据输入指令
WriteAddr(SPageAddr<<12); //地址输入
WriteCmd(0x35); //自动编程命令
while(!(FRB & IO0PIN));
WriteCmd(0x85); //数据输入指令
WriteAddr(DPageAddr<<12); //地址输入
WriteCmd(0x10); //自动编程命令
while(!(ReadStatus(SPstatusCMD)&(1<<6))); //wait for read page completed
if(ReadStatus(SPstatusCMD)&0x01) //编程错误
{
SET_FCE();
return(false);
}
SET_FCE();
return(true);
}
/************************************************************************
//ProSpace,space空间编程16字节
*************************************************************************/
BOOL ProSpace(uint32 PageAddr,uint8 *buf)
{
uint16 i;
CLR_FCE();
WriteCmd(0x80); //数据输入指令
WriteAddr((PageAddr<<12) | 2048); //地址输入
for(i=0;i<64;i++)
WriteData(*buf++);
WriteCmd(0x10); //自动编程命令
while(!(ReadStatus(SPstatusCMD)&(1<<6))); //wait for read page completed
if(ReadStatus(SPstatusCMD)&0x01) //编程错误
{
SET_FCE();
return(false);
}
SET_FCE();
return(true);
}
/************************************************************************
//EraseBlk
*************************************************************************/
BOOL EraseBlk(uint16 blks)
{
CLR_FCE();
WriteCmd(0x60); //建立擦除命令
WriteByteAddr((uint8)(blks&0xff)); //A12-A19
WriteByteAddr((uint8)((blks>>8)&0xFF)); //A20-A27
WriteCmd(0xD0); //启动擦除命令
while(!(ReadStatus(SPstatusCMD)&(1<<6))); //wait for read page completed
if(ReadStatus(SPstatusCMD)&0x01) //编程错误
{
SET_FCE();
return(false);
}
SET_FCE();
return(true);
}
/************************************************************************
//END
*************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -