uboot-step 13 NandFlash 做硬盤(pán)

uboot-step 13 NandFlash 做硬盤(pán)

  • NandFlash 簡(jiǎn)介
    • 內(nèi)部結(jié)構(gòu)
    • 編址方式
    • 信號(hào)引腳
    • 命令設(shè)置
  • S3c6410 NCONF
  • 代碼實(shí)現(xiàn)
  • 參考鏈接

NandFlash 簡(jiǎn)介

對(duì)于嵌入式設(shè)備來(lái)說(shuō)袍榆,NandFlash就相當(dāng)于電腦中硬盤(pán)的作用古瓤,我們的代碼和數(shù)據(jù)都存儲(chǔ)在上面葱轩。

分類
  • SLC (Single level cell): 單層式存儲(chǔ) 每個(gè)存儲(chǔ)單元存一位數(shù)據(jù)

  • MLC (multi level cell): 多層式存儲(chǔ) 每個(gè)存儲(chǔ)單元存兩位數(shù)據(jù)

    |分類|價(jià)格|壽命|速度|功耗|
    |---|---|---|---|
    |SLC|高|10萬(wàn)|快3倍|低|
    |MLC|低|1萬(wàn)|慢|高15%|

內(nèi)部結(jié)構(gòu)

NandFlash分為塊(Block)和頁(yè)(Pages)宴树,如下圖:


nand.png

上圖是開(kāi)發(fā)板所采用的Flash芯片的datasheet里面的框圖,總共大小為256M
每頁(yè)分為main區(qū)和spare區(qū)额各,main去用來(lái)存保存的數(shù)據(jù)国觉,spare存儲(chǔ)一些附加信息,比如壞塊的標(biāo)記臊泰,ECC校驗(yàn)和等蛉加,此處所用的Nandflash的main區(qū)有2K大小蚜枢,還有64個(gè)Bytes的spare區(qū)缸逃,每塊有64頁(yè),共有128KPages厂抽,總共有256MByte的存儲(chǔ)空間

編址方式

與內(nèi)存的編址方式不同需频,NandFlash的編址方式為獨(dú)立編址,內(nèi)存屬于統(tǒng)一編址筷凤,占據(jù)了cpu的地址空間昭殉,而NandFlash有自己的地址空間苞七,并不占用CPU的地址空間。NandFlash的地址分為行地址與列地址挪丢,行地址即為頁(yè)地址蹂风,列地址為頁(yè)內(nèi)偏移。下面是尋址所用的周期數(shù)乾蓬,前兩個(gè)周期發(fā)送列地址惠啄,后三個(gè)周期發(fā)送行地址,總共需要5個(gè)周期發(fā)送地址任内。


addr.png
信號(hào)引腳
pin.png

引腳如上圖所示撵渡,NandFlash總共有IO0~IO7八個(gè)IO口,數(shù)據(jù)死嗦,命令趋距,和地址都需要這8個(gè)IO口來(lái)進(jìn)行傳輸

  • CLE,ALE :命令越除,地址使能引腳节腐,代表當(dāng)前傳輸?shù)臄?shù)據(jù)是地址還是命令
  • CE,RE摘盆,WE :片選铜跑,讀寫(xiě)使能引腳,低有效
  • WP骡澈,R/B: 保護(hù)使能引腳锅纺,準(zhǔn)備、忙狀態(tài)引腳肋殴,可以得知NandFlash的工作狀態(tài)
命令設(shè)置
command.png
NandFlash使用流程 讀囤锉,寫(xiě),擦除
write.png

read.png

S3C6410 NandFlash Controler

6410.png

如上圖护锤,為S3C6410的Nand Flash Controller 與NandFlash的接口框圖官地,將對(duì)應(yīng)的引腳與NandFlash進(jìn)行連接
使用之前,首先要對(duì)相關(guān)的寄存器進(jìn)行配置烙懦,圈出來(lái)的是常用的驱入,剩下的是與ECC校驗(yàn)相關(guān)的寄存器相關(guān)的寄存器如下:


register.png
配置寄存器: 這里主要設(shè)置TACLS,TWRPH0氯析,TWRPH1 時(shí)序參數(shù)和ECC配置
NFCONF.png
控制寄存器: 使能,片選等控制信號(hào)
control.png
地址寄存器亏较,數(shù)據(jù)寄存器,命令寄存器
misc.png
狀態(tài)寄存器:主要是看NANDFlash狀態(tài)是繁忙還是已準(zhǔn)備好
stat.png

代碼實(shí)現(xiàn)

前面我們代碼搬移的時(shí)候是從steppingstone中搬移到內(nèi)存中的掩缓,實(shí)際上正確的應(yīng)該是從NandFlash 中搬移到內(nèi)存中雪情,因此需要重寫(xiě)代碼搬移的函數(shù),在代碼搬移之前你辣,需要先進(jìn)行NandFlash的初始化巡通。
下面是NandFlash簡(jiǎn)單驅(qū)動(dòng)文件nand.c,沒(méi)有進(jìn)行ECC校驗(yàn)尘执,無(wú)法保證數(shù)據(jù)正確

/*
tiny6410用的nandflash為 一頁(yè)2K
*/


#define NFCONF             (*((volatile unsigned long*)0x70200000))
#define NFCONT             (*((volatile unsigned long*)0x70200004))
#define NFCMMD             (*((volatile unsigned char*)0x70200008))
#define NFSTAT             (*((volatile unsigned char*)0x70200028))
#define NFADDR             (*((volatile unsigned char*)0x7020000c))
#define NFDATA             (*((volatile unsigned char*)0x70200010))

void select_ship(void)
{
NFCONT &= ~(1<<1);  //CE引腳接到了ncs[2] 這個(gè)引腳上
}

void delselect_ship(void)
{
    NFCONT |= (1<<1); //CE
}

void clean_RnB()
{
    NFSTAT |= (1<<4);
} 
void nand_cmd(unsigned char cmd)
{
    NFCMMD = cmd;   
}

void wait_RnB(void)
{
    while(!(NFSTAT & 0x1));
}

void nand_addr(unsigned char addr)
{
    NFADDR = addr;
}

void nand_reset(void)
{
    /* 選中 */
    select_ship();

    /* 清除RnB */
    clean_RnB();
        
    /* 發(fā)出復(fù)位信號(hào) */
    nand_cmd(0xff);

    /* 等待就緒 */
    wait_RnB();

    /* 取消選中 */
    delselect_ship();
}

void nand_init(void)
{ 


    /* 設(shè)置時(shí)間參數(shù) */
#define TACLS  7
#define TWRPH0 7
#define TWRPH1 7
    
    NFCONF &= ~((7<<12)|(7<<8)|(7<<4));
    NFCONF |= (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

    /* 使能 nandflash controller*/
    NFCONT = 1 | (1<<1);



/* 復(fù)位 */
nand_reset();
}

void NF_PageRead(unsigned long addr,unsigned char* buff)
{
    int i;


    /* 選中芯片 */
    select_ship();
    
    /* 清除RnB */
    clean_RnB();

    /* 發(fā)出命令0x00 */
     nand_cmd(0x00);
    
     /* 發(fā)出列地址 */
    nand_addr(0x00);
    nand_addr(0x00);

    /* 發(fā)出行地址 */
nand_addr(addr&0xff);
nand_addr((addr >>8 ) & (0xff));
nand_addr((addr >>16 ) & (0xff));
    
/* 發(fā)出命令0x30 */
 nand_cmd(0x30);
    
/* 等待就緒 */
 wait_RnB();
    
/* 讀數(shù)據(jù) */
 for(i = 0; i<1024*2; i++)
{
    *buff++ = NFDATA;
}
    
  
 /* 取消片選 */
 
 delselect_ship();
 
}


void nand_to_ram(unsigned long start_addr,unsigned char* sdram_addr,int size)
{
    int i;
        
for( i=(start_addr >>11); size>0;)
{
    NF_PageRead(i,sdram_addr);  
    size -= 2048;
    sdram_addr += 2048;
    i++;
}
    
}


int NF_Erase(unsigned long addr)
{
int ret;

//選中flash芯片
select_ship();

//清除RnB
clean_RnB();

//發(fā)送命令60
nand_cmd(0x60);

//發(fā)送行地址(3個(gè)周期)
nand_addr(addr&0xff);
    nand_addr((addr >>8 ) & (0xff));
    nand_addr((addr >>16 ) & (0xff));

//發(fā)送命令D0
nand_cmd(0xD0);

//等待RnB
wait_RnB();

//發(fā)送命令70
nand_cmd(0x70);

//讀取擦除結(jié)果
ret = NFDATA;

//取消選中flash芯片
delselect_ship();

return ret;
}

int NF_WritePage(unsigned long addr,unsigned char* buff)
{
    int ret,i;

    //選中flash芯片
    select_ship();

    //清除RnB
    clean_RnB();

    //發(fā)送命令80
    nand_cmd(0x80);

    //發(fā)送列地址(2個(gè)周期)
    nand_addr(0x00);
        nand_addr(0x00);
    
    //發(fā)送行地址(3個(gè)周期)
    nand_addr(addr&0xff);
    nand_addr((addr >>8 ) & (0xff));
    nand_addr((addr >>16 ) & (0xff));

//寫(xiě)入數(shù)據(jù)
    for(i=0;i<1024*2;i++)
    {
        NFDATA = buff[i];   
    }

//發(fā)送命令10
nand_cmd(0x10);

//等待RnB
wait_RnB();

//發(fā)送命令70
nand_cmd(0x70);

//讀取寫(xiě)入結(jié)果
ret = NFDATA;

//取消選中flash芯片
delselect_ship();

return ret;
}

由于以前是從steppingstone中搬移代碼到內(nèi)存,現(xiàn)在更改為從flash中宴凉,新改的start.s文件如下誊锭,只有改動(dòng)部分

reset:
    bl set_svc
    bl set_peri_port
    bl disable_watchdog
    bl disable_interrupt
    bl disable_mmu
    bl init_clock
    bl mem_init
    bl init_stack  //由于要跳轉(zhuǎn)到c語(yǔ)言中運(yùn)行,先要設(shè)置堆棧弥锄,進(jìn)行堆棧初始化
    bl nand_init  //copy 到內(nèi)存之前炉旷,要先進(jìn)行flash的初始化

    bl copy_to_ram //跳轉(zhuǎn)到去拷貝代碼
    bl clean_bss
    ldr pc, =gboot_main


copy_to_ram:
    mov r0,#0 
    ldr r1,=_start
    ldr r2,=bss_end

    sub r2,r2,r1
    mov ip,lr        //調(diào)用之前先保存當(dāng)前的lr指針,后面要恢復(fù)的 ip寄存器是r12寄存器
    bl nand_to_ram  //這里牽扯到匯編調(diào)用c函數(shù)的參數(shù)傳遞叉讥,r0窘行,r1,r2,分別為函數(shù)的第1,2,3個(gè)參數(shù),正好對(duì)應(yīng)讀flash函數(shù)的flash開(kāi)始地址r0=0图仓,目標(biāo)地址r1=0x50008000和復(fù)制大小r2=bss_end - _start=整個(gè)代碼的大小   
    mov lr,ip


    mov pc,lr



init_stack:
    msr cpsr_c, #0xd2
    ldr sp, =0x53000000 //初始化r13_irq
    msr cpsr_c, #0xd3
    ldr sp, =0x54000000  //初始化R13_svc
    mov pc ,lr

下面是主程序罐盔,main.c 首先寫(xiě)入了一些數(shù)據(jù),然后讀出來(lái)判斷數(shù)據(jù)是否正確

unsigned char buf[1024*2];
#ifdef MMU_ON
    mmu_init();
#endif
    
led_init();
button_init();
init_irq();
 
led_off();

NF_Erase(128*1+1);
buf[0] = 100;
NF_WritePage(128*1+1,buf);

buf[0] = 10;
NF_PageRead(128*1+1,buf);

if( buf[0] == 100 )
    led_on();
    
while(1);

return 0;

此去經(jīng)年
zhaiyk@sina.cn
August 11, 2016

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末救崔,一起剝皮案震驚了整個(gè)濱河市惶看,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌六孵,老刑警劉巖纬黎,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異劫窒,居然都是意外死亡本今,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門主巍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)冠息,“玉大人,你說(shuō)我怎么就攤上這事孕索」浼瑁” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵搞旭,是天一觀的道長(zhǎng)散怖。 經(jīng)常有香客問(wèn)我,道長(zhǎng)肄渗,這世上最難降的妖魔是什么镇眷? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮恳啥,結(jié)果婚禮上偏灿,老公的妹妹穿的比我還像新娘丹诀。我一直安慰自己钝的,他們只是感情好翁垂,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著硝桩,像睡著了一般沿猜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碗脊,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天啼肩,我揣著相機(jī)與錄音,去河邊找鬼衙伶。 笑死祈坠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的矢劲。 我是一名探鬼主播赦拘,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼芬沉!你這毒婦竟也來(lái)了躺同?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤丸逸,失蹤者是張志新(化名)和其女友劉穎蹋艺,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體黄刚,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捎谨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了憔维。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侍芝。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖埋同,靈堂內(nèi)的尸體忽然破棺而出州叠,到底是詐尸還是另有隱情,我是刑警寧澤凶赁,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布咧栗,位于F島的核電站,受9級(jí)特大地震影響虱肄,放射性物質(zhì)發(fā)生泄漏致板。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一咏窿、第九天 我趴在偏房一處隱蔽的房頂上張望斟或。 院中可真熱鬧,春花似錦集嵌、人聲如沸萝挤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)怜珍。三九已至端蛆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間酥泛,已是汗流浹背今豆。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留柔袁,地道東北人呆躲。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捶索,于是被迫代替她去往敵國(guó)和親歼秽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容