📄 nflash.c
字号:
/***
* nflash.c - Samsung nandflash driver
* - modified by Feng Lie Bin 2006/12/12
***/
#include "PublHead.h"
#if (INCLUDE_ALLDATASAVE == 0)
//const define
#define MaxNandTypeNum 0x04 //定义型号种类
#define MaxWriteTryNum 0x03 //重复写nandflash次数
//product ID
#define ProductID_SAMSUNG 0xec //厂商代码
//nandflash command
#define NandReadCommand0 0x00 //读A区指令
#define NandReadCommand1 0x01 //读B区指令
#define NandReadCommand2 0x50 //读C区指令
#define NandWriteCommand 0x80 //写输入指令
#define NandWriteStartCom 0x10 //写开始指令
#define NandReadIDCom 0x90 //读厂商指令
#define NandEraseCom 0x60 //擦除建立指令
#define NandEraseStartCom 0xd0 //擦除开始指令
#define NandReadStatusCom 0x70 //读擦写是否成功标志
//定义常量
static U8 const NandTypeIdx[MaxNandTypeNum] = {0xE3,0xE6,0x73,0x75}; //nandflash型号列表
// 4M 8M 16M 32M
static U32 const NandSizeIdx[MaxNandTypeNum] = {0x00400000,0x00800000,0x01000000,0x02000000}; //nandflash总容量列表
// 8K 8K 16K 16K
static U16 const NandBlockSizeIdx[MaxNandTypeNum] = {0x2000,0x2000,0x4000,0x4000}; //nandflash块容量列表
//定义全局变量
U32 NandFlashSize; //nandflash可使用全局容量
U16 NandBlockSize; //nandflash全局块容量
BOOL NandFlashExist; //nandflash是否存在
// 读NandFlash厂商码
static void nf_ReadIDOneTime(U8 * id)
{
NandSelect();
NfMoveCToFlash(NandReadIDCom);
NfMoveAToFlash(0x00);
nf_MoveByteToRam(id,2);
NandDeselect();
}
// NandFlash初始化
extern Boolean NF_DeviceInit(void)
{
U8 id[2];
Uchar i;
Boolean ok;
ok = 0;
nf_ReadIDOneTime(id);
for(i=0 ; i<MaxWriteTryNum ; i++)
{
U8 tmp[2];
nf_ReadIDOneTime(tmp);
if((id[0] == tmp[0]) && (id[1] == tmp[1]))
{
ok = 1;
break;
}
else
{
id[0] = tmp[0];
id[1] = tmp[1];
}
}
if(ok)
{
if(id[0] == ProductID_SAMSUNG)
{
for(i=0 ; i<MaxNandTypeNum ; i++)
{
if(id[1] == NandTypeIdx[i])
{
NandFlashSize = NandSizeIdx[i];
NandBlockSize = NandBlockSizeIdx[i];
NandFlashExist = TRUE;
return(TRUE);
}
}
}
}
NandFlashSize = 0xFFFFFFFF;
NandBlockSize = 0xFFFF;
NandFlashExist = FALSE;
return(FALSE);
}
// 判断Nand Flash是否插入
extern Boolean NF_NoNandFlashErr(void)
{
if(NandFlashExist == FALSE)
{
return(TRUE);
}
return(FALSE);
}
// 选择A,B,C区
static void nf_AreaSelect(Ulong nandadr,Boolean area)
{
Uchar rdcmd;
if(area == 1)
{
rdcmd = NandReadCommand2;
}
else
{
rdcmd = (nandadr & 0x00000100) ? NandReadCommand1 : NandReadCommand0;
}
NfMoveCToFlash(rdcmd);
}
// 地址输出
// 输入: RwOrErase 0:设置Erase的地址, 1:设置读写地址
static void nf_AddrOutput(Ulong nandadr,Boolean RwOrErase)
{
UNION32 un_adr;
un_adr.l = nandadr;
if(RwOrErase)
{
NfMoveAToFlash(un_adr.b[0]); // output address(a0~a7)
}
un_adr.l >>= 1;
NfMoveAToFlash(un_adr.b[1]); // output address(a9~a16)
NfMoveAToFlash(un_adr.b[2]); // output address(a17~a24)
if(NandFlashSize > 0x02000000) //超过32M
{
NfMoveAToFlash(un_adr.b[3]); // output address(a25~a26)
}
}
// 向nandflash发送读命令
static void nf_SendReadCom(Ulong nandadr,Boolean area)
{
nf_AreaSelect(nandadr,area);
nf_AddrOutput(nandadr,1);
nf_PollBusy(100); //根据samsung数据手册进行延时
}
// 从nandflash一个页内读取数据到指定缓冲区,不可以跨页读
extern void NF_ReadDataInPage(Ulong nandadr,U8 * buf,Uint len,Boolean area)
{
NandSelect();
nf_SendReadCom(nandadr,area);
nf_MoveByteToRam(buf,len);
NandDeselect();
}
// 判断nandflash一个页内的数据是否可以写成指定缓冲区中的数据,不可以跨页判断
extern Boolean NF_CompAndDataInPage(Ulong nandadr,U8 * buf,Uint len)
{
Boolean result;
NandSelect();
nf_SendReadCom(nandadr,0);
result = nf_CompAndRamFlash(buf,len);
NandDeselect();
return(result);
}
//读擦写是否成功标志
static Uchar nf_ReadStatus(void)
{
U8 status;
NfMoveCToFlash(NandReadStatusCom); //read status
nf_MoveByteToRam(&status,1);
return(status);
}
// 将NandFlash作块擦除
extern Boolean NF_EraseBlock(Ulong nandadr)
{
Uchar i,status;
for(i=0 ; i<MaxWriteTryNum ; i++) // retry 10 times
{
NandSelect();
NandNoProtect();
NfMoveCToFlash(NandEraseCom);
nf_AddrOutput(nandadr,0);
NfMoveCToFlash(NandEraseStartCom);
nf_PollBusy(30000);
status = nf_ReadStatus();
NandProtect();
NandDeselect();
if((status & 0x01) == 0)
{
return(TRUE);
}
}
return(FALSE);
}
// 从指定缓冲区写入数据到nandflash一个页内,不可以跨页写
extern Boolean NF_WriteDataInPage(Ulong nandadr,U8 * buf,Uint len,Boolean area)
{
Uchar i;
for(i=0 ; i<MaxWriteTryNum ; i++) // retry 3 times
{
Uchar status;
NandNoProtect();
NandSelect();
nf_AreaSelect(nandadr,area);
NfMoveCToFlash(NandWriteCommand);
nf_AddrOutput(nandadr,1);
nf_MoveByteToFlash(buf,len);
NfMoveCToFlash(NandWriteStartCom);
nf_PollBusy(5000); // check busy (spec: typ=200us, max=500us)
status = nf_ReadStatus(); // get status
NandDeselect();
NandProtect(); // enable protect
if(status & 0x01)
{
continue;
}
//-------
NandSelect();
nf_SendReadCom(nandadr,area);
status = nf_CompRamFlash(buf,len);
NandDeselect();
if(status == TRUE)
{
return(TRUE); // program ok
}
}
return(FALSE);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -