?? 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 + -