電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 2228|回復(fù): 0
收起左側(cè)

達(dá)內(nèi)嵌入式培訓(xùn)視頻教程_嵌入式Linux開發(fā)環(huán)境的搭建之:U-Boot移植

[復(fù)制鏈接]

2607

主題

2607

帖子

7472

積分

高級會員

Rank: 5Rank: 5

積分
7472
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2020-8-13 11:27:31 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
達(dá)內(nèi)嵌入式培訓(xùn)視頻教程_嵌入式Linux開發(fā)環(huán)境的搭建之:U-Boot移植,   



5.2U-Boot移植5.2.1Bootloader介紹1.概念

簡單地說,Bootloader就是在操作系統(tǒng)內(nèi)核運行之前運行的一段程序,它類似于PC機中的BIOS程序。通過這段程序,可以完成硬件設(shè)備的初始化,并建立內(nèi)存空間的映射關(guān)系,從而將系統(tǒng)的軟硬件環(huán)境帶到一個合適的狀態(tài),為最終加載系統(tǒng)內(nèi)核做好準(zhǔn)備。



通常,Bootloader比較依賴于硬件平臺,特別是在嵌入式系統(tǒng)中,更為如此。因此,在嵌入式世界里建立一個通用的Bootloader是一件比較困難的事情。盡管如此,仍然可以對Bootloader歸納出一些通用的概念來指導(dǎo)面向用戶定制的Bootloader設(shè)計與實現(xiàn)。



(1)Bootloader所支持的CPU和嵌入式開發(fā)板。

每種不同的CPU體系結(jié)構(gòu)都有不同的Bootloader。有些Bootloader也支持多種體系結(jié)構(gòu)的CPU,如后面要介紹的U-Boot支持ARM、MIPS、PowerPC等眾多體系結(jié)構(gòu)。除了依賴于CPU的體系結(jié)構(gòu)外,Bootloader實際上也依賴于具體的嵌入式板級設(shè)備的配置。



(2)Bootloader的存儲位置。

系統(tǒng)加電或復(fù)位后,所有的CPU通常都從某個由CPU制造商預(yù)先安排的地址上取指令。而基于CPU構(gòu)建的嵌入式系統(tǒng)通常都有某種類型的固態(tài)存儲設(shè)備(比如ROM、EEPROM或Flash等)被映射到這個預(yù)先安排的地址上。因此在系統(tǒng)加電后,CPU將首先執(zhí)行Bootloader程序。



(3)Bootloader的啟動過程分為單階段和多階段兩種。通常多階段的Bootloader能提供更為復(fù)雜的功能,以及更好的可移植性。



(4)Bootloader的操作模式。大多數(shù)Bootloader都包含兩種不同的操作模式:“啟動加載”模式和“下載”模式,這種區(qū)別僅對于開發(fā)人員才有意義。



n 啟動加載模式:這種模式也稱為“自主”模式。也就是Bootloader從目標(biāo)機上的某個固態(tài)存儲設(shè)備上將操作系統(tǒng)加載到RAM中運行,整個過程并沒有用戶的介入。這種模式是嵌入式產(chǎn)品發(fā)布時的通用模式。



n 下載模式:在這種模式下,目標(biāo)機上的Bootloader將通過串口連接或網(wǎng)絡(luò)連接等通信手段從主機(Host)下載文件,比如:下載內(nèi)核映像和根文件系統(tǒng)映像等。從主機下載的文件通常首先被Bootloader保存到目標(biāo)機的RAM中,然后再被Bootloader寫入到目標(biāo)機上的Flash類固態(tài)存儲設(shè)備中。Bootloader的這種模式在系統(tǒng)更新時使用。工作于這種模式下的Bootloader通常都會向它的終端用戶提供一個簡單的命令行接口。



(5)Bootloader與主機之間進(jìn)行文件傳輸所用的通信設(shè)備及協(xié)議,最常見的情況就是,目標(biāo)機上的Bootloader通過串口與主機之間進(jìn)行文件傳輸,傳輸協(xié)議通常是xmodem/ymodem/zmodem等。但是,串口傳輸?shù)乃俣仁怯邢薜,因此通過以太網(wǎng)連接并借助TFTP等協(xié)議來下載文件是個更好的選擇。

2.Bootloader啟動流程

