|
/**********************按鍵實(shí)驗(yàn)*********************************/
// 公司名稱 :飛凌嵌入式技術(shù)有限公司
// 描 述 :nandflash
// 版 權(quán) :飛凌嵌入式技術(shù)有限公司
// 網(wǎng) 址 :www.witech.com.cn
/***************************************************************/
/*
本實(shí)驗(yàn)接口說明
*/
#include "include.h"
/*-----------------------函數(shù)聲明----------------------------*/
void InitNandFlash(int info);
void cpy_bpage(void);
void add_bpage(unsigned int seq);
extern void Uart_Printf(char *fmt,...);
extern void Uart_Init(int baud);
extern void Uart_Select(int ch);
/*------------------------------------------------------------/
函數(shù)名稱: InitNandCfg
功能描述: 配置flash
傳 參: 無
返 回 值: 無
-------------------------------------------------------------*/
static void InitNandCfg(void)
{
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
//
}
/*------------------------------------------------------------/
函數(shù)名稱: WaitNFBusy
功能描述:
傳 參: 無
返 回 值: static U32 stat&1
-------------------------------------------------------------*/
static U32 WaitNFBusy(void) // 等待nand flash 的操作結(jié)束
{
U8 stat; //因?yàn)閚ansh flash數(shù)據(jù)通道只有8bit
WrNFCmd(QUERYCMD); //QUERYCMD=0X70,將0x70寫入NFCMD
//查看nand flash芯片的資料中的Command Sets
//0x70表示讀nand flash的狀態(tài)
do
{
stat = RdNFDat(); //上面命令是讀nandflash的狀態(tài),因此RdNFDat獲得的是nandflash的狀態(tài)。
}
while (!(stat&0x40)); //[6] busy:0 ready:1
WrNFCmd(READCMD0); //READCMD0=0
return stat&1; //注意0為操作成功.見datasheet34頁表。
}
/*------------------------------------------------------------/
函數(shù)名稱: ReadChipId
功能描述: 讀flash ID
傳 參: 無
返 回 值: static U32 id
-------------------------------------------------------------*/
// 讀ID過程的時(shí)序圖在K9F1G08U0A的datasheet中,第28和35頁//
static U32 ReadChipId(void)
{
U32 id,k;
NFChipEn(); //選中nandflash
WrNFCmd(RdIDCMD);//讀ID命令
WrNFAddr(0); //寫入00h(根據(jù)datasheet)
while(NFIsBusy()); //等待前一步完成
id = RdNFDat()<<8; //define中規(guī)定:RdNFDat8(); for 8 bit nand flash,use byt access
for(k=0;k<500;k++); //
id |= RdNFDat(); //從運(yùn)行結(jié)果ID:ecda來看,可能是這邊程序有點(diǎn)問題(ID指什么不明確)
NFChipDs();
return id;
}
/*------------------------------------------------------------/
函數(shù)名稱: ReadStatus
功能描述: 讀FLASH狀態(tài)
傳 參: 無
返 回 值: static U16 stat
-------------------------------------------------------------*/
static U16 ReadStatus(void)
{
U16 stat;
NFChipEn();
WrNFCmd(QUERYCMD);
stat = RdNFDat();
NFChipDs();
return stat;
}
/*------------------------------------------------------------/
函數(shù)名稱: EraseBlock
功能描述: 擦除 FLASH
傳 參: U32 addr
返 回 值: U32 ~stat
-------------------------------------------------------------*/
// 地址輸入(兩個(gè)周期) datasheet第27頁 //
U32 EraseBlock(U32 addr)
{
U8 stat;
addr &= ~0x3f; //addr=0000 0001 1000 0000
NFChipEn();
WrNFCmd(ERASECMD0); //ERASECMD0=0X60
WrNFAddr(addr); //cycle1:8bit address=1000 0000
WrNFAddr(addr>>8); //cycle2:8bit address=0000 0001
WrNFCmd(ERASECMD1); //ERASE confirm cmd
stat = WaitNFBusy(); //等待擦除完成
NFChipDs();
return ~stat;
}
/*------------------------------------------------------------/
函數(shù)名稱: ReadPage
功能描述:
傳 參: U32 addr, U8 *buf
返 回 值: 無
-------------------------------------------------------------*/
// 讀取block6中的page25 參考datasheet30頁 //
void ReadPage(U32 addr, U8 *buf)
{
U16 i;
NFChipEn();
WrNFCmd(READCMD0); //READCMD0=0
WrNFAddr(0); //
WrNFAddr(0); //因?yàn)樽x的是一個(gè)page,所以col addr=0
WrNFAddr(addr); //
WrNFAddr(addr>>8); //block6,page25的地址
WrNFCmd(READCMD1); //READCMD1=0X30
InitEcc(); //初始化ECC
WaitNFBusy(); //
for(i=0; i<2048; i++)
buf = RdNFDat(); //將2k的內(nèi)容讀出
NFChipDs();
}
/*------------------------------------------------------------/
函數(shù)名稱: WritePage
功能描述:
傳 參: U32 addr, U8 *buf
返 回 值: U32 ~stat
-------------------------------------------------------------*/
/*【Nand Flash中的特殊硬件結(jié)構(gòu)】
1.頁寄存器(Page Register):由于Nand Flash讀取和編程操作
來說,一般最小單位是頁,所以,nand flash在硬件設(shè)計(jì)時(shí)候,就考慮到
這一特性,對于每一片,都有一個(gè)對應(yīng)的區(qū)域,專門用于存放,將要寫入
到物理存儲單元中去的或者剛從存儲單元中讀取出來的,一頁的數(shù)據(jù),這
個(gè)數(shù)據(jù)緩存區(qū),本質(zhì)上就是一個(gè)buffer,但是只是名字叫法不同,datasheet
里面叫做data Register,實(shí)際理解為頁緩存,大小應(yīng)該是等于1個(gè)page
恰當(dāng)些。而正是因?yàn)橛行┤瞬涣私獯藘?nèi)部結(jié)構(gòu),才容易產(chǎn)生之前遇到的某人
的誤解,以為內(nèi)存里面的數(shù)據(jù),通過Nand Flash的FIFO,寫入到Nand Flash
里面去,就以為立刻實(shí)現(xiàn)了實(shí)際數(shù)據(jù)寫入到物理存儲單元中了。而實(shí)際上,
只是寫到了這個(gè)頁緩存中,只有等你發(fā)了對應(yīng)的編程第二階段的確認(rèn)命令0x10
之后,實(shí)際的編程動作才開始,才開始把頁緩存中的數(shù)據(jù),一點(diǎn)點(diǎn)寫到物理存
儲單元中去。*/
// 參考datasheet的第23頁 //
U32 WritePage(U32 addr, U8 *buf)
{
U32 i, mecc;
U8 stat, tmp[7];
NFChipEn(); //
WrNFCmd(PROGCMD0); //page program 命令
WrNFAddr(0); //
WrNFAddr(0); //
WrNFAddr(addr); //
WrNFAddr(addr>>8); //要寫入的page地址
InitEcc(); //reset mecc and secc
MEccUnlock(); //unlock main data area ecc generation
for(i=0; i<512; i++) //具體要寫入頁的數(shù)據(jù)寫入main data area
WrNFDat(buf); //將數(shù)據(jù)輸入NAND FLASH的data register中
//或者可以理解為寫入page的緩沖區(qū)
//只有在發(fā)送確認(rèn)命令0x10之后,該內(nèi)容才被寫入物理存儲單元。
MEccLock(); //unlock it
mecc = RdNFMEcc(); //mecc賦值等于MAIN DATA AREA ECC0 STATUS ERGISTER的內(nèi)容
tmp[0] = mecc&0xff; //[7:0]
tmp[1] = (mecc>>8)&0xff;//[15:8]
tmp[2] = (mecc>>16)&0xff;//[23:16]
tmp[3] = (mecc>>24)&0xff;//[31:24]
tmp[5] = 0xff; //mark good block
//WrNFDat(0xff); //2048,壞塊標(biāo)志//此時(shí)主數(shù)據(jù)區(qū)已經(jīng)lock了。如果不等于0xff就說明是壞塊
//sumsung規(guī)定在block第一和第二個(gè)page的spare area的第一個(gè)字節(jié),如果不等于0xff就說明是壞塊。
SEccUnlock(); //校驗(yàn)碼寫入spare data area
WrNFDat(0xff); //改到這里來運(yùn)行也一樣,應(yīng)該是沒做壞塊的判斷吧?
WrNFDat(tmp[0]);//ECC校驗(yàn)碼
WrNFDat(tmp[1]);
WrNFDat(tmp[2]);
WrNFDat(tmp[3]);//同上,也在頁緩沖區(qū)
SEccLock();
WrNFCmd(PROGCMD1); //確認(rèn)命令,將以上數(shù)據(jù)寫入物理存儲器
stat = WaitNFBusy();
NFChipDs();
return ~stat;
}
/*------------------------------------------------------------/
函數(shù)名稱: nandMain
功能描述: 入口函數(shù)
傳 參: 無
返 回 值: 無
-------------------------------------------------------------*/
void nandMain(void)
{
U16 ID,i;
U8 buf[512];
U32 NFBlockNO=6;
U32 NFPagesNO = 25; //block6,page25
U32 status;
U32 BlockPages;
BlockPages =(NFBlockNO<<6)+NFPagesNO; //BlockPages=000110011001
//左移6位是因?yàn)?Block=64Page
//因此block6的起始地址位:6*64=6<<6
Uart_Init(115200);
Uart_Printf("\nthe main is running\n");
InitNandCfg(); //初始化函數(shù)
ID=ReadChipId(); //ID=ECf1 ;;ID=ecda
Uart_Printf("\nnand flash`s ID is:%x\n",ID);
if(EraseBlock(BlockPages)&0x1==TRUE)
{
Uart_Printf("\nblock %d is erased\n",NFBlockNO);
ReadPage(BlockPages,buf); //讀page中的內(nèi)容
Uart_Printf("\n/***********************擦除之后flash中的數(shù)據(jù)****************/\n");
for(i=0; i<512; i++)
Uart_Printf("%4x", buf);
Uart_Printf("\n/***********************應(yīng)寫入數(shù)據(jù)****************/\n"); |
|