版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、目錄1.1 U-Boot 工作過程11.1.1 U-Boot 啟動(dòng)第一階段代碼分析11.1.2 U-Boot 啟動(dòng)第二階段代碼分析181.1.3 U-Boot 啟動(dòng) Linux 過程251.1.4 U-Boot 添加命令的方法及 U-Boot 命令執(zhí)行過程301.1 U-Boot 工作過程U-Boot 啟動(dòng)內(nèi)核的過程可以分為兩個(gè)階段,兩個(gè)階段的功能如下:(1)第一階段的功能Ø 硬件設(shè)備初始化Ø 加載 U-Boot 第二階段代碼到 RAM 空間Ø 設(shè)置好棧Ø 跳轉(zhuǎn)到第二階段代碼(2)第二階段的功能Ø 初始化本階段使用的硬件設(shè)備Ø 檢測(cè)系
2、統(tǒng)內(nèi)存Ø 將內(nèi)核從 Flash到 RAM 中Ø 為內(nèi)核設(shè)置啟動(dòng)參數(shù)Ø 調(diào)用內(nèi)核1.1.1 U-Boot 啟動(dòng)第一階段代碼分析第一階段對(duì)應(yīng)的文件是 crm920t/start.S 和board/samsung/mini2440/lowlevel_init.S。U-Boot 啟動(dòng)第一階段流程如下:圖 2.1 U-Boot 啟動(dòng)第一階段流程根據(jù) crm920t/u-boot.lds 中指定的連接方式:第一個(gè)的是 crm920t/start.o,因此 u-boot.bin 的代碼在crm920t/start.o 中,其源代碼在 crm920t/start.S 中。下面我們
3、來分析 crm920t/start.S 的執(zhí)行。ENTRY(_start) SECTIONS. = 0x00000000;. = ALIGN(4);.text :crm920t/start.o (.text) board/samsung/mini2440/lowlevel_init.o (.text) board/samsung/mini2440/nand_read.o (.text)*(.text) 1. 硬件設(shè)備初始化(1)設(shè)置異常crm920t/start.S 開頭有如下的代碼:以上代碼設(shè)置了 ARM 異常表,各個(gè)異常介紹如下:表 2.1 ARM 異常表地址異常進(jìn)入模式描述0x00000
4、000復(fù)位管理模式復(fù)位電平有效時(shí),產(chǎn)生復(fù)位異常,程序跳轉(zhuǎn)到復(fù)位處理程序處執(zhí)行0x00000004未定義指令未定義模式遇到不能處理的指令時(shí),產(chǎn)生未定義指令異常.globl _start_start: b start_code/*復(fù)位 */ldr pc, _undefined_instruction /* 未定義指令 */ ldr pc, _software_interrupt /* 軟件中斷 */ldr pc, _prefetch_abort /* 預(yù)取指令異常 */ ldr pc, _data_abort/* 數(shù)據(jù)操作異常 */ ldr pc, _not_used/* 未使用 */ldr pc
5、, _irq/* irq 中斷 */ldr pc, _fiq/* fiq 中斷 */* 中斷 表 地址 */_undefined_instruction: .word undefined_instruction_software_interrupt: .word software_interrupt_prefetch_abort: .word prefetch_abort_data_abort:.word data_abort_not_used:.word not_used_irq:.word irq_fiq:.word fiq.balignl 16,0xdeadbeef在 crm920t/s
6、tart.S 中還有這些異常對(duì)應(yīng)的異常處理程序。當(dāng)一個(gè)異常產(chǎn)生時(shí),CPU 根據(jù)異常號(hào)在異常表中找到對(duì)應(yīng)的異常,然后執(zhí)行異常向量處的跳轉(zhuǎn)指令,CPU 就跳轉(zhuǎn)到對(duì)應(yīng)的異常處理程序執(zhí)行。其中復(fù)位異常的指令“bstart_code”決定了 U-Boot 啟動(dòng)后將自動(dòng)跳轉(zhuǎn)到標(biāo)號(hào)“start_code”處執(zhí)行。(2)CPU 進(jìn)入 SVC 模式以上代碼將 CPU 的工作模式位設(shè)置為管理模式,并將中斷位和快中斷禁止位置一,從而了 IRQ 和 FIQ 中斷。(3)設(shè)置寄存器地址start_code:/* set the cpu to SVC32 mode*/mrs r0, cpsrbic r0, r0, #0x
7、1f/*工作模式位清零 */orr r0, r0, #0xd3/*工作模式位設(shè)置為“10011”(管理模式),并將中斷位和快中斷位置 1 */msr cpsr, r00x00000008軟件中斷管理模式執(zhí)行 SWI 指令產(chǎn)生,用于用戶模式下的程序調(diào)用操作指令0x0000000c預(yù)存指令中止模式處理器預(yù)取指令的地址不存在,或該地址不當(dāng)前指令,產(chǎn)生指令預(yù)取中止異常0x00000010數(shù)據(jù)操作中止模式處理器數(shù)據(jù) 指令的地址不存在,或該地址不 當(dāng)前指令 時(shí),產(chǎn)生數(shù)據(jù)中止異常0x00000014未使用未使用未使用0x00000018IRQIRQ外部中斷請(qǐng)求有效,且 CPSR 中的 I 位為 0 時(shí), 產(chǎn)
8、生 IRQ 異常0x0000001cFIQFIQ快速中斷請(qǐng)求引腳有效,且 CPSR 中的 F 位為0 時(shí),產(chǎn)生 FIQ 異常對(duì)與 s3c2440 開發(fā)板,以上代碼完成了 WATCHDOG,INTMSK,INTSUBMSK,CLKDIVN 四個(gè)寄存器的地址的設(shè)置。各個(gè)寄存器地址參見參考文獻(xiàn)4 。(4)關(guān)閉看門狗以上代碼向看門狗中,CPU 將不斷重啟。寄存器寫入 0,關(guān)閉看門狗。否則在 U-Boot 啟動(dòng)過程(5)中斷INTMSK 是主中斷寄存器,每一位對(duì)應(yīng) SRCPND(中斷源引腳寄存器)中的一位,表明 SRCPND 相應(yīng)位代表的中斷請(qǐng)求是否被 CPU 所處理。根據(jù)參考文獻(xiàn) 4,INTMSK 寄
9、存器是一個(gè) 32 位的寄存器,每位對(duì)應(yīng)一個(gè)中斷,向其中寫入 0xffffffff 就將 INTMSK 寄存器全部位置一,從而對(duì)應(yīng)的中斷。# if defined(CONFIG_S3C2440)/* mask all IRQs by setting all bits in the INTMR - default*/mov r1, #0xffffffff /* 某位被置 1 則對(duì)應(yīng)的中斷被*/ ldr r0, =INTMSKstr r1, r0ldr r0, =pWTCON mov r1, #0x0str r1, r0 /*看門狗器的最低位為 0 時(shí),看門狗不輸出復(fù)位信號(hào) */# if defin
10、ed(CONFIG_S3C2400) # define pWTCON 0x15300000 # define INTMSK 0x14400008 # define CLKDIVN 0x14800014#else /* s3c2410 與 s3c2440 下面 4 個(gè)寄存器地址相同 */# define pWTCON 0x53000000/* WATCHDOG寄存器地址*/ # define INTMSK 0x4A000008/* INTMSK 寄存器地址 */# define INTSUBMSK0x4A00001C /* INTSUBMSK 寄存器地址 */ # define CLKDIVN
11、0x4C000014/* CLKDIVN 寄存器地址 */# endifINTSUBMSK 每一位對(duì)應(yīng) SUBSRCPND 中的一位,表明 SUBSRCPND 相應(yīng)位代表的中斷請(qǐng)求是否被 CPU 所處理。根據(jù)參考文獻(xiàn) 4,INTSUBMSK 寄存器是一個(gè) 32 位的寄存器,但是只使用了低15 位。向其中寫入 0x7fff 就是將 INTSUBMSK 寄存器全部有效位(低 15 位)置一,從而對(duì)應(yīng)的中斷。(6)設(shè)置 MPLLCON,UPLLCON, CLKDIVN# if defined(CONFIG_S3C2440) #define MPLLCON 0x4C000004 #define UPL
12、LCON 0x4C000008ldr r0, =CLKDIVNmov r1, #5 str r1, r0ldr r0, =MPLLCONldr r1, =0x7F021 str r1, r0ldr r0, =UPLLCONldr r1, =0x38022 str r1, r0# else/* FCLK:HCLK:PCLK = 1:2:4 */* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVNmov r1, #3 str r1, r0#endifldr r1, =0x7fff ldr r0, =INTSUBMSKstr r1, r0# endifCPU
13、 上電幾毫秒后,晶振輸出穩(wěn)定,F(xiàn)CLK=Fin(晶振頻率),CPU 開始執(zhí)行指令。但實(shí)際上,F(xiàn)CLK 可以高于 Fin,為了提高系統(tǒng)時(shí)鐘,需要用軟件來啟用PLL。這就需要設(shè)置 CLKDIVN,MPLLCON,UPLLCON 這 3 個(gè)寄存器。CLKDIVN 寄存器用于設(shè)置 FCLK,HCLK,PCLK 三者間的比例,可以根據(jù)表 2.2來設(shè)置。表 2.2 S3C2440 的 CLKDIVN 寄存器格式設(shè)置 CLKDIVN 為 5,就將 HDIVN 設(shè)置為二進(jìn)制的 10,由于 CAMDIVN9沒有被改變過,取默認(rèn)值 0,因此 HCLK = FCLK/4。PDIVN 被設(shè)置為 1,因此 PCLK=
14、HCLK/2。因此分頻比 FCLK:HCLK:PCLK = 1:4:8 。MPLLCON 寄存器用于設(shè)置 FCLK 與Fin 的倍數(shù)。MPLLCON 的位19:12稱為 MDIV,位9:4稱為 PDIV,位1:0稱為 SDIV。對(duì)于 S3C2440,F(xiàn)CLK 與 Fin 的關(guān)系如下面公式:MPLLCON 與 UPLLCON 的值可以根據(jù)參考文獻(xiàn) 4 中“PLL VALUE SELECTIONTABLE”設(shè)置。該表部分摘錄如下:表 2.3 推薦 PLL 值輸入頻率輸出頻率MDIVPDIVSDIV12.0000MHz48.00 MHz56(0x38)2212.0000MHz405.00 MHz12
15、7(0x7f)21MPLL(FCLK) = (2×m×Fin)/(p× )其中: m=MDIC+8,p=PDIV+2,s=SDIVCLKDIVN位說明初始值HDIVN2:100 : HCLK = FCLK/1.01 : HCLK = FCLK/2.10 : HCLK = FCLK/4 (當(dāng) CAMDIVN9 = 0 時(shí))HCLK= FCLK/8 (當(dāng) CAMDIVN9 = 1 時(shí))11 : HCLK = FCLK/3 (當(dāng) CAMDIVN8 = 0 時(shí))HCLK = FCLK/6 (當(dāng) CAMDIVN8 = 1 時(shí))00PDIVN00: PCLK = HCLK/1
16、 1: PCLK = HCLK/20當(dāng) mini2440 系統(tǒng)主頻設(shè)置為 405MHZ,USB 時(shí)鐘頻率設(shè)置為 48MHZ 時(shí),系統(tǒng)可以穩(wěn)定運(yùn)行,因此設(shè)置 MPLLCON 與 UPLLCON 為:(7)關(guān)閉 MMU,cache接著往下看:cpu_init_crit 這段代碼在 U-Boot 正常啟動(dòng)時(shí)才需要執(zhí)行,若將 U-Boot 從RAM 中啟動(dòng)則應(yīng)該注釋掉這段代碼。下面分析一下 cpu_init_crit 到底做了什么:320 #ifndef CONFIG_SKIP_LOWLEVEL_INIT321 cpu_init_crit:322/*323* 使數(shù)據(jù) cache 與指令 cache 無
17、效 */324*/325 mov r0, #0326 mcr p15, 0, r0, c7, c7, 0/* 向 c7 寫入 0 將使 ICache 與 DCache無效*/327 mcr p15, 0, r0, c8, c7, 0/* 向 c8 寫入 0 將使 TLB 失效 */ 328329/*330* disable MMU stuff and caches331*/332mrc p15, 0, r0, c1, c0, 0/* 讀出寄存器到 r0 中 */ 333bic r0, r0, #0x00002300 clear bits 13, 9:8 (-V- -RS) 334bic r0,
18、 r0, #0x00000087 clear bits 7, 2:0 (BCAM)335orr r0, r0, #0x00000002 set bit 2 (A) Align336orr r0, r0, #0x00001000 set bit 12 (I) I-Cache#ifndef CONFIG_SKIP_LOWLEVEL_INITbl cpu_init_crit #endifMPLLCON=(0x7f<<12) | (0x02<<4) | (0x01) = 0x7f021UPLLCON=(0x38<<12) | (0x02<<4) | (0
19、x02) = 0x38022代碼中的 c0,c1,c7,c8 都是 ARM920T 的協(xié)處理器 CP15 的寄存器。其中 c7是 cache寄存器,c8 是 TLB寄存器。325327 行代碼將 0 寫入 c7、c8,使 Cache,TLB 內(nèi)容無效。第 332337 行代碼關(guān)閉了 MMU。這是通過修改 CP15 的 c1 寄存器來實(shí)現(xiàn)的,先看 CP15 的 c1 寄存器的格式(僅列出代碼中用到的位):表 2.3 CP15 的 c1 寄存器格式(部分)各個(gè)位的意義如下:V : 表示異常表所在的位置,0:異常在 0x00000000;1:異常在0xFFFF0000I : 0 :關(guān)閉 ICache
20、s;1 :開啟 ICachesR、S : 用來與頁(yè)表中的描述符一起確定內(nèi)存的權(quán)限B : 0 :CPU 為小字節(jié)序;1 : CPU 為大字節(jié)序C : 0:關(guān)閉 DCaches;1:開啟 DCaches.VI.RSB.CAM337mcr p15, 0, r0, c1, c0, 0/* 保存 r0 到寄存器 */ 338339/*340 * before relocating, we have to setup RAM timing341 * because memory timing is board-dependend, you will342 * find a lowlevel_init.S
21、in your board directory.343*/344mov ip, lr 345346bl lowlevel_init 347348 mov lr, ip349 mov pc, lr350 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */332337 行代碼將 c1 的 M 位置零,關(guān)閉了 MMU。(8)初始化 RAM寄存器其中的 lowlevel_init 就完成了內(nèi)存初始化的工作,由于內(nèi)存初始化是依賴于開發(fā)板的,因此 lowlevel_init 的代碼一般放在 board 下面相應(yīng)的目錄中。對(duì)于 mini2440,lowlevel_init 在 bo
22、ard/samsung/mini2440/lowlevel_init.S 中定義如下:45 #define BWSCON 0x48000000/* 13 個(gè)器的開始地址 */ 129 _TEXT_BASE:130 .wordTEXT_BASE 131132 .globl lowlevel_init133 lowlevel_init:134 /* memory control configuration */135 /* make r0 relative the current location so that it */136 /* reads SMRDATA out of FLASH rat
23、her than memory ! */137 ldr r0, =SMRDATA138 ldr r1, _TEXT_BASE139 sub r0, r0, r1/* SMRDATA 減 _TEXT_BASE 就是 13 個(gè)寄存器的偏移地址 */140 ldr r1, =BWSCON/* Bus Width Status Controller */ 141add r2, r0, #13*4142 0:143ldr r3, r0, #4 /*將 13 個(gè)寄存器的值逐一賦值給對(duì)應(yīng)的寄存器*/ 144str r3, r1, #4145 cmp r2, r0146 bne 0b 147A : 0:數(shù)據(jù)時(shí)
24、不進(jìn)行地址對(duì)齊檢查;1:數(shù)據(jù)時(shí)進(jìn)行地址對(duì)齊檢查M : 0:關(guān)閉 MMU;1:開啟 MMUlowlevel_init 初始化了 13 個(gè)寄存器來實(shí)現(xiàn) RAM 時(shí)鐘的初始化。lowlevel_init 函數(shù)對(duì)于 U-Boot 從 NAND Flash 或 NOR Flash 啟動(dòng)的情況都是有效的。U-Boot.lds有如下代碼:board/samsung/mini2440/lowlevel_init.o 將被到crm920t/start.o 后面,因此 board/samsung/mini2440/lowlevel_init.o也在 U-Boot 的前 4KB 的代碼中。U-Boot 在 NAND
25、 Flash 啟動(dòng)時(shí),lowlevel_init.o 將自動(dòng)被到 CPU 內(nèi)部4KB 的內(nèi)部 RAM 中。因此第 137146 行的代碼將從 CPU 內(nèi)部 RAM 中值到相應(yīng)的寄存器中。寄存器的對(duì)于 U-Boot 在 NOR Flash 啟動(dòng)的情況,由于 U-Boot 連接時(shí)確定的地址是U-Boot 在內(nèi)存中的地址,而此時(shí) U-Boot 還在 NOR Flash 中,因此還需要在 NORFlash 中數(shù)據(jù)到 RAM 中。.text :crm920t/start.o (.text) board/samsung/mini2440/lowlevel_init.o (.text) board/sams
26、ung/mini2440/nand_read.o (.text) 148 /* everything is fine now */149 mov pc, lr 150151 .ltorg152 /* the literal pools origin */ 153154 SMRDATA:/* 下面是 13 個(gè)寄存器的值 */155 .word 156 .word 由于 NOR Flash 的開始地址是 0,而 U-Boot 的加載到內(nèi)存的起始地址是TEXT_BASE,SMRDATA 標(biāo)號(hào)在 Flash 的地址就是 SMRDATATEXT_BASE。綜上所述,lowlevel_init 的作用就是
27、將 SMRDATA 開始的 13 個(gè)值給開始地址BWSCON的 13 個(gè)寄存器,從而完成了器的設(shè)置。(9)U-Boot 第二階段代碼到 RAMcrm920t/start.S 原來的代碼是只支持從 NOR Flash 啟動(dòng)的,經(jīng)過修改現(xiàn)在 U-Boot 在 NOR Flash 和 NAND Flash 上都能啟動(dòng)了,實(shí)現(xiàn)的思路是這樣的:其中 bBootFrmNORFlash 函數(shù)作用是U-Boot 是在 NAND Flash 啟動(dòng)還是NOR Flash 啟動(dòng),若在 NOR Flash 啟動(dòng)則返回 1,否則返回 0。根據(jù) ATPCS 規(guī)則,函數(shù)返回值會(huì)被存放在 r0 寄存器中,因此調(diào)用 bBoot
28、FrmNORFlash 函數(shù)后根據(jù)r0 的值就可以U-Boot 在 NAND Flash 啟動(dòng)還是 NOR Flash 啟動(dòng)。bBootFrmNORFlash 函數(shù)在 board/samsung/mini2440/nand_read.c 中定義如下:int bBootFrmNORFlash(void)volatile unsigned int *pdw = (volatile unsigned int *)0; unsigned int dwVal;dwVal = *pdw; /*先下原來的數(shù)據(jù) */*pdw = 0x12345678;if (*pdw != 0x12345678) /* 寫入
29、失敗,說明是在 NOR Flash 啟動(dòng)*/bl bBootFrmNORFlash /*U-Boot 是在 NAND Flash 還是 NOR Flash 啟動(dòng) */cmp r0, #0/* r0 存放 bBootFrmNORFlash 函數(shù)返回值,若返回 0 表示NAND Flash 啟動(dòng),否則表示在 NOR Flash 啟動(dòng) */beq nand_boot/* 跳轉(zhuǎn)到 NAND Flash 啟動(dòng)代碼 */* NOR Flash 啟動(dòng)的代碼 */b stack_setup/*跳過 NAND Flash 啟動(dòng)的代碼 */ nand_boot:/* NAND Flash 啟動(dòng)的代碼 */ sta
30、ck_setup:/*其他代碼 */無論是從 NOR Flash 還是從 NAND Flash 啟動(dòng),地址 0 處為 U-Boot 的第一條指令“ bstart_code”。對(duì)于從 NAND Flash 啟動(dòng)的情況,其開始 4KB 的代碼會(huì)被自動(dòng)部 4K 內(nèi)存中,因此可以通過直接賦值的方法來修改。到 CPU 內(nèi)對(duì)于從 NOR Flash 啟動(dòng)的情況,NOR Flash 的開始地址即為 0,必須通過一定令序列才能向 NOR Flash 中寫數(shù)據(jù),所以可以根據(jù)這點(diǎn)差別來分辨是從NAND Flash 還是 NOR Flash 啟地址 0 寫入一個(gè)數(shù)據(jù),然后讀出來,如果發(fā)現(xiàn)寫入失敗的就是 NOR Fl
31、ash,否則就是 NAND Flash。下面來分析 NOR Flash 啟動(dòng)部分代碼:208 adr r0, _start/* r0<- current position of code */209 ldr r1, _TEXT_BASE/* test if we run from flash or RAM */*U-Boot 是否是到 RAM 中運(yùn)行,若是,則不用 再到 RAM 中了, 這種情況通常在調(diào)試 U-Boot 時(shí)才發(fā)生 */210 cmpr0, r1 /*_start 等于_TEXT_BASE 說明是到 RAM 中運(yùn)行 */211 beq stack_setup212 /* 以
32、下直到 nand_boot 標(biāo)號(hào)前都是 NOR Flash 啟動(dòng)的代碼 */213 ldr r2, _armboot_start214 ldr r3, _bss_start215 sub r2, r3, r2/* r2<- size of armboot */216 add r2, r0, r2/* r2<- source end address */217 /* 搬運(yùn) U-Boot 自身到 RAM 中*/return 1;else/* 寫入,說明是在 NAND Flash 啟動(dòng) */*pdw = dwVal;/* 恢復(fù)原來的數(shù)據(jù) */ return 0;下面再來分析 NAND F
33、lash 啟動(dòng)部分代碼:nand_boot:mov r1, #NAND_CTL_BASEldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )str r2, r1, #oNFCONF /* 設(shè)置 NFCONF 寄存器 */*設(shè)置 NFCONT,初始化 ECC 編/器,NAND Flash 片選 */ ldr r2, =( (1<<4)|(0<<1)|(1<<0) )str r2, r1, #oNFCONTldr r2, =(0x6) /* 設(shè)置 NFSTAT */ str r2, r
34、1, #oNFSTAT/*復(fù)位命令,第一次使用 NAND Flash 前復(fù)位 */ mov r2, #0xffstrb r2, r1, #oNFCMD mov r3, #0/* 為調(diào)用 C 函數(shù) nand_read_ll 準(zhǔn)備堆棧 */ ldr sp, DW_STACK_STARTmov fp, #0/* 下面先設(shè)置 r0 至 r2,然后調(diào)用 nand_read_ll 函數(shù)將 U-Boot 讀入 RAM */ ldr r0, =TEXT_BASE/* 目的地址:U-Boot 在 RAM 的開始地址 */mov r1, #0x0/* 源地址:U-Boot 在 NAND Flash 中的開始地址
35、*/mov r2, #0x30000/*的大小,必須比 u-boot.bin 文件大,并且必須是 NAND Flash 塊大小的整數(shù)倍,這里設(shè)置為 0x30000(192KB) */218 copy_loop:219 ldmiar0!, r3-r10 /* 從地址為r0的 NOR Flash 中讀入 8 個(gè)字的數(shù)據(jù) */220 stmiar1!, r3-r10 /* 將r3 至r10 寄存器的數(shù)據(jù)給地址為r1 的內(nèi)存 */221 cmp r0, r2/* until source end addreee r2 */222 ble copy_loop223 b stack_setup/* 跳過
36、NAND Flash 啟動(dòng)的代碼 */其中 NAND_CTL_BASE,oNFCONF 等在 include/confi下:ini2440.h 中定義如NAND Flash 各個(gè)就不介紹了。寄存器的設(shè)置在 S3C2440 的有詳細(xì)說明,這里代碼中 nand_read_ll 函數(shù)的作用是在 NAND Flash 中搬運(yùn) U-Boot 到 RAM,該函數(shù)在 board/samsung/mini2440/nand_read.c 中定義。NAND Flash 根據(jù) page 大小可分為 2 種: 512B/page 和 2048B/page 的。這兩種 NAND Flash 的讀操作是不同的。因此就需
37、要 U-Boot 識(shí)別到 NAND Flash 的類型,然后采用相應(yīng)的讀操作,也就是說 nand_read_ll 函數(shù)要能自動(dòng)適應(yīng)兩種NAND Flash。參考 S3C2440 的可以知道:根據(jù) NFCONF 寄存器的 Bit3(AdvFlash(Read only))和 Bit2 (PageSize (Read only))可以NAND Flash 的類型。Bit2、Bit3 與 NAND Flash 的 block 類型的關(guān)系如下表所示:#define NAND_CTL_BASE 0x4E000000 / NAND Flash寄存器基址#define STACK_BASE 0x33F000
38、00 /base address of stack #define STACK_SIZE 0x8000 /size of stack#define oNFCONF 0x00 /* NFCONF 相對(duì)于 NAND_CTL_BASE 偏移地址 */ #define oNFCONT 0x04 /* NFCONT 相對(duì)于 NAND_CTL_BASE 偏移地址*/ #define oNFADDR 0x0c /* NFADDR 相對(duì)于 NAND_CTL_BASE 偏移地址*/ #define oNFDATA 0x10 /* NFDATA 相對(duì)于 NAND_CTL_BASE 偏移地址*/ #define o
39、NFCMD 0x08/* NFCMD 相對(duì)于 NAND_CTL_BASE 偏移地址*/ #define oNFSTAT 0x20/* NFSTAT 相對(duì)于 NAND_CTL_BASE 偏移地址*/#define oNFECC 0x2c/* NFECC 相對(duì)于 NAND_CTL_BASE 偏移地址*/bl nand_read_ll/*跳轉(zhuǎn)到nand_read_ll 函數(shù),開始U-Boot 到RAM */ tst r0, #0x0/*檢查返回值是否正確 */beq stack_setup bad_nand_read:loop2: b loop2 /infinite loop.align 2DW_S
40、TACK_START: .word STACK_BASE+STACK_SIZE-4表 2.4 NFCONF 的 Bit3、Bit2 與 NAND Flash 的關(guān)系由于的 NAND Flash 只有 512B/page 和 2048 B/page 這兩種,因此根據(jù) NFCONF寄存器的 Bit3 即可區(qū)分這兩種 NAND Flash 了。完整代碼見 board/samsung/mini2440/nand_read.c 中的 nand_read_ll 函數(shù),這里給出偽代碼:(10)設(shè)置堆棧/* 設(shè)置堆棧*/int nand_read_ll(unsigned char *buf, unsigned
41、 long start_addr, int size)/根據(jù) NFCONF 寄存器的 Bit3 來區(qū)分 2 種 NAND Flashif( NFCONF & 0x8 )/* Bit 是 1,表示是 2KB/page 的 NAND Flash */ 2K block 的 NAND Flash/else/* Bit 是 0,表示是 512B/page 的 NAND Flash */ 512B block 的 NAND Flash/return 0;Bit2Bit3010256 B/page512 B/page11024 B/page2048 B/page只要將 sp 指針指向一段沒有被使用
42、的內(nèi)存就完成棧的設(shè)置了。根據(jù)上面的代碼可以知道 U-Boot 內(nèi)存使用情況了,如下圖所示:圖 2.2 U-Boot 內(nèi)存使用情況(11)清除 BSS 段clear_bss:ldr r0, _bss_start/* BSS 段開始地址,在 u-boot.lds 中指定*/ ldr r1, _bss_end/* BSS 段結(jié)束地址,在 u-boot.lds 中指定*/stack_setup:ldr r0, _TEXT_BASE/* upper 128 KiB: relocated uboot */ sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area
43、*/sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* 跳過全局?jǐn)?shù)據(jù)區(qū) */ #ifdef CONFIG_USE_IRQsub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)#endifsub sp, r0, #12/* leave 3 words for abort-stack */初始值為 0,無初始值的全局變量,靜態(tài)變量將自動(dòng)被放在 BSS 段。應(yīng)該將這些變量的初始值賦為 0,否則這些變量的初始值將是一個(gè)隨機(jī)的值,若有些程序直接使用這些沒有初始化的變量將引的后果。(12)跳轉(zhuǎn)到第二階段代碼跳轉(zhuǎn)到第二階
44、段代碼start_armboot 處。1.1.2 U-Boot 啟動(dòng)第二階段代碼分析start_armboot 函數(shù)在 lib_arm/board.c 中定義,是 U-Boot 第二階段代碼的。U-Boot 啟動(dòng)第二階段流程如下:ldr pc, _start_armboot_start_armboot: .word start_armbootmov r2, #0x00000000clbss_l:strr2, r0/* 將 bss 段清零*/ add r0, r0, #4cmp r0, r1ble clbss_l圖 2.3 U-Boot 第二階段執(zhí)行流程在分析 start_armboot 函數(shù)前
45、先來看看一些重要的數(shù)據(jù)結(jié)構(gòu):(1)gd_t 結(jié)構(gòu)體U-Boot 使用了一個(gè)結(jié)構(gòu)體 gd_t 來全局?jǐn)?shù)據(jù)區(qū)的數(shù)據(jù),這個(gè)結(jié)構(gòu)體在include/asm-arm/global_data.h 中定義如下:U-Boot 使用了一個(gè)在寄存器中的指針 gd 來全局?jǐn)?shù)據(jù)區(qū)的地址:DECLARE_GLOBAL_DATA_PTR 定義一個(gè) gd_t 全局?jǐn)?shù)據(jù)結(jié)構(gòu)的指針,這個(gè)指針存放在指定的寄存器 r8 中。這個(gè)也避免編譯器把 r8 分配給其它的變量。任何想要全局?jǐn)?shù)據(jù)區(qū)的代碼,只要代碼開頭加入“DECLARE_GLOBAL_DATA_PTR”一行代碼,然后就可以使用 gd 指針來全局?jǐn)?shù)據(jù)區(qū)了。根據(jù) U-Boot 內(nèi)
46、存使用圖中可以計(jì)算 gd 的值:(2)bd_t 結(jié)構(gòu)體bd_t 在 include/asm-arm.u/u-boot.h 中定義如下:typedef struct bd_info intbi_baudrate;/*串口通訊波特率 */ unsigned long bi_ip_addr;/* IP 地址*/struct environment_s *bi_env;/*環(huán)境變量開始地址 */ ulongbi_arch_number; /* 開發(fā)板的碼 */ulongbi_boot_params; /* 內(nèi)核參數(shù)的開始地址 */ struct/* RAM 配置信息 */ulong start; ul
47、ong size;gd = TEXT_BASE CONFIG_SYS_MALLOC_LEN sizeof(gd_t)#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")typedefstruct global_data bd_t*bd;unsigned long flags; unsigned long baudrate;unsigned long have_console; /* serial_init() was called */ unsigned long env_addr; /*
48、 Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long fb_base;/* base address of frame buffer */ void*jt;/* jump table */ gd_t;U-Boot 啟動(dòng)內(nèi)核時(shí)要給內(nèi)核傳遞參數(shù),這時(shí)就要使用 gd_t,bd_t 結(jié)構(gòu)體中的信息來設(shè)置標(biāo)記列表。(3)init_sequence 數(shù)組U-Boot 使用一個(gè)數(shù)組 init_sequence 來對(duì)于大多數(shù)開發(fā)板都要執(zhí)行的初始化
49、函數(shù)的函數(shù)指針。init_sequence 數(shù)組中有較多的編譯選項(xiàng),去掉編譯選項(xiàng)后 init_sequence 數(shù)組如下所示:其中的 board_init 函數(shù)在 board/samsung/mini2440/mini2440.c 中定義,該函數(shù)設(shè)置了,UPLLCON,以及一些 GPIO 寄存器的值,還設(shè)置了 U-Boot碼和內(nèi)核啟動(dòng)參數(shù)地址 :/* MINI2440 開發(fā)板的碼 */gd->bd->bi_arch_number = MACH_TYPE_MINI2440;typedef int (init_fnc_t) (void); init_fnc_t *init_sequen
50、ce = board_init,/*開發(fā)板相關(guān)的配置-board/samsung/mini2440/mini2440.c */timer_init,/* 時(shí)鐘初始化- crm920t/s3c24x0/timer.c */ env_init,/*初始化環(huán)境變量mon/env_flash.c 或common/env_nand.c*/init_baudrate,/*初始化波特率- lib_arm/board.c */ serial_init,/* 串口初始化- drivers/serial/serial_s3c24x0.c*/console_init_f, /*通訊臺(tái)初始化階段 1- common/
51、console.c */ display_banner, /*打印 U-Boot 版本、編譯的時(shí)間- geditlib_arm/board.c */dram_init,/*配置可用的 RAM- board/samsung/mini2440/mini2440.c*/display_dram_config,/* 顯示 RAM 大小- lib_arm/board.c */ NULL,;bi_dramCONFIG_NR_DRAM_BANKS; bd_t;其中的 dram_init 函數(shù)在 board/samsung/mini2440/mini2440.c 中定義如下:mini2440 使用 2 片 3
52、2MB 的 SDRAM 組成了 64MB 的內(nèi)存,接在器的 BANK6,地址空間是 0x300000000x34000000。在include/confiini2440.h 中PHYS_SDRAM_1 和PHYS_SDRAM_1_SIZE分別被定義為 0x30000000 和 0x04000000(64M)。分析完上述的數(shù)據(jù)結(jié)構(gòu),下面來分析 start_armboot 函數(shù):void start_armboot (void)init_fnc_t *init_fnc_ptr; char *s; /*計(jì)算全局?jǐn)?shù)據(jù)結(jié)構(gòu)的地址 gd */gd = (gd_t*)(_armboot_start - CO
53、NFIG_SYS_MALLOC_LEN - sizeof(gd_t); memset (void*)gd, 0, sizeof (gd_t);gd->bd = (bd_t*)(char*)gd - sizeof(bd_t); memset (gd->bd, 0, sizeof (bd_t);gd->flags |= GD_RELOC;monitor_flash_len = _bss_start - _armboot_start;/* 逐個(gè)調(diào)用 init_sequence 數(shù)組中的初始化函數(shù) */int dram_init (void)/* 由于 mini2440 只有 */gd->bd->bi_dram0.start = PHYS_SDRAM_1;gd->bd->bi_dram0.size = PHYS_SDRAM_1_SIZE; return 0;/* 內(nèi)核啟動(dòng)參數(shù)地址 */gd->bd->bi_boot_params = 0x30000100;for (init_fnc_ptr = init_sequence; *init_fnc_ptr; +init_fnc_ptr) if (*init_fnc_ptr)() != 0)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024-2030年中國(guó)隔熱耐火磚行業(yè)面臨的困境及對(duì)策規(guī)劃研究報(bào)告
- 2024-2030年中國(guó)銑刀具行業(yè)市場(chǎng)運(yùn)營(yíng)模式及未來發(fā)展動(dòng)向預(yù)測(cè)報(bào)告
- 2024-2030年中國(guó)鉆機(jī)配件項(xiàng)目可行性研究報(bào)告
- 2024-2030年中國(guó)金融軟件產(chǎn)業(yè)未來發(fā)展趨勢(shì)及投資策略分析報(bào)告
- 2024年新修訂版:苗木購(gòu)銷協(xié)議
- 2024年改良版:建筑工程木工協(xié)作協(xié)議
- 2024年教育機(jī)構(gòu)輔導(dǎo)老師派遣協(xié)議
- 2024年式沿街店面出租協(xié)議
- 2024年損害賠償協(xié)議:交通事故雙方和解條款
- 2024年度安徽省住宅租賃交易合同協(xié)議書
- 期刊編輯的學(xué)術(shù)期刊編輯規(guī)范考核試卷
- T-CCSAS014-2022《化工企業(yè)承包商安全管理指南》
- 電梯安全總監(jiān)和安全員的任命文件
- SL-T+62-2020水工建筑物水泥灌漿施工技術(shù)規(guī)范
- 2024年安徽省普通高中學(xué)業(yè)水平選擇性考試 歷史試卷
- 電子商務(wù)師職業(yè)技能等級(jí)證書培訓(xùn)方案
- JBT 14615-2024 內(nèi)燃機(jī) 活塞運(yùn)動(dòng)組件 清潔度限值及測(cè)定方法(正式版)
- DL5009.2-2013電力建設(shè)安全工作規(guī)程第2部分:電力線路
- 理智與情感:愛情的心理文化之旅智慧樹知到期末考試答案章節(jié)答案2024年昆明理工大學(xué)
- GA/T 2097-2023執(zhí)法辦案管理場(chǎng)所信息應(yīng)用技術(shù)要求
- GB 20052-2024電力變壓器能效限定值及能效等級(jí)
評(píng)論
0/150
提交評(píng)論