Bootloader的啟動流程一般分為兩個階段:stage1和stage2,下面分別對這兩個階段進(jìn)行講解。



(1)Bootloader的stage1。

在stage1中Bootloader主要完成以下工作。

n 基本的硬件初始化,包括屏蔽所有的中斷、設(shè)置CPU的速度和時鐘頻率、RAM初始化、初始化外圍設(shè)備、關(guān)閉CPU內(nèi)部指令和數(shù)據(jù)cache等。

n 為加載stage2準(zhǔn)備RAM空間,通常為了獲得更快的執(zhí)行速度,通常把stage2加載到RAM空間中來執(zhí)行,因此必須為加載Bootloader的stage2準(zhǔn)備好一段可用的RAM空間。

n 復(fù)制stage2到RAM中,在這里要確定兩點:①stage2的可執(zhí)行映像在固態(tài)存儲設(shè)備的存放起始地址和終止地址;②RAM空間的起始地址。

n 設(shè)置堆棧指針sp,這是為執(zhí)行stage2的C語言代碼做好準(zhǔn)備。



(2)Bootloader的stage2。

在stage2中Bootloader主要完成以下工作。

n 用匯編語言跳轉(zhuǎn)到main入口函數(shù)。

由于stage2的代碼通常用C語言來實現(xiàn),目的是實現(xiàn)更復(fù)雜的功能和取得更好的代碼可讀性和可移植性。但是與普通C語言應(yīng)用程序不同的是,在編譯和鏈接Bootloader這樣的程序時,不能使用glibc庫中的任何支持函數(shù)。

n 初始化本階段要使用到的硬件設(shè)備,包括初始化串口、初始化計時器等。在初始化這些設(shè)備之前可以輸出一些打印信息。

n 檢測系統(tǒng)的內(nèi)存映射,所謂內(nèi)存映射就是指在整個4GB物理地址空間中指出哪些地址范圍被分配用來尋址系統(tǒng)的內(nèi)存。

n 加載內(nèi)核映像和根文件系統(tǒng)映像,這里包括規(guī)劃內(nèi)存占用的布局和從Flash上復(fù)制數(shù)據(jù)。

n 設(shè)置內(nèi)核的啟動參數(shù)。

5.2.2U-Boot概述1.U-Boot簡介

U-Boot(UniversalBootloader)是遵循GPL條款的開放源碼項目。它是從FADSROM、8xxROM、PPCBOOT逐步發(fā)展演化而來。其源碼目錄、編譯形式與Linux內(nèi)核很相似,事實上,不少U-Boot源碼就是相應(yīng)的Linux內(nèi)核源程序的簡化,尤其是一些設(shè)備的驅(qū)動程序,這從U-Boot源碼的注釋中能體現(xiàn)這一點。但是U-Boot不僅僅支持嵌入式Linux系統(tǒng)的引導(dǎo),而且還支持NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS等嵌入式操作系統(tǒng)。其目前要支持的目標(biāo)操作系統(tǒng)是OpenBSD、NetBSD、FreeBSD、4.4BSD、Linux、SVR4、Esix、Solaris、Irix、SCO、Dell、NCR、VxWorks、LynxOS、pSOS、QNX、RTEMS、ARTOS。這是U-Boot中Universal的一層含義,另外一層含義則是U-Boot除了支持PowerPC系列的處理器外,還能支持MIPS、x86、ARM、NIOS、XScale等諸多常用系列的處理器。這兩個特點正是U-Boot項目的開發(fā)目標(biāo),即支持盡可能多的嵌入式處理器和嵌入式操作系統(tǒng)。就目前為止,U-Boot對PowerPC系列處理器支持最為豐富,對Linux的支持最完善。

2.U-Boot特點

U-Boot的特點如下。

n 開放源碼;

n 支持多種嵌入式操作系統(tǒng)內(nèi)核,如Linux、NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS;

n 支持多個處理器系列,如PowerPC、ARM、x86、MIPS、XScale;

n 較高的可靠性和穩(wěn)定性;

n 高度靈活的功能設(shè)置,適合U-Boot調(diào)試、操作系統(tǒng)不同引導(dǎo)要求和產(chǎn)品發(fā)布等;

n 豐富的設(shè)備驅(qū)動源碼,如串口、以太網(wǎng)、SDRAM、Flash、LCD、NVRAM、EEPROM、RTC、鍵盤等;

