uboot学习之三-----uboot启动第一阶段--start.S之一
uboot分為兩個(gè)階段:start.S是uboot的第一階段。
一:引入start.S
u-boot.s找到start.S的入口
①首先在C語(yǔ)言中整個(gè)項(xiàng)目的入口就是main函數(shù)(這是C語(yǔ)言規(guī)定的),所以如果要去了解C語(yǔ)言的項(xiàng)目,從main函數(shù)開(kāi)始,這樣才能分析,如果隨便拿一個(gè)文件就開(kāi)始看,最后看得一頭霧水,對(duì)自己沒(méi)有信心。怎么來(lái)找呢?可以使用souceinsight的搜索功能來(lái)查找。
②在uboot中因?yàn)橛袇R編階段參與,因此不能直接找main.c。整個(gè)程序的入口取決于連接腳本中ENTRY聲明的地方。ENTRY(_start)因此 _start符號(hào)是整個(gè)程序的入口,_start所在的代碼就是整個(gè)程序的起始代碼。
?
二:分析start.S
1、頭文件包含
①#include <config.h> config.h是在include文件下,這個(gè)文件不是源碼中的文件,是配置時(shí)自動(dòng)生成的文件。詳見(jiàn)mkconfig腳本,在mkcofig腳本最后 發(fā)現(xiàn)?
包含了一個(gè)#include <configs/x210_sd.h>
最后分析發(fā)現(xiàn),最終包含的是/include/configs/x210_sd.h,這個(gè)文件是整個(gè)uboot移植時(shí)的配置文件,里面有很多宏。這樣就將兩個(gè)文件關(guān)聯(lián)了起來(lái)。所以分析start.S時(shí),要考慮configs/x210_sd.h。
②#include <version.h>
/include/version.h中包含了#include "version_autogenerated.h"這個(gè)頭文件是編譯時(shí)自動(dòng)生成的,這里面定義的宏define U_BOOT_VERSION "U-Boot1.3.4Joran"來(lái)自于makefile的配置值。這個(gè)宏在我們的程序中會(huì)被調(diào)用,在我們uboot啟動(dòng)過(guò)程中串口打印出uboot的版本號(hào),那個(gè)版本號(hào)信息就來(lái)自于這 里。
③#if defined(CONFIG_ENABLE_MMU)
#include <asm/proc/domain.h>
#endif
asm目錄不是uboot中的原生目錄,uboot中本來(lái)是沒(méi)有這個(gè)目錄的。asm目錄是配置時(shí)創(chuàng)建的一個(gè)符號(hào)鏈接,實(shí)際指向的是就是asm-arm(詳解上一章節(jié)分析mkconfig腳本時(shí)).經(jīng)過(guò)分析后發(fā)現(xiàn),實(shí)際文件是:include/asm-arm/proc-armv/domain.h從這里可以看出之前配置時(shí)創(chuàng)建的符號(hào)鏈接的作用,如果沒(méi)有這些符號(hào)鏈接則編譯時(shí)根本通不過(guò),因?yàn)檎也坏筋^文件。(所以u(píng)boot不能在windows的共享文件夾下配置編譯,因?yàn)閣indows中沒(méi)有符號(hào)鏈接)
思考:為什么start.S不直接包含asm-arm/proc-armv/domain.h,而要用asm/proc/domain.h?這樣的設(shè)計(jì)主要是為了可移植性。因?yàn)槿绻苯影?#xff0c;則start.S文件和CPU架構(gòu)(和硬件)有關(guān)了,可移植性就差了。譬如我要把uboot移植到mips架構(gòu)下,則start.S源代碼中所有的頭文件包含全部要修改。我們用了符號(hào)鏈接之后,則start.S中源代碼不用改,只需要在具體的硬件移植時(shí)配置不同,創(chuàng)建的符號(hào)鏈接指向的不同,則可以具有可移植性。
④啟動(dòng)代碼的16字節(jié)頭部
從代碼讀出:如果定義了CONFIG_EVT1并且沒(méi)有定義CONFIG_FUSED,那么就定義4個(gè)4字節(jié)的空間。從sourceinsight部分可以看出紅色是已經(jīng)定義的,黑色是未定義的,所以條件滿足,定義出16字節(jié)的空間,并且填充起來(lái)。
裸機(jī)中講過(guò),從SD卡和nand啟動(dòng)是需要16字節(jié)校驗(yàn)頭(mkv210image.c就是為了計(jì)算這個(gè)校驗(yàn)頭),以前做裸機(jī)實(shí)驗(yàn)時(shí),dnw下載方式不需要校驗(yàn)頭,做SD卡啟動(dòng),mkv210image.c會(huì)給原鏡像210.bin加上16字節(jié)的校驗(yàn)頭。
uboot中,這里的start.S中在開(kāi)頭位置放了16字節(jié)的填充占位,這個(gè)占位的16字節(jié)只是保證正式的image的頭部確實(shí)有16字節(jié),但是這個(gè)16字節(jié)內(nèi)容是不對(duì)的,還需要后面去計(jì)算校驗(yàn)和然后重新去填充的,uboot下有一個(gè)sd_fusing文件夾下C110-EVT1-mkbl1.c這個(gè)文件幾乎就是我們之前的mkv210image.c。
C110-EVT1-mkbl1.c中:
這里和star.S是相互聯(lián)系的。
⑤異常向量表構(gòu)建
這個(gè)異常表順序是CPU設(shè)計(jì)時(shí)決定的,是硬件決定的。這些異常應(yīng)該被處理,如果不處理這些這些異常,程序會(huì)跑飛。
? 復(fù)位異常處理:復(fù)位異常的代碼是 b reset ,因此在CPU復(fù)位后真正去執(zhí)行的有效代碼是reset處的代碼,因此reset符號(hào)處,才是真正有意義代碼的開(kāi)始處。
⑥有意思的deadbeef
??? .balignl 16,0xdeadbeef? .balignl 16 是以16字節(jié)對(duì)齊,如果沒(méi)有對(duì)齊,用0xdeadbeef這個(gè)數(shù)字來(lái)填充,這個(gè)填充沒(méi)有什么特別的意義,只是剛好組成一個(gè)有意思的英語(yǔ)單詞----壞牛肉
?
?
為什么要對(duì)齊呢?有時(shí)候是為了提高訪問(wèn)效率,有時(shí)候是硬件的要求。
?
⑦TEXT_BASE等
?
第100行的TEXT_BASE在整個(gè)代碼里都是被引用,它是在makefile里配置階段時(shí)的TEXT_BASE,其實(shí)就是我們鏈接時(shí),指定的程序的鏈接地址,它的值就是c3e00000,我們?cè)谠创a中和配置的makefile中很多變量是互相關(guān)聯(lián)的,有些符號(hào)的值可以從makefile中傳遞到源代碼中.
⑧CFG_PHY_UBOOT_BASE? 33e00000? uboot在DDR中的物理地址。虛擬地址就是之前的ce3e00000。
?
⑨
.globl _armboot_start_armboot_start:
?? ?.word _start
/*
?* These are defined in the board-specific linker script.
?*/
.globl _bss_start
_bss_start:
?? ?.word __bss_start
.globl _bss_end
_bss_end:
?? ?.word _end
?armboot_start是后面重定位時(shí)用到的,bss_start這些是后面清bss段時(shí)會(huì)使用到的。
轉(zhuǎn)載于:https://www.cnblogs.com/yr-linux/p/5401178.html
總結(jié)
以上是生活随笔為你收集整理的uboot学习之三-----uboot启动第一阶段--start.S之一的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 利用python自带的包可以建立简单的w
- 下一篇: Android Studio 怎样打JA