版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第7章嵌入式系統(tǒng)的BootLoader7.1BootLoader概述7.2BootLoader與嵌入式系統(tǒng)的關(guān)系7.3BootLoader的主要功能及典型結(jié)構(gòu)7.4S3C44B0X的BootLoader分析7.5U-Boot啟動(dòng)流程及相關(guān)代碼分析 7.1BootLoader概述
7.1.1BootLoader的作用和任務(wù)
嵌入式系統(tǒng)的BootLoader程序,即系統(tǒng)的引導(dǎo)裝載程序,簡(jiǎn)單地說,就是在操作系統(tǒng)內(nèi)核或用戶應(yīng)用程序之前運(yùn)行的一段小程序。通過這段小程序可以初始化硬件設(shè)備和建立內(nèi)存空間的映射圖,將系統(tǒng)的軟、硬件環(huán)境帶到一個(gè)合適的狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核或用戶應(yīng)用程序準(zhǔn)備好正確的環(huán)境。BootLoader的主要任務(wù)如圖7.1所示。圖7.1BootLoader的主要任務(wù)7.1.2常用嵌入式BootLoader介紹
常用的嵌入式BootLoader有vivi、U-Boot、RedBoot、ARMBoot、Blob和DIY。
1.?vivi
vivi是由韓國MIZI公司開發(fā)的一種專門用于ARM產(chǎn)品線的BootLoader。因?yàn)関ivi目前只支持使用串口與主機(jī)通信,所以必須使用一條串口電纜來連接目標(biāo)板和主機(jī)。vivi的源代碼下載地址為/developer/s3c2410x/download/vivi.html。
2.?U-Boot
U-Boot是德國DENX小組開發(fā)的用于多種嵌入式CPU的BootLoader程序,它可以運(yùn)行在PowerPC、ARM、MIPS等多種嵌入式開發(fā)板上。從/或
ftp://ftp.denx.de/pub/u-boot/站點(diǎn)均可以下載U-Boot的源代碼。
3.RedBoot
RedBoot是一個(gè)專門為嵌入式系統(tǒng)定制的引導(dǎo)啟動(dòng)工具,最初由RedHat公司開發(fā)。在/redboot站點(diǎn)可以下載RedBoot源碼,Redboot在嵌入式體系中應(yīng)用非常廣泛。
RedBoot是集BootLoader、調(diào)試和Flash燒寫于一體的,支持串口、網(wǎng)絡(luò)下載的可執(zhí)行嵌入式應(yīng)用程序。它既可以用在產(chǎn)品的開發(fā)階段(調(diào)試功能),也可以用在最終的產(chǎn)品上(Flash更新、網(wǎng)絡(luò)啟動(dòng))。
4.?ARMBoot
ARMBoot是一個(gè)以ARM或StrongARM為CPU內(nèi)核的嵌入式系統(tǒng)的BootLoader固件程序,該軟件的主要目標(biāo)是使新的平臺(tái)更容易被移植,并且盡可能地發(fā)揮其強(qiáng)大性能。它只基于ARM固件,但是它支持多種類型的啟動(dòng),如Flash,網(wǎng)絡(luò)下載通過BOOTP、DHCP、TFTP等。它也是開源項(xiàng)目,可以從/projects/armboot網(wǎng)站獲得最新的ARMBoot源碼和詳細(xì)資料,它在ARM處理器方面應(yīng)用非常廣泛。
5.?Blob
Blob是BootLoaderObject的縮寫,是一款功能強(qiáng)大的BootLoader,其源代碼在/
projects/blob上可以獲取。
6.?DIY
DIY(DoItYourself),即自己制作。用DIY的方式自己編寫針對(duì)目標(biāo)的BootLoader,不但代碼量短小,而且靈活性很大,最重要的是將來容易維護(hù)。所以在實(shí)際嵌入式產(chǎn)品的開發(fā)中大多都選擇DIY的方式編寫B(tài)ootLoader。
7.2BootLoader與嵌入式系統(tǒng)的關(guān)系
系統(tǒng)加電復(fù)位后,所有的處理器都從處理器制造商預(yù)先安排的地址上取指令,如基于S3C44B0X的處理器在復(fù)位時(shí)通常都從地址0x00000000上取它的第一條指令。而且基于處理器構(gòu)建的嵌入式系統(tǒng)通常都有某種類型的固態(tài)存儲(chǔ)設(shè)備(如ROM、E2PPOM、Flash等)被映射到這個(gè)預(yù)先安排的地址上,因此在系統(tǒng)加電后,處理器將首先執(zhí)行BootLoader程序。
裝有BootLoader內(nèi)核的啟動(dòng)參數(shù)、內(nèi)核映像和根文件系統(tǒng)映像的固態(tài)存儲(chǔ)設(shè)備的典型空間分配結(jié)構(gòu)如圖7.2所示。圖7.2存儲(chǔ)設(shè)備典型空間分配結(jié)構(gòu)7.2.1BootLoader的操作模式
1.啟動(dòng)加載(BootLoading)模式
BootLoader從目標(biāo)機(jī)的某個(gè)固態(tài)存儲(chǔ)設(shè)備上將操作系統(tǒng)加載到RAM中運(yùn)行,整個(gè)過程并沒有用戶的介入。該模式是BootLoader的正常工作模式。
2.下載(DownLoading)模式
目標(biāo)機(jī)的BootLoader將通過串口連接、網(wǎng)絡(luò)連接等通信手段從主機(jī)上下載文件。從主機(jī)下載的文件通常先被BootLoader保存到目標(biāo)機(jī)的RAM中,然后再被BootLoader寫到目標(biāo)機(jī)上的固態(tài)存儲(chǔ)設(shè)備中。該模式通常在系統(tǒng)更新時(shí)使用。7.2.2BootLoader的總體設(shè)計(jì)
1.階段設(shè)計(jì)
BootLoader的啟動(dòng)是可以分階段的,因此在設(shè)計(jì)時(shí)也可將BootLoader分為階段1和階段2。
(1)基于編程語言的考慮。階段1主要用匯編語言編寫,這是因?yàn)樗饕M(jìn)行與CPU核心及存儲(chǔ)設(shè)備密切相關(guān)的處理工作和進(jìn)行一些必要的初始化工作,是依賴于CPU體系結(jié)構(gòu)的代碼,這部分直接在Flash中執(zhí)行。階段2可以用C語言編寫,主要實(shí)現(xiàn)一般的流程以及對(duì)板級(jí)的一些驅(qū)動(dòng)支持,這部分會(huì)被復(fù)制到RAM中執(zhí)行。
(2)為了使代碼具有更好的可讀性與可移植性。對(duì)于相同的CPU以及存儲(chǔ)設(shè)備,若要增加外設(shè)支持,階段1的代碼可以維持不變,只對(duì)階段2的代碼進(jìn)行修改;而對(duì)于不同的CPU,則只需在階段1中修改基礎(chǔ)代碼。
2.地址規(guī)劃設(shè)計(jì)
當(dāng)BootLoader的階段設(shè)計(jì)完成之后,需要考慮的是鏡像存儲(chǔ)的地址分配,如總鏡像保存在什么地方、階段2對(duì)應(yīng)的鏡像會(huì)被復(fù)制到什么地方、內(nèi)核鏡像原先存放在什么地方及BootLoader會(huì)把它又重新加載到什么地方、如何進(jìn)行準(zhǔn)確的地址規(guī)劃以保證沒有相互沖突等。
3.模式設(shè)計(jì)
普通用戶:?jiǎn)?dòng)加載模式;開發(fā)者:下載模式。
既支持啟動(dòng)加載模式又支持下載模式的具體思路:在BootLoader完成一些硬件初始化工作之后、在加載內(nèi)核鏡像之前,判斷一定的時(shí)間內(nèi)有沒有用戶的鍵盤輸入。如果沒有,則為啟動(dòng)加載模式,直接加載內(nèi)核鏡像進(jìn)行啟動(dòng);如果有,則進(jìn)入命令行格式,這時(shí)開發(fā)者就可以根據(jù)自己的需要以及BootLoader的支持情況,做一些其他的工作。模式的轉(zhuǎn)換設(shè)計(jì)主要在階段2中實(shí)現(xiàn)。
7.3BootLoader的主要功能及典型結(jié)構(gòu)
7.3.1BootLoader的階段1
1.基本的硬件初始化
(1)屏蔽所有的中斷。
(2)設(shè)置處理器的速度和時(shí)鐘頻率。
(3)初始化RAM,包括正確地設(shè)置系統(tǒng)內(nèi)存控制器的功能寄存器以及各內(nèi)存控制寄存器。
(4)初始化LED。
(5)關(guān)閉處理器內(nèi)部指令/數(shù)據(jù)緩存。
2.加載階段2的RAM空間
為了獲得更快的執(zhí)行速度,通常把階段2加載到RAM空間中來執(zhí)行,因此必須為加載BootLoader的階段2準(zhǔn)備好一段可用的RAM空間。由于階段2通常用C語言來執(zhí)行,因此在考慮空間大小時(shí),除了階段2可執(zhí)行映像的大小外,還必須把堆棧空間也考慮進(jìn)來。此外,空間大小最好是頁面文件大小(通常是4?KB)的倍數(shù)。將階段2安排到整個(gè)RAM最頂層的1?MB空間是一種最常用的方法。
3.復(fù)制階段2到RAM
復(fù)制階段2到RAM時(shí)要確定以下兩點(diǎn):
(1)階段2的可執(zhí)行映像在固態(tài)存儲(chǔ)設(shè)備的存放起始地址和終止地址。
(2)?RAM空間的起始地址。
4.設(shè)置堆棧指針(SP)
堆棧指針的設(shè)置是為執(zhí)行C語言代碼作準(zhǔn)備的。通常可以把SP的值設(shè)置為stage2_end-4,即在7.3.2節(jié)中提到的那個(gè)1MB的RAM空間的最頂端(堆棧向下生長)。
5.跳轉(zhuǎn)到階段2的C程序入口點(diǎn)
在上述一切都就緒后,就可以跳轉(zhuǎn)到BootLoader的階段2去執(zhí)行了。比如,在ARM系統(tǒng)中,就可以通過修改寄存器PC為合適的地址來實(shí)現(xiàn)。BootLoader在Flash和RAM中的系統(tǒng)布局如圖7.3所示。圖7.3BootLoader在Flash和RAM中的系統(tǒng)布局7.3.2BootLoader的階段2
階段2的代碼通常用C語言來實(shí)現(xiàn),以便實(shí)現(xiàn)更復(fù)雜的功能和取得更好的代碼可讀性及可移植性。
1.初始化階段2要使用的硬件設(shè)備
初始化階段2通常包括初始化一個(gè)串行口,以便和終端用戶進(jìn)行I/O輸出信息;初始化計(jì)時(shí)器等。
2.檢測(cè)系統(tǒng)內(nèi)存映射
所謂內(nèi)存映射就是指整個(gè)物理地址空間中那些分配用來尋址系統(tǒng)的RAM單元。在S3C44B0X處理器中,從0x0C000000到0x10000000之間的64MB地址空間被用作系統(tǒng)的RAM地址空間。
BootLoader的階段2必須在執(zhí)行操作之前檢測(cè)整個(gè)系統(tǒng)的內(nèi)存映射情況,即它必須知道處理器預(yù)留的全部RAM地址空間哪些被真正映射到RAM地址單元,哪些是處于“未使用”狀態(tài)的。
3.加載內(nèi)核映像和根文件系統(tǒng)映像
(1)規(guī)劃內(nèi)存占用的布局。在規(guī)劃內(nèi)存占用的布局時(shí),主要考慮內(nèi)核映像所占用的內(nèi)存范圍和根文件系統(tǒng)所占用的內(nèi)存范圍兩個(gè)方面。
(2)從Flash上復(fù)制。由于像ARM這樣的嵌入式處理器通常都是在統(tǒng)一的內(nèi)存地址空間中尋找Flash等固態(tài)存儲(chǔ)設(shè)備的,因此從Flash上讀取數(shù)據(jù)與從RAM單元中讀取數(shù)據(jù)并沒有什么不同。用一個(gè)簡(jiǎn)單的循環(huán)就可以完成從Flash設(shè)備上拷貝映像的工作,程序代碼如下:
/*拷貝Flash地址0x10000內(nèi)核到RAM0xC300000中*/
ldrR0, =0x10000
ldrR1, =0xC300000
addR2, R0,#(1536*1024)
copy_kernel:
ldmia R0!,{R3-R10}
stmia R1!,{R3-R10}
cmp
R0,R2
ble
copy_kernel
4.調(diào)用內(nèi)核
所有硬件的設(shè)置完成之后,就可以跳轉(zhuǎn)到內(nèi)核,并開始運(yùn)行內(nèi)核了。調(diào)用內(nèi)核的程序代碼如下:
/*跳轉(zhuǎn)到RAM中執(zhí)行內(nèi)核*/
ldrR0,=0xC30000 ;0xC30000正是前面拷貝kernel函數(shù)中的目的地址
movPC,R0;修改程序地址寄存器,完成跳轉(zhuǎn)
7.4S3C44B0X的BootLoader分析
S3C44B0X下的μCLinux的BootLoader只是一個(gè)比較簡(jiǎn)單的BootLoader,所以它的階段1和階段2是一起由匯編完成的,程序流程如圖7.4所示。圖7.4簡(jiǎn)單的BootLoader工作流程圖以下是該BootLoader的完整程序:
/**********************************************************
*File:boot.s
**********************************************************/
WTCONEQU0x01D30000
;以下的幾個(gè)定義均是為了設(shè)置相應(yīng)的控制寄存器,請(qǐng)注意查閱各位所對(duì)應(yīng)的作用,
;理解所作的設(shè)置
PCONEEQU0x01D20028
LOCKTIMEEQU0x01D8000C
PLLCONEQU0x01D80000
CLKCONEQU0x01D80004
GLOBAL_start
_start:
breset;程序的第一條指令,在燒寫時(shí),它將會(huì)被燒寫在0x00000000地址
addpc,pc,#0x0C000000
addpc,pc,#0x0C000000
addpc,pc,#0x0C000000
addpc,pc,#0x0C000000
addpc,pc,#0x0C000000
addpc,pc,#0x0C000000
addpc,pc,#0x0C000000
MEMORY_CONFIG: ;定義一組數(shù)據(jù)用來設(shè)置后面的存儲(chǔ)器,可以把它看做一個(gè)數(shù)組
DCD0x11110102
DCD0x600
DCD0x7FFC
DCD0x7FFC
DCD0x7FFC
DCD0x7FFC
DCD0x7FFC
DCD0x18000
DCD0x18000
DCD0x860459
DCD0x10
DCD0x20
DCD0x20
;復(fù)位地址
reset:
;關(guān)看門狗
ldrr0,=WTCON
ldrr1,=0x0
strr1,[r0]
;設(shè)置端口控制寄存器PortE,打開RxD0和TxD0(串口輸入功能)
ldrr1,=PCONE
ldrr0,=0x25529
strr0,[r1]
;設(shè)置時(shí)鐘控制寄存器
ldrr1,=LOCKTIME
ldrr0,=0xFFF
strr0,[r1]
ldrr1,=PLLCON
ldrr0,=0x78061
strr0,[r1]
ldrr1,=CLKCON
ldrr0,=0x7FF8
strr0,[r1]
;設(shè)置寄存器
memsetup:
ldrr0,=MEMORY_CONFIG ;注意不用一個(gè)一個(gè)設(shè)置,通過前面已經(jīng)定義好的數(shù)
;組用4條指令就可以完成設(shè)置
ldmiar0,{r1-r13}
ldrr0,=0x01C80000
stmiar0,{r1-r13}
;拷貝Flash地址0x1000內(nèi)核到RAM0xC300000中
ldrr0,=0x10000
ldrr1,=0xC300000
addr2,r0,#(1536*1024) ;計(jì)算內(nèi)核的終點(diǎn)地址
copy_kernel:
ldmiar0!,{r3-r10}
stmiar1!,{r3-r10}
cmpr0,r2
blecopy_kernel
;跳轉(zhuǎn)到RAM中執(zhí)行內(nèi)核
ldrr0,=0xC300000 ;0xC300000正是前面拷貝內(nèi)核函數(shù)中的目的地址
movpc,r0 ;修改程序地址寄存器,完成跳轉(zhuǎn)
7.5U-Boot啟動(dòng)流程及相關(guān)代碼分析
7.5.1U-Boot啟動(dòng)流程
U-Boot作為ARM平臺(tái)常用的引導(dǎo)程序,具有結(jié)構(gòu)強(qiáng)大和功能強(qiáng)大的特點(diǎn)。下載u-boot-1.2.0.tar.bz2源碼包,解壓后會(huì)生成u-boot-1.2.0目錄,該目錄主要包括三類子目錄:與處理器或硬件電路板相關(guān)的文件目錄,如cpu、board、libarm等;存放通用文件和設(shè)備驅(qū)動(dòng)的目錄,如common、inculde、drivers等;存放U-Boot應(yīng)用程序、工具和文檔的目錄,如examples、tools等。下面來分析U-Boot的啟動(dòng)流程。
1.階段1
U-Boot的階段1(Stage1)代碼通常放在u-boot-1.2.0\cpu\arm920t\start.s文件中,用匯編語言寫成,其主要代碼功能如下:
●定義入口。由于一個(gè)可執(zhí)行的Image必須有一個(gè)入口點(diǎn),并且只能有一個(gè)全局入口,通常這個(gè)入口放在ROM(Flash)的0x0地址,因此,必須使編譯器知道這個(gè)入口。該工作可通過修改鏈接器腳本來完成。
●設(shè)置異常向量(ExceptionVector)。
●設(shè)置CPU的速度、時(shí)鐘頻率及終端控制寄存器。
●初始化內(nèi)存控制器。
●將ROM中的程序復(fù)制到RAM中。
●初始化堆棧。
●轉(zhuǎn)到RAM中執(zhí)行,該工作可使用指令ldrpc來完成。
2.階段2
對(duì)于ARM平臺(tái)來說,U-Boot的階段2(Stage2)代碼在u-boot-1.2.0\lib_arm\board.c文件中。文件中的start_armboot函數(shù)是整個(gè)C語言啟動(dòng)代碼中的主函數(shù),同時(shí)還是整個(gè)U-Boot(針對(duì)ARM平臺(tái))的主函數(shù),該函數(shù)將完成如下操作:
●調(diào)用一系列的初始化函數(shù)。
●初始化Flash設(shè)備。
●初始化系統(tǒng)內(nèi)存分配函數(shù)。
●如果目標(biāo)系統(tǒng)擁有NAND設(shè)備,則初始化NAND設(shè)備。
●如果目標(biāo)系統(tǒng)有顯示設(shè)備,則初始化該設(shè)備。
●初始化相關(guān)網(wǎng)絡(luò)設(shè)備,填寫IP、MAC地址等。
●進(jìn)入命令循環(huán)(即整個(gè)boot的工作循環(huán)),接收用戶從串口輸入的命令,然后進(jìn)行相應(yīng)的工作。圖7.5U-Boot啟動(dòng)代碼順序圖7.5.2U-Boot代碼分析
U-Boot代碼分析如下:
//U-Boot的start.S
//定義變量_start,然后跳轉(zhuǎn)到處理器復(fù)位代碼
.glob1_start;U-Boot啟動(dòng)入口
_start:breset
//若產(chǎn)生中斷則利用pc來跳轉(zhuǎn)到對(duì)應(yīng)的中斷處理程序中
ldrpc,_undefined_instruction //未定義指令向量
ldrpc,_software_interrupt //軟件中斷向量
ldrpc,_prefetch_abort //預(yù)取指中止向量
ldrpc,_data_abort //數(shù)據(jù)中止向量
ldrpc,_not_used //保留
ldrpc,_irq //中斷請(qǐng)求向量
ldrpc,_fiq //快速中斷請(qǐng)求向量
//利用.word在當(dāng)前位置放置一個(gè)值,這個(gè)值實(shí)際上就是對(duì)應(yīng)的中斷處理函數(shù)的地址
//.word的意義為在當(dāng)前地址處放入一個(gè)16bits的值
_undefined_instruction: .wordundefined_instruction
_software_interrupt: .wordsoftware_interrupt
_prefetch_abort: .wordprefetch_abort
_data_abort: .worddata_abort
_not_used: .wordnot_used
_irq: .wordirq
_fiq: .wordfiq
.balignl16,0xdeadbeef
/************************↓reset代碼***********************/
reset:
mrsr0,cpsr
bicr0,r0,#0x1f//bic清除指定為1的位
orrr0,r0,#0xd3//orr邏輯或操作
//經(jīng)過以上兩步r0值控制位為11010011,第0~4位表示處理器當(dāng)前所處模式為10011(32
//位管理模式);第6、7位為1表示禁止IRQ和FIQ中斷;第5位為0表示程序在ARM
//狀態(tài),若其為1則運(yùn)行在Thumb狀態(tài)
msrcpsr,r0 //設(shè)置處理器為32位管理模式
/*關(guān)閉看門狗*/
#definepWTCON0x53000000 //看門狗寄存器地址
#defineINTMSK0x4A00008 //中斷掩碼寄存器,決定哪個(gè)中斷源被屏蔽,某位為1則
//屏蔽中斷源,初始值為0xffffffff,屏蔽所有中斷
#defineINTSUBMSK0x4A00001C //中斷子掩碼寄存器,該寄存器只能屏蔽11個(gè)中斷源,
//因此其僅低11位有效,初始值為0x7ff
#defineCLKDIVN0x4C000014//時(shí)鐘分頻控制寄存器
//將看門狗寄存器清空,其各位含義為:第0位為1則當(dāng)看門狗定時(shí)器溢出時(shí)重啟,為
//0則不重啟,初值為1
//第2位為中斷使能位,初值為0
//第3、4位為時(shí)鐘分頻因子,初值為00
//第5位為看門狗的使能位,初值為1
//第8~15位為比例因子,初值為0x80
ldrr0,=pWTCON
movr1,#0x0
strr1,[r0] //將看門狗寄存器所有位置0,關(guān)閉看門狗,其實(shí)只要將第5位置0即可
movr1,#0xFFFFFFFF
ldrr0,=INTMSK
strr1,[r0] //屏蔽所有中斷,實(shí)際上中斷掩碼寄器初值即為0xFFFFFFF
ldrr1,=0x3FF
ldrr0,=INTSUBMSK
strr1,[r0] //設(shè)置中斷子掩碼寄存器
//設(shè)置時(shí)鐘寄存器,CLKDIVN第0位為PDIVN,為0則PCLK=HCLK,為1則
//PCLK=HCLK/2
//第1位為HDIVN,為0則HCLK=FCLK,為1則HCLK=FCLK/2
//這里兩位均為1,則FCLK∶HCLK∶PCLK=4∶2∶1
ldrr0,=CLKDIVN
movri,#3
strr1,[r0]
/***********************↑reset代碼**********************/
/*********************↓cpu_init_crit代碼******************/
//對(duì)關(guān)鍵寄存器的初始化,如果從RAM中啟動(dòng)則不執(zhí)行cpu_init_crit段代碼
cpu_init_crit:
//清空指令和數(shù)據(jù)caches
movr0,#0
mcrp15,0,r0,c7,c7,0
mcrp15,0,r0,c8,c7,0
/*disableMMUstuffandcaches*/
mrcp15,0,r0,c1,c0,0
bicr0,r0,#0x00002300@clearbits13,9:8(--V--RS)
bicr0,r0,#0x00000087@clearbits7,2:0(B--CAM)
orrr0,r0,#0x00000002@setbit2(A)Align
orrr0,r0,#0x00001000@setbit12(I)I-Cache
mcrp15,0,r0,c2,c0,0
//在重定向代碼之前,必須初始化內(nèi)存時(shí)序,因?yàn)橹囟ㄏ驎r(shí)需要將Flash中的代碼復(fù)制
//到內(nèi)存中
//內(nèi)存初始化的代碼在board/smdk2410/lowlevel_ini.S中
movip,lr
bllowlevel_init //調(diào)用lowlevel_init子程序(board/smdk2410/lowlevel_ini.S)
movlr,ip
movpc,lr //程序返回
/*********************↑c(diǎn)pu_init_crit代碼*******************/
/************↓lowlevel_init代碼(lowlevel_ini.S)**************/
lowlevel_init:
/*memorycontrolconfiguration*/
/*maker0relativethecurrentlocationsothatit*/
/*readsSMRDATAoutofFlashratherthanmemory!*/
ldr r0,=SMRDATA
ldr r1,_TEXT_BASE
sub r0,r0,r1
ldr r1,=BWSCON /*BusWidthStatusController*/
add r2,r0,#13*4
0b:
ldr r3,[r0],#4
str r3,[r1],#4
cmp r2,r0
bne 0b
/*everythingisfinenow*/
mov pc,lr
/**************↑lowlevel_init代碼(lowlevel_ini.s)*************/
/**************↓relocate代碼******************************/
relocate:/*relocateU-BoottoRAM*/
//當(dāng)前代碼地址,adr獲取當(dāng)前代碼的地址信息,若從RAM運(yùn)行,則_start=TEXT_BASE,
//否則_start=0x00000000
adrr0,_start/*r0<-currentpositionofcode*/
//獲取_TEXT_BASE
ldrr1,_TEXT_BASE/*testifwerunfromflashorRAM*/
cmpr0,r1/*don‘treloctduringdebug*/
//兩者相等,表示從RAM運(yùn)行則跳轉(zhuǎn)到堆棧設(shè)置
bepstack_setup
//不相等則表示從Flash中運(yùn)行,重定向代碼
ldrr2,_armboot_start
//獲取未初始化數(shù)據(jù)段地址
Ldrr3,_bss_start
//計(jì)算代碼段大小
subr2,r3,r2/*r2<-sizeofarmboot*/
//計(jì)算代碼段終止地址
addr2,r0,r2/*r2<-sourceendaddress*/
//復(fù)制代碼,r0為代碼的起始地址,r1為RAM中地址,r2為代碼的終止地址
//每次復(fù)制后將r0值遞增同r2比較來判斷是否復(fù)制完成
copy_loop:
ldmiar0!,{r3-r10}/*copyfromsourceaddress[r0]*/
stmiar1!,{r3-r10}/*copytotargetaddress[r1]*/
cmpr0,r2/*untilsourceendaddreee[r2]*/
blecopy_loop
/*******************↑relocate代碼**************************/
/*******************↓stack_setup代碼***********************/
stack_setup:
//獲取_TEXT_BASE
ldrro,_TEXT_BASE/*upper128K/B:relocateduboot*/
//獲取分配區(qū)域起始指針,CFG_MALLOC_LEN=128*1024+CFG_ENV_SIZE
//=128*1024+0X1000=192K
subr0,r0,#CFG_MALLOC_LEN/*mallocarea*/
//另外分配128B來存儲(chǔ)開發(fā)板信息
subr0,r0,#(CFG_GBL_DATA_SIZE/*bdinfo*/
#ifdefCONFIG_USE_IRQ
subr0,r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
//再減去12B用于棧起點(diǎn)
subsp,r0,#12/*leave3wordsforabort-stack*/
//清空未初始化數(shù)據(jù)段
clear_bss;
ldrr0,_bss_start/*findstartofbsssegment*/
ldrr1,_bss_end/*stophere*/
movr2,#0x00000000/*clear*/
clbss_1:strr2,[r0]/*clearloop…*/
addr0,r0,#4
cmpr0,r1
bleclbss_1
/*********************↑stack_setup代碼********************/
//完成復(fù)制后跳轉(zhuǎn)到start_armboot,到這里則進(jìn)入lib_arm/board.c的start-armboot函數(shù)中
ldrpc,_start_armboot
_start_armboot:.wordstart_armboot
在lib_arm/board.c中,首先定義函數(shù)指針數(shù)組,代碼如下:
typedefint(init_fnc_t)(void);
//定義函數(shù)指針數(shù)組,對(duì)硬件初始化按照該數(shù)組進(jìn)行
init_fnc_t*init_sequence[]={
cpu_init,//cpu/arm920t/cpu.c中定義,該函數(shù)為空,因?yàn)闆]有采用IPQ或FIQ模式
board_init,//board/smdk2410/smdk2410.c
interrupt_init,//cpu/arm920t/s3c24x0/interrupt.c
env_init,//tools/env/FW_env.c
init_baudrate,//lib_arm/board.c
serial_init,//cpu/arm920t/s3c24x0/serial.c
console_init_f,//common/console.c
display_banner,//lib_arm/board.c
#ifdefined(CONFIG_DISPLAY_BOARDINFO)
print_cpuinfo,//
#endif
#ifdefined(CONFIG_DISPLAY_BOARDINFO)
checkboard,//
#endif
dram_init,//board/smdk2410/smdk2410.c
display_dram_config,//lib_arm/board.c
NULL,
};
/*************↓start_armboot代碼***************/
voidstar_armboot(void)
{
init_fnc_t**init_fnc_ptr;
char*s;
#ifndefCFG_NO_FLASH
ulongsize;
#endif
#ifdefined(CONFIG_VFD)||defined(CONFIG_LCD)
unsignedlongaddr;
#endif
/*Pointeriswritablesinceweallocatedaregisterforit*/
//獲取全局gd指針
gd=(gd_t*)(_armboot_start-CFG_MALLOC_LEN-sizeof(gd_t));
/*compileroptimizationbarrierneededforGCC>=3.4*/
__asm__volatile__(**:::”memory”);
//清空該結(jié)構(gòu)體
memset((void*)gd,0,sizeof(gd_t));
//獲取bd_info結(jié)構(gòu)體指針
gd->bd=(bd_t*)((char*)gd–sizeof(bd_t));
memset(gd->bd,0,sizeof(bd_t));
//整個(gè)代碼區(qū)的長度
Monitor_flash_len=_bss_start-_armboot_start;
//調(diào)用初始化函數(shù),用來初始化gd結(jié)構(gòu)體
for(init_fnc_ptr=init_sequence;*init_fnc_ptr;++ini_fnc_ptr){
if((*init_fnc_ptr)()!=0){
hang();
}
}
#ifndefCFG_NO_FLASH
/*configureavailableFLASHbanks*/
//board/smdk2410/flash.c配置flash
//從其實(shí)現(xiàn)來看,好像只是配置NORFlash
//按頁對(duì)其方式保留顯存
addr=(_bss_end+(PAGE_SIZE-1))&~(PAGE_SIZE-1);
size=vfd_setmem(addr);
gd->fb_base=addr;
#endif /*CONFIG_VFD*/
//顯示器為LCD,同上
#ifdefCONFIG_VFD
#ifndefPAGE_SIZE
#definePAGE_SIZE4096
#endif
/*reservememoryforLCDdisplay(alwaysfullpages)*/
/*bss_endisdefinedintheboard-specificlinkerscript*/
size=flash_init();
//顯示Flash信息
display_flash_config(size);
#endif /*CFG_NO_FLASH*/
//定義顯示類型
#ifdefCONFIG_VFD
#ifndefPAGE_SIZE
#definePAGE_SIZE4096
#endif
/*reservememoryforVFDdisplay(alwaysfullpages)*/
/*bss_endisdefinedintheboard-specificlinkerscript*/
addr=(_bss_end+(PAGE_SIZE-))&~(PAGE_SIZE-1);
size=lcd_setmem(addr);
gd->fb_base=addr;
#endif /*CONFIG_LCD*/
//初始化CFG_MALLOC_LEN大小空間
/*armboot_startisdefinedintheboard-specificlinkerscript*/
mem_malloc_init(_armboot_start–CFG_MALLOC_LEN);
//初始化NANDFlash,這是在NANDFlash啟動(dòng)的s3c2410移植U-Boot的關(guān)鍵,根據(jù)Flash
//時(shí)序編寫函數(shù)即可
//在include/configs/smdk2410.h中的commanddefinition中增加CONFIG_COMMANDS
//和CFG_CMD_NAND命令
#if(CONFIG_COMMAND&CFG_CMD_NAND)
puts("NAND:");
nand_init();//board/smdk2410/smdk2410.c
#endif
#ifdefCONFIG_HAS_DATAFLASH
AT91F_DataflashInit();
dataflash_print_info();
#endif
/*initializeenvironment*/
//初始化環(huán)境參數(shù)
env_relocate();
//framebuffer初始化
#ifdefCONFIG_VFD
/*mustdothisaftertheframebufferisallocated*/
drv_vfd_init();
#endif/*CONFIG_VFD*/
//通過命令行參數(shù)傳遞獲取IP地址
/*IPAdress*/
gd->bd->bi_ip_addr=getenv_IPaddr("ipaddr");
//通過命令行參數(shù)傳遞獲取物理地址
/*MACAddress*/
{
inti
ulongreg
char*s,*e;
chartmp[64];
i=getenv_r("ethaddr",tmp,size(tmp));
s=(i>0)?tmp:NULL;
for(reg=0;reg<6;++reg)
{
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度照明工程設(shè)計(jì)、施工與監(jiān)理一體化合同2篇
- 2024年淄博職業(yè)學(xué)院高職單招語文歷年參考題庫含答案解析
- 解三角形復(fù)習(xí)
- 二零二五年度藝術(shù)展覽LOGO設(shè)計(jì)及文化傳播協(xié)議2篇
- 2024年陽泉市第一人民醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫頻考點(diǎn)附帶答案
- 2024年江西婺源茶業(yè)職業(yè)學(xué)院高職單招語文歷年參考題庫含答案解析
- 2024年江蘇護(hù)理職業(yè)學(xué)院高職單招職業(yè)技能測(cè)驗(yàn)歷年參考題庫(頻考版)含答案解析
- 二零二五年度財(cái)務(wù)顧問與創(chuàng)業(yè)投資機(jī)構(gòu)合作合同模板3篇
- 2024年杭州萬向職業(yè)技術(shù)學(xué)院高職單招職業(yè)適應(yīng)性測(cè)試歷年參考題庫含答案解析
- 2024年揭陽職業(yè)技術(shù)學(xué)院高職單招職業(yè)技能測(cè)驗(yàn)歷年參考題庫(頻考版)含答案解析
- 非諾貝特酸膽堿緩釋膠囊-臨床用藥解讀
- 二年級(jí)上冊(cè)數(shù)學(xué)豎式計(jì)算300道帶答案
- 設(shè)備管理:設(shè)備管理的維護(hù)與保養(yǎng)
- 土特產(chǎn)行業(yè)現(xiàn)狀分析
- 組織學(xué)與胚胎學(xué)課程教學(xué)大綱
- 玻璃硝酸鉀加硬工藝
- 蘇教版五年級(jí)上冊(cè)數(shù)學(xué)簡(jiǎn)便計(jì)算大全500題及答案
- 根軌跡分析基本概念
- 設(shè)立股權(quán)交易中心公司實(shí)施方案
- 珠海金灣區(qū)2023-2024學(xué)年七年級(jí)上學(xué)期期末數(shù)學(xué)達(dá)標(biāo)卷(含答案)
- 廣西壯族自治區(qū)欽州市浦北縣2023-2024學(xué)年七年級(jí)上學(xué)期期末歷史試題
評(píng)論
0/150
提交評(píng)論