n 較為豐富的開發(fā)調(diào)試文檔與強大的網(wǎng)絡(luò)技術(shù)支持。

3.U-Boot主要功能

U-Boot可支持的主要功能列表。

n 系統(tǒng)引導(dǎo):支持NFS掛載、RAMDISK(壓縮或非壓縮)形式的根文件系統(tǒng)。支持NFS掛載,并從Flash中引導(dǎo)壓縮或非壓縮系統(tǒng)內(nèi)核。

n 基本輔助功能:強大的操作系統(tǒng)接口功能;可靈活設(shè)置、傳遞多個關(guān)鍵參數(shù)給操作系統(tǒng),適合系統(tǒng)在不同開發(fā)階段的調(diào)試要求與產(chǎn)品發(fā)布,尤其對Linux支持最為強勁;支持目標(biāo)板環(huán)境參數(shù)多種存儲方式,如Flash、NVRAM、EEPROM;CRC32校驗,可校驗Flash中內(nèi)核、RAMDISK映像文件是否完好。

n 設(shè)備驅(qū)動:串口、SDRAM、Flash、以太網(wǎng)、LCD、NVRAM、EEPROM、鍵盤、USB、PCMCIA、PCI、RTC等驅(qū)動支持。

n 上電自檢功能:SDRAM、Flash大小自動檢測;SDRAM故障檢測;CPU型號。

n 特殊功能:XIP內(nèi)核引導(dǎo)。

5.2.3U-Boot源碼導(dǎo)讀1.U-Boot源碼結(jié)構(gòu)

U-Boot源碼結(jié)構(gòu)如圖5.27所示。

  

圖5.27U-Boot源碼結(jié)構(gòu)



n board:和一些已有開發(fā)板有關(guān)的代碼,比如makefile和U-Boot.lds等都和具體開發(fā)板的硬件和地址分配有關(guān)。

n common:與體系結(jié)構(gòu)無關(guān)的代碼,用來實現(xiàn)各種命令的C程序。

n cpu:包含CPU相關(guān)代碼,其中的子目錄都是以U-BOOT所支持的CPU為名,比如有子目錄arm926ejs、mips、mpc8260和nios等,每個特定的子目錄中都包括cpu.c和interrupt.c,start.S等。其中cpu.c初始化CPU、設(shè)置指令Cache和數(shù)據(jù)Cache等;interrupt.c設(shè)置系統(tǒng)的各種中斷和異常,比如快速中斷、開關(guān)中斷、時鐘中斷、軟件中斷、預(yù)取中止和未定義指令等;匯編代碼文件start.S是U-BOOT啟動時執(zhí)行的第一個文件,它主要是設(shè)置系統(tǒng)堆棧和工作方式,為進(jìn)入C程序奠定基礎(chǔ)。



n disk:disk驅(qū)動的分區(qū)相關(guān)代碼。

n doc:文檔。

n drivers:通用設(shè)備驅(qū)動程序,比如各種網(wǎng)卡、支持CFI的Flash、串口和USB總線等。

n fs:支持文件系統(tǒng)的文件,U-BOOT現(xiàn)在支持cramfs、fat、fdos、jffs2和registerfs等。

n include:頭文件,還有對各種硬件平臺支持的匯編文件,系統(tǒng)的配置文件和對文件系統(tǒng)支持的文件。

n net:與網(wǎng)絡(luò)有關(guān)的代碼,BOOTP協(xié)議、TFTP協(xié)議、RARP協(xié)議和NFS文件系統(tǒng)的實現(xiàn)。

n lib_arm:與ARM體系結(jié)構(gòu)相關(guān)的代碼。

n tools:創(chuàng)建S-Record格式文件和U-BOOTimages的工具。

2.U-Boot重要代碼

(1)cpu/arm920t/start.S

這是U-Boot的起始位置。在這個文件中設(shè)置了處理器的狀態(tài)、初始化中斷向量和內(nèi)存時序等,從Flash中跳轉(zhuǎn)到定位好的內(nèi)存位置執(zhí)行。

.globl_start(起始位置:中斷向量設(shè)置)

_start:breset

ldrpc,_undefined_instruction

ldrpc,_software_interrupt

ldrpc,_prefetch_abort

ldrpc,_data_abort

ldrpc,_not_used

ldrpc,_irq

