freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

uboot啟動代碼詳解(編輯修改稿)

2025-07-25 08:35 本頁面
 

【文章內(nèi)容簡介】 set bit 2 (A) Align orr r0, r0, 0x00001000 @ set bit 12 (I) ICache mcr p15, 0, r0, c1, c0, 0 /* 保存r0到控制寄存器 */ /* * before relocating, we have to setup RAM timing * because memory timing is boarddependend, you will * find a in your board directory. */ mov ip, lr bl lowlevel_init mov lr, ip mov pc, lrendif /* CONFIG_SKIP_LOWLEVEL_INIT */ 代碼中的c0,c1,c7,c8都是ARM920T的協(xié)處理器CP15的寄存器。其中c7是cache控制寄存器,c8是TLB控制寄存器。將0寫入cc8,使Cache,TLB內(nèi)容無效。 通過修改CP15的c1寄存器來關(guān)閉了MMU。為什么要關(guān)閉catch 和MMU 呢?catch 和MMU 是做什么用的? catch 是cpu內(nèi)部的一個2級緩存,她的作用是將常用的數(shù)據(jù)和指令放在cpu內(nèi)部,MMU是用來做虛實地址轉(zhuǎn)換用的,我們的目的是設(shè)置控制的寄存器,寄存器都是實地址,如果既要開啟MMU又要做虛實地址轉(zhuǎn)換的話,中間還多一步,先要把實地址轉(zhuǎn)換成虛地址,然后再做設(shè)置,但對uboot 而言就是起到一個簡單的初始化的作用和引導(dǎo)操作系統(tǒng),如果開啟MMU 的話,很麻煩,也沒必要,所以關(guān)閉MMU. 說到catch 就必須提到一個關(guān)鍵字Volatile,以后在設(shè)置寄存器時會經(jīng)常遇到,他的本質(zhì)是告訴編譯器不要對我的代碼進(jìn)行優(yōu)化,優(yōu)化的過程是將常用的代碼取出來放到catch中,它沒有從實際的物理地址去取,它直接從cpu的緩存中去取,但常用的代碼就是為了感知一些常用變量的變化,所以在這種情況下要用Volatile關(guān)鍵字告訴編譯器不要做優(yōu)化,每次從實際的物理地址中去取指令。(8)初始化RAM控制寄存器 其中的bl lowlevel_init用于初始化各個bank,完成了內(nèi)存初始化的工作,由于內(nèi)存初始化是依賴于開發(fā)板的,因此lowlevel_init的代碼一般放在board下面相應(yīng)的目錄中。對于s3c2440,lowlevel_init在board/smdk2440/:define BWSCON 0x48000000 /* 13個存儲控制器的開始地址 */ … …_TEXT_BASE: .word TEXT_BASE.globl lowlevel_initlowlevel_init: /* memory control configuration */ /* make r0 relative the current location so that it */ /* reads SMRDATA out of FLASH rather than memory ! */ ldr r0, =SMRDATA ldr r1, _TEXT_BASE sub r0, r0, r1 /* SMRDATA減 _TEXT_BASE就是13個寄存器的偏移地址 */ ldr r1, =BWSCON /* Bus Width Status Controller */ add r2, r0, 13*40: ldr r3, [r0], 4 /*將13個寄存器的值逐一賦值給對應(yīng)的寄存器*/ str r3, [r1], 4 cmp r2, r0 bne 0b /* everything is fine now */ mov pc, lr .ltorg /* the literal pools origin */SMRDATA: /* 下面是13個寄存器的值 */ .word … ….word … …… … lowlevel_init的作用就是將SMRDATA開始的13個值復(fù)制給開始地址[BWSCON]的13個寄存器,從而完成了存儲控制器的設(shè)置。(9)復(fù)制UBoot第二階段代碼到RAMrelocate: adr r0, _start /* r0 current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM *//* 判斷UBoot是否是下載到RAM中運行,若是,則不用再復(fù)制到RAM中了,這種情況通常在調(diào)試UBoot時才發(fā)生 */ cmp r0, r1 /*_start等于_TEXT_BASE說明是下載到RAM中運行 */ beq stack_setup ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 size of armboot */ add r2, r0, r2 /* r2 source end address */ /* 搬運UBoot自身到RAM中*/copy_loop: ldmia r0!,{r3r10}/* 從地址為[r0]的NOR Flash中讀入8個字的數(shù)據(jù) */ stmia r1!,{r3r10}/* 將r3至r10寄存器的數(shù)據(jù)復(fù)制給地址為[r1]的內(nèi)存 */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop終于到重點部分了:代碼重定向(拷貝stage2到RAM中),拷貝時要確定兩點:(1) stage2的可執(zhí)行映象在固態(tài)存儲設(shè)備的存放起始地址和終止地址;(2) RAM空間的起始地址。下面我們來看看它到底是怎么重定向的:adr r0,_startadr偽指令,匯編器會將執(zhí)行到_start時PC的值放到r0中。所以此時r0中保存的不是編譯地址,而是運行地址。假如Uboot 是從RAM 開始運行,則從adr,r0,_start 得到的地址信息為r0=_start=_TEXT_BASE=TEXT_BASE=0x33f80000。假如Uboot 從Flash 開始運行,即從處理器對應(yīng)的地址運行,則r0=0x00000000。而這里r0=0。ldr r1,_TEXT_BASE這條匯編指令的意思是把_TEXT_BASE的值作為地址,把這個地址的內(nèi)容賦給r1,從下面可以知道:_TEXT_BASE里面存儲的內(nèi)容是TEXT_BASE,我們通過查看board/smdk2410/,所以r1的值就是0x33f80000cmp r0,r1將r0和r1做比較,此時r0 = 0x00000000,r1 = 0x33f80000,顯然不相等,那么執(zhí)行的就是下面的匯編指令:ldr r2, _armboot_start由此可以知道r2的值是_start,通過ldr將標(biāo)號的編譯地址放到r2中,也就是0x33f80000,即代碼段的起始地址。ldr r3, _bss_start有此可知,r3就是__bss_start的值。,r3的值是整個代碼得結(jié)尾.sub r2,r3,r2這條指令的意思是r2 = r3 r2,即r2 = 代碼結(jié)束 代碼開始,這樣得到的是r2 = 整個代碼的大小。add r2,r0,r2這條指令的意思是r2 = r0 + r2,即 r2 = 代碼開始 + 代碼大小,這樣得到的是r2 = falsh 里面代碼的結(jié)尾,此時我們得到r0 = flash 代碼的起始位置,r1 = 0x33f80000(sdram :0x300000000 ~ 0x34000000)將flash里面的代碼拷貝到sdram里面了。(10)設(shè)置堆棧 /* 設(shè)置堆棧 */stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, CONFIG_SYS_MALLOC_LEN /* malloc area */ sub r0, r0, CONFIG_SYS_GBL_DATA_SIZE /* 跳過全局?jǐn)?shù)據(jù)區(qū) */ifdef CONFIG_USE_IRQ sub r0, r0, (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)endif sub sp, r0, 12 /* leave 3 words for abortstack */ 只要將sp指針指向一段沒有被使用的內(nèi)存就完成棧的設(shè)置了。UBoot內(nèi)存使用情況如下圖所示:(11)清除BSS段clear_bss: ldr r0, _bss_start /* BSS段開始地址,*/ ldr r1, _bss_end /* BSS段結(jié)束地址,*/ mov r2, 0x00000000clbss_l:str r2, [r0] /* 將bss段清零*/ add r0, r0, 4 cmp r0, r1 ble clbss_l 初始值為0,無初始值的全局變量,靜態(tài)變量將自動被放在BSS段。應(yīng)該將這些變量的初始值賦為0,否則這些變量的初始值將是一個隨機的值,若有些程序直接使用這些沒有初始化的變量將引起未知的后果。(12)跳轉(zhuǎn)到第二階段代碼入口 ldr pc, _start_armboot_start_armboot: .word start_armboot跳轉(zhuǎn)到第二階段代碼入口start_armboot處。 Boot Loader 的 stage2詳細(xì)分析start_armboot函數(shù)在lib_arm/,是UBoot第二階段代碼的入口。UBoot啟動第二階段流程如下: 正如前面所說,stage2 的代碼通常用 C 語言來實現(xiàn),以便于實現(xiàn)更復(fù)雜的功能和取得更好的代碼可讀性和可移植性。在分析start_armboot函數(shù)前先來看看一些重要的數(shù)據(jù)結(jié)構(gòu):(1)gd_t結(jié)構(gòu)體 UBoot使用了一個結(jié)構(gòu)體gd_t來存儲全局?jǐn)?shù)據(jù)區(qū)的數(shù)據(jù),這個結(jié)構(gòu)體在include/asmarm/:typedef struct global_data{ bd_t *bd。 /* 與板子相關(guān)的結(jié)構(gòu)體,見下面 */ unsigned long flags。 /* 選項 */ unsigned long baudrate。 /* 波特率 */ unsigned long have_console。 /* serial_init() was called */ unsigned long env_addr。 /* 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。 UBoot使用了一個存儲在寄存器中的指針gd來記錄全局?jǐn)?shù)據(jù)區(qū)的地址:define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm (r8) DECLARE_GLOBAL_DATA_PTR定義一個gd_t全局?jǐn)?shù)據(jù)結(jié)構(gòu)的指針,這個指針存放在指定的寄存器r8中。這個聲明也避免編譯器把r8分配給其它的變量。任何想要訪問全局?jǐn)?shù)據(jù)區(qū)的代碼,只要代碼開頭加入“DECLARE_GLOBAL_DATA_PTR”一行代碼,然后就可以使用gd指針來訪問全局?jǐn)?shù)據(jù)區(qū)了。 根據(jù)UBoot內(nèi)存使用圖中可以計算gd的值:gd = TEXT_BASE - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t) (2)bd_t結(jié)構(gòu)體 bd_t在include/:typedef struct bd_info{ int bi_baudrate。 /* 串口通訊波特率 */ unsigned long bi_ip_addr。 /* IP 地址*/ struct environment_s *bi_env。 /* 環(huán)境變量開始地址 */ ulong bi_arch_number。 /* 開發(fā)板的機器碼 */ ulong bi_boot_params。 /* 內(nèi)核參數(shù)的開始地址 */ struct /* RAM配置信息 */ { ulong start。 /* 起始地址 */ ulong size。 /* 長度 */ }bi_dram[CONFIG_NR_DRAM_BANKS]。}bd_t。 UBoot啟動內(nèi)核時要給內(nèi)核傳遞參數(shù),這時就要使用gd_t,bd_t結(jié)構(gòu)體中的信息來設(shè)置標(biāo)記列表。(3)init_sequence數(shù)組 UBoot使用一個數(shù)組init_sequence(在lib_arm/)來存儲對于大多數(shù)開發(fā)板都要執(zhí)行的初始化函數(shù)的函數(shù)指針。init_sequence數(shù)組中有較多的編譯選項,去掉編譯選項后init_sequence數(shù)組如下所示:typedef int (init_fnc_t) (void)。 /* 這是使用typedef定義一個init_fnc_t為函數(shù)類型,該函數(shù)返回int型,無參數(shù) *
點擊復(fù)制文檔內(nèi)容
研究報告相關(guān)推薦
文庫吧 www.dybbs8.com
備案圖片鄂ICP備17016276號-1