ldrpc,_fiq



_undefined_instruction:.wordundefined_instruction

_software_interrupt:.wordsoftware_interrupt

_prefetch_abort:.wordprefetch_abort

_data_abort:.worddata_abort

_not_used:.wordnot_used

_irq:.wordirq

_fiq:.wordfiq



_TEXT_BASE:(代碼段起始位置)

.wordTEXT_BASE



.globl_armboot_start

_armboot_start:

.word_start



/*

*Thesearedefinedintheboard-specificlinkerscript.

*/

.globl_bss_start(BSS段起始位置)

_bss_start:

.word__bss_start



.globl_bss_end

_bss_end:

.word_end

reset:(執(zhí)行入口)

/*

*setthecputoSVC32mode;使處理器進(jìn)入特權(quán)模式

*/

mrsr0,cpsr

bicr0,r0,#0x1f

orrr0,r0,#0xd3

msrcpsr,r0

relocate:(代碼的重置)/*relocateU-BoottoRAM*/

adrr0,_start/*r0<-currentpositionofcode*/

ldrr1,_TEXT_BASE/*testifwerunfromflashorRAM*/

cmpr0,r1/*don\“trelocduringdebug*/

beqstack_setup



ldrr2,_armboot_start

ldrr3,_bss_start

subr2,r3,r2/*r2<-sizeofarmboot*/

addr2,r0,r2/*r2<-sourceendaddress*/



copy_loop:(拷貝過程)

ldmiar0!,{r3-r10}/*copyfromsourceaddress[r0]*/

stmiar1!,{r3-r10}/*copytotargetaddress[r1]*/

cmpr0,r2/*untilsourceendaddreee[r2]*/

blecopy_loop



/*Setupthestack;設(shè)置堆棧*/

stack_setup:

ldrr0,_TEXT_BASE/*upper128KiB:relocateduboot*/

subr0,r0,#CFG_MALLOC_LEN/*mallocarea*/

subr0,r0,#CFG_GBL_DATA_SIZE/*bdinfo*/



clear_bss:(清空BSS段)

ldrr0,_bss_start/*findstartofbsssegment*/

ldrr1,_bss_end/*stophere*/

movr2,#0x00000000/*clear*/



clbss_l:strr2,[r0]/*clearloop...*/

addr0,r0,#4

cmpr0,r1

bneclbss_l

ldrpc,_start_armboot



_start_armboot:.wordstart_armboot



(2)interrupts.c

這個文件是處理中斷的,如打開和關(guān)閉中斷等。



#ifdefCONFIG_USE_IRQ

/*enableIRQinterrupts;中斷使能函數(shù)*/

voidenable_interrupts(void)

{

unsignedlongtemp;

__asm____volatile__(“mrs%0,cpsrn“

“bic%0,%0,#0x80n“

“msrcpsr_c,%0“

:“=r“(temp)

:

:“memory“);

}



/*

*disableIRQ/FIQinterrupts;中斷屏蔽函數(shù)

*returnstrueifinterruptshadbeenenabledbeforewedisabledthem

*/

intdisable_interrupts(void)

{

unsignedlongold,temp;

__asm____volatile__(“mrs%0,cpsrn“

“orr%1,%0,#0xc0n“

“msrcpsr_c,%1“

:“=r“(old),“=r“(temp)

:

:“memory“);

return(old&0x80)==0;

}

#endif

voidshow_regs(structpt_regs*regs)

{

unsignedlongflags;

constchar*processor_modes[]={

“USER_26“,“FIQ_26“,“IRQ_26“,“SVC_26“,

“UK4_26“,“UK5_26“,“UK6_26“,“UK7_26“,

“UK8_26“,“UK9_26“,“UK10_26“,“UK11_26“,

“UK12_26“,“UK13_26“,“UK14_26“,“UK15_26“,

“USER_32“,“FIQ_32“,“IRQ_32“,“SVC_32“,

“UK4_32“,“UK5_32“,“UK6_32“,“ABT_32“,

“UK8_32“,“UK9_32“,“UK10_32“,“UND_32“,

“UK12_32“,“UK13_32“,“UK14_32“,“SYS_32“,

};



}

/*在U-Boot啟動模式下,在原則上要禁止中斷處理,所以如果發(fā)生中斷,當(dāng)作出錯處理*/

voiddo_fiq(structpt_regs*pt_regs)

{

printf(“fastinterruptrequestn“);

show_regs(pt_regs);

bad_mode();

}



voiddo_irq(structpt_regs*pt_regs)

{

printf(“interruptrequestn“);

show_regs(pt_regs);

bad_mode();

}



(3)cpu.c

這個文件是對處理器進(jìn)行操作,如下所示:



intcpu_init(void)

{

/*

*setupupstacksifnecessary;設(shè)置需要的堆棧

*/

#ifdefCONFIG_USE_IRQ

DECLARE_GLOBAL_DATA_PTR;



IRQ_STACK_START=_armboot_start-CFG_MALLOC_LEN-CFG_GBL_DATA_SIZE-4;

FIQ_STACK_START=IRQ_STACK_START-CONFIG_STACKSIZE_IRQ;

#endif

return0;

}

intcleanup_before_linux(void)/*準(zhǔn)備加載linux*/

{

/*

*thisfunctioniscalledjustbeforewecalllinux

*itpreparestheprocessorforlinux

*

*weturnoffcachesetc...

*/

unsignedlongi;

disable_interrupts();



/*turnoffI/D-cache:關(guān)閉cache*/

asm(“mrcp15,0,%0,c1,c0,0“:“=r“(i));

i&=~(C1_DC|C1_IC);

asm(“mcrp15,0,%0,c1,c0,0“::“r“(i));



/*flushI/D-cache*/

i=0;

asm(“mcrp15,0,%0,c7,c7,0“::“r“(i));

return(0);

}



OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS

{

.=0x00000000;

.=ALIGN(4);

.text:

{

cpu/arm920t/start.o(.text)

*(.text)

}



.=ALIGN(4);

.rodata:{*(.rodata)}



.=ALIGN(4);

.data:{*(.data)}



.=ALIGN(4);

.got:{*(.got)}



__u_boot_cmd_start=.;

.u_boot_cmd:{*(.u_boot_cmd)}

__u_boot_cmd_end=.;



.=ALIGN(4);

__bss_start=.;

.bss:{*(.bss)}

_end=.;

}



(4)memsetup.S

這個文件是用于配置開發(fā)板參數(shù)的,如下所示:



/*memsetup.c*/

/*memorycontrolconfiguration*/

/*maker0relativethecurrentlocationsothatit*/

/*readsSMRDATAoutofFLASHratherthanmemory!*/

ldrr0,=SMRDATA

ldrr1,_TEXT_BASE

subr0,r0,r1

ldrr1,=BWSCON /*BusWidthStatusController*/

addr2,r0,#52

0:

ldrr3,[r0],#4

strr3,[r1],#4

cmpr2,r0

bne0b



/*everythingisfinenow*/

movpc,lr



.ltorg

5.2.4U-Boot移植主要步驟

(1)建立自己的開發(fā)板類型。

閱讀makefile文件,在makefile文件中添加兩行,如下所示:



fs2410_config:unconfig

@./mkconfig$(@:_config=)armarm920tfs2410



其中“arm”為表示處理器體系結(jié)構(gòu)的種類,“arm920t”表示處理器體系結(jié)構(gòu)的名稱,“fs2410”為主板名稱。



在board目錄中建立fs2410目錄,并將smdk2410目錄中的內(nèi)容(cp–asmdk2410/*fs2410)復(fù)制到該目錄中。



n 在include/configs/目錄下將smdk2410.h復(fù)制到(cpsmdk2410.hfs2410.h)。

n 修改ARM編譯器的目錄名及前綴(都要改成以“fs2410”開頭)。

n 完成之后,可以測試配置。



$makefs2410_config;make



(2)修改程序鏈接地址。

在board/s3c2410中有一個config.mk文件,它是用于設(shè)置程序鏈接的起始地址,因為會在U-Boot中增加功能,所以留下6MB的空間,修改33F80000為33A00000。

為了以后能用U-Boot的“go”命令執(zhí)行修改過的用loadb或tftp下載的U-Boot,需要在board/s3c2410的memsetup.S中標(biāo)記符”0:”上加入5句:



movr3,pc

ldrr4,=0x3FFF0000

andr3,r3,r4(以上3句得到實際代碼啟動的內(nèi)存地址)

aadr0,r0,r3(用go命令調(diào)試u-boot時,啟動地址在RAM)

addr2,r2,r3(把初始化內(nèi)存信息的地址,加上實際啟動地址)



(3)將中斷禁止的部分應(yīng)該改為如下所示(/cpu/arm920t/start.S):



#ifdefined(CONFIG_S3C2410)

ldrr1,=0x7ff

ldrr0,=INTSUBMSK

strr1,[r0]

#endif



(4)因為在fs2410開發(fā)板啟動時是直接從NandFlash加載代碼,所以啟動代碼應(yīng)該改成如下所示(/cpu/arm920t/start.S):



#ifdefCONFIG_S3C2410_NAND_BOOT@START

@resetNAND北京理工嵌入式, 嵌入式比賽心得體會, 嵌入式硬盤錄像機價格, 嵌入式計算器系統(tǒng), 嵌入式irq實驗, 個人嵌入式風(fēng)險防控, 嵌入式硬盤啟動, 嵌入式養(yǎng)老床位最低, 嵌入式前后臺軟件系統(tǒng), 嵌入式dvr拆機, 嵌入式機構(gòu)培訓(xùn), 嵌入式直拉手, 廣東嵌入式壓濾機, 嵌入式項目接包, 嵌入式學(xué)到了什么, 車輛座椅嵌入式系統(tǒng), 嵌入式軟件電源, 軟件嵌入式外包, 嵌入式的衍生工具, 接入式和嵌入式, 海同教育嵌入式, 怎么做嵌入式電視,

movr1,#NAND_CTL_BASE

ldrr2,=0xf830@initialvalue

strr2,[r1,#oNFCONF]

ldrr2,[r1,#oNFCONF]

bicr2,r2,#0x800@enablechip

strr2,[r1,#oNFCONF]

movr2,#0xff@RESETcommand

strbr2,[r1,#oNFCMD]

movr3,#0@wait

nand1:

addr3,r3,#0x1

cmpr3,#0xa

bltnand1

nand2:

ldrr2,[r1,#oNFSTAT]@waitready

tstr2,#0x1

beqnand2

ldrr2,[r1,#oNFCONF]

orrr2,r2,#0x800@disablechip

strr2,[r1,#oNFCONF]

@getreadtocallCfunctions(fornand_read())

ldrsp,DW_STACK_START@setupstackpointer

movfp,#0@nopreviousframe,sofp=0

@copyU-BoottoRAM

ldrr0,=TEXT_BASE

movr1,#0x0

movr2,#0x20000

blnand_read_ll

tstr0,#0x0

beqok_nand_read

bad_nand_read:

loop2:bloop2@infiniteloop

ok_nand_read:

@verify

movr0,#0

ldrr1,=TEXT_BASE

movr2,#0x400@4bytes*1024=4K-bytes

go_next:

ldrr3,[r0],#4

ldrr4,[r1],#4

teqr3,r4

bnenotmatch

subsr2,r2,#4

beqstack_setup

bnego_next

notmatch:

loop3:bloop3@infiniteloop

#endif@CONFIG_S3C2410_NAND_BOOT@END



在“_start_armboot:.wordstart_armboot”后加入:



.align2

DW_STACK_START:.wordSTACK_BASE+STACK_SIZE-4



(5)修改內(nèi)存配置(board/fs2410/lowlevel_init.S)。



#defineBWSCON0x48000000

#definePLD_BASE0x2C000000

#defineSDRAM_REG0x2C000106



/*BWSCON*/

#defineDW8 (0x0)

#defineDW16(0x1)

#defineDW32(0x2)

#defineWAIT(0x1<<2)

#defineUBLB(0x1<<3)



/*BANKSIZE*/

#defineBURST_EN(0x1<<7)



#defineB1_BWSCON(DW16+WAIT)

#defineB2_BWSCON(DW32)

#defineB3_BWSCON(DW32)

#defineB4_BWSCON(DW16+WAIT+UBLB)

#defineB5_BWSCON(DW8+UBLB)

#defineB6_BWSCON(DW32)

#defineB7_BWSCON(DW32)

/*BANK0CON*/

#defineB0_Tacs0x0/*0clk*/

#defineB0_Tcos0x1/*1clk*/

#defineB0_Tacc0x7/*14clk*/

#defineB0_Tcoh0x0/*0clk*/

#defineB0_Tah0x0/*0clk*/

#defineB0_Tacp0x0/*pagemodeisnotused*/

#defineB0_PMC0x0/*pagemodedisabled*/



/*BANK1CON*/

#defineB1_Tacs0x0/*0clk*/

#defineB1_Tcos0x1/*1clk*/

#defineB1_Tacc0x7/*14clk*/

#defineB1_Tcoh0x0/*0clk*/

#defineB1_Tah0x0/*0clk*/

#defineB1_Tacp0x0/*pagemodeisnotused*/

#defineB1_PMC0x0/*pagemodedisabled*/

……

/*REFRESHparameter*/

#defineREFEN0x1/*Refreshenable*/

#defineTREFMD0x0/*CBR(CASbeforeRAS)/Autorefresh*/

#defineTrp0x0/*2clk*/

#defineTrc0x3/*7clk*/

#defineTchr0x2/*3clk*/

#defineREFCNT1113/*period=15.6us,HCLK=60Mhz,(2048+1-15.6*60)*/

......

.word((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))

.word((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))

.word((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)

.word0x32

.word0x30

.word0x30



(6)加入NandFlash讀函數(shù)(創(chuàng)建board/fs2410/nand_read.c文件)。



#include<config.h>

#define__REGb(x)(*(volatileunsignedchar*)(x))

#define__REGi(x)(*(volatileunsignedint*)(x))

#defineNF_BASE0x4e000000

#defineNFCONF__REGi(NF_BASE+0x0)

#defineNFCMD__REGb(NF_BASE+0x4)

#defineNFADDR__REGb(NF_BASE+0x8)

#defineNFDATA__REGb(NF_BASE+0xc)

#defineNFSTAT__REGb(NF_BASE+0x10)

#defineBUSY1

inlinevoidwait_idle(void)

{

Inti;

while(!(NFSTAT&BUSY))

{

for(i=0;i<10;i++);

}

}



/*lowlevelnandreadfunction*/

intnand_read_ll(unsignedchar*buf,unsignedlongstart_addr,intsize)

{

inti,j;

if((start_addr&NAND_BLOCK_MASK)||(size&NAND_BLOCK_MASK))

{

return-1;/*invalidalignment*/

}

/*chipEnable*/

NFCONF&=~0x800;

for(i=0;i<10;i++);

for(i=start_addr;i<(start_addr+size);)

{

/*READ0*/

NFCMD=0;

/*WriteAddress*/

NFADDR=i&0xff;

NFADDR=(i>>9)&0xff;

NFADDR=(i>>17)&0xff;

NFADDR=(i>>25)&0xff;

wait_idle();

for(j=0;j<NAND_SECTOR_SIZE;j++,i++)

{

*buf=(NFDATA&0xff);

buf++;

}

}

/*chipDisable*/

NFCONF|=0x800;/*chipdisable*/

return0;

}



修改board/fs2410/makefile文件,以增加nand_read()函數(shù)。



OBJS:=fs2410.oflash.onand_read.o



(7)加入NandFlash的初始化函數(shù)(board/fs2410/fs2410.c)。



#if(CONFIG_COMMANDS&CFG_CMD_NAND)

typedefenum

{

NFCE_LOW,

NFCE_HIGH

}NFCE_STATE;

staticinlinevoidNF_Conf(u16conf)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFCONF=conf;

}

staticinlinevoidNF_Cmd(u8cmd)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFCMD=cmd;

}

staticinlinevoidNF_CmdW(u8cmd)

{

NF_Cmd(cmd);

udelay(1);

}

staticinlinevoidNF_Addr(u8addr)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFADDR=addr;

}

staticinlinevoidNF_SetCE(NFCE_STATEs)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

switch(s)

{

caseNFCE_LOW:

nand->NFCONF&=~(1<<11);

break;

caseNFCE_HIGH:

nand->NFCONF|=(1<<11);

break;

}

}

staticinlinevoidNF_WaitRB(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

while(!(nand->NFSTAT&(1<<0)));

}

staticinlinevoidNF_Write(u8data)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFDATA=data;

}

staticinlineu8NF_Read(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

return(nand->NFDATA);

}

staticinlinevoidNF_Init_ECC(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFCONF|=(1<<12);

}

staticinlineu32NF_Read_ECC(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

return(nand->NFECC);

}

#endif

/*

*NANDflashinitialization.

*/

#if(CONFIG_COMMANDS&CFG_CMD_NAND)

externulongnand_probe(ulongphysadr);

staticinlinevoidNF_Reset(void)

{

inti;

NF_SetCE(NFCE_LOW);

NF_Cmd(0xFF);/*resetcommand*/

for(i=0;i<10;i++);/*tWB=100ns.*/

NF_WaitRB();/*wait200~500us;*/

NF_SetCE(NFCE_HIGH);

}

staticinlinevoidNF_Init(void)

{

#defineTACLS0

#defineTWRPH04

#defineTWRPH12

NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)

|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));

/*1111,1xxx,rxxx,rxxx*/

/*En512B4stepECCRnFCE=HtACLStWRPH0tWRPH1*/

NF_Reset();

}

voidnand_init(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

NF_Init();

#ifdefDEBUG

printf(“NANDflashprobingat0x%.8lXn“,(ulong)nand);

#endif

printf(“%4luMBn“,nand_probe((ulong)nand)>>20);

}

#endif



(8)修改GPIO配置(board/fs2410/fs2410.c)。



/*setuptheI/Oports*/

gpio->GPACON=0x007FFFFF;

gpio->GPBCON=0x002AAAAA;

gpio->GPBUP=0x000002BF;

gpio->GPCCON=0xAAAAAAAA;

gpio->GPCUP=0x0000FFFF;

gpio->GPDCON=0xAAAAAAAA;

gpio->GPDUP=0x0000FFFF;

gpio->GPECON=0xAAAAAAAA;

gpio->GPEUP=0x000037F7;

gpio->GPFCON=0x00000000;

gpio->GPFUP=0x00000000;

gpio->GPGCON=0xFFEAFF5A;

gpio->GPGUP=0x0000F0DC;

gpio->GPHCON=0x0018AAAA;

gpio->GPHDAT=0x000001FF;

gpio->GPHUP=0x00000656



(9)提供nandflash相關(guān)宏定義(include/configs/fs2410.h),具體參考源碼。



(10)加入NandFlash設(shè)備(include/linux/mtd/nand_ids.h)



staticstructnand_flash_devnand_flash_ids[]=

{

......

{“SamsungKM29N16000“,NAND_MFR_SAMSUNG,0x64,21,1,2,0x1000,0},

{“SamsungK9F1208U0M“,NAND_MFR_SAMSUNG,0x76,26,0,3,0x4000,0},

{“Samsungunknown4Mb“,NAND_MFR_SAMSUNG,0x6b,22,0,2,0x2000,0},

......

{NULL,}

};



(11)設(shè)置NandFlash環(huán)境(common/env_nand.c)



intnand_legacy_rw(structnand_chip*nand,intcmd,

size_tstart,size_tlen,

size_t*retlen,u_char*buf);

externstructnand_chipnand_dev_desc[CFG_MAX_NAND_DEVICE];

externintnand_legacy_erase(structnand_chip*nand,

size_tofs,size_tlen,intclean);



/*infoforNANDchips,definedindrivers/nand/nand.c*/

externnand_info_tnand_info[CFG_MAX_NAND_DEVICE];

......

#else/*!CFG_ENV_OFFSET_REDUND*/

intsaveenv(void)

{

ulongtotal;

intret=0;

puts(“ErasingNand...“);

if(nand_legacy_erase(nand_dev_desc+0,

CFG_ENV_OFFSET,CFG_ENV_SIZE,0))

{

return1;

}

puts(“WritingtoNand...“);

total=CFG_ENV_SIZE;

ret=nand_legacy_rw(nand_dev_desc+0,0x00|0x02,CFG_ENV_OFFSET,

CFG_ENV_SIZE,&total,(u_char*)env_ptr);

if(ret||total!=CFG_ENV_SIZE)

{

return1;

}

puts(“donen“);

returnret;

......

#else/*!CFG_ENV_OFFSET_REDUND*/

voidenv_relocate_spec(void)

{

#if!defined(ENV_IS_EMBEDDED)

ulongtotal;

intret;

total=CFG_ENV_SIZE;

ret=nand_legacy_rw(nand_dev_desc+0,0x01|0x02,CFG_ENV_OFFSET,

CFG_ENV_SIZE,&total,(u_char*)env_ptr);
回復(fù)

使用道具 舉報

發(fā)表回復(fù)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表