只分析脈絡,并不分析細節(jié)
一送粱、入口
通過百度和查找相應鏈接腳本,發(fā)現(xiàn)程序的入口位于arch/arm/lib/vectors.S
該文件的第一段代碼是定義了一個宏,并不生成代碼构拳!
標簽_start后面的語句才是要執(zhí)行的語句;將宏展開可知梁棠,執(zhí)行的是b reset
置森。
其余部分定義了中斷向量表,如果想要定義中斷符糊,可以模仿人家凫海。
執(zhí)行跳轉(zhuǎn)語句后,一般不會回到該文件了男娄,除非發(fā)生中斷行贪!
二漾稀、reset
通過百度查找,發(fā)現(xiàn)剩余代碼基本在相應CPU目錄下瓮顽,故知道符號reset位于目錄arch/arm/cpu/armv7/start.S
該文件做了些基本初始化操作县好,然后一去不復返的跳轉(zhuǎn)到_main。
現(xiàn)階段不必深究暖混。根據(jù)我的原則缕贡,不要修改公共代碼;修改公共代碼拣播,會出現(xiàn)不可預料的錯誤晾咪;因此這個文件不會修改。
三贮配、_main
通過JLINK谍倦,發(fā)現(xiàn)該符號位于arch/arm/lib/crt0.S,看名字就知道做了C語言環(huán)境初始化泪勒。
該調(diào)整了堆棧昼蛀,分配了內(nèi)存,并將內(nèi)存寫零圆存。最后一去不復返的跳轉(zhuǎn)到board_init_f
四叼旋、board_init_f ——SPL階段的導游
通過JLINK,發(fā)現(xiàn)該符號位于arch/arm/mach-exynos/spl_boot.c沦辙。
該函數(shù)是描述了SPL階段要做的事情夫植。首先分配內(nèi)存,并初始化了某些內(nèi)存油讯;然后做低級初始化操作详民;拷貝uboot到RAM;最后執(zhí)行uboot陌兑。
五沈跨、低級初始化 —— 為啟動uboot做準備
函數(shù)位于arch/arm/mach-exynos/lowlevel_init.c,做了電源初始化诀紊,時鐘初始化和內(nèi)存初始化谒出。
調(diào)用的函數(shù)都在同級目錄下,通過文件名字就能確定邻奠,不在啰嗦笤喳。
六、board_init_f ——再次出現(xiàn)該符號
再SPL階段碌宴,會執(zhí)行arch/arm/mach-exynos/spl_boot.c中的board_init_f杀狡,但進入uboot后,將會執(zhí)行common/board_f.c中的board_init_f贰镣。
通過分析發(fā)現(xiàn)呜象,這個函數(shù)主要調(diào)用函數(shù)initcall_run_list膳凝。
在initcall_run_list中,循環(huán)調(diào)用數(shù)組中的函數(shù)完成初始化工作恭陡,只要由一個函數(shù)失敗蹬音,程序沒法繼續(xù)往下執(zhí)行
執(zhí)行完board_init_f 后,程序會返回休玩。
七著淆、取消重定向
重定向的目的就是把代碼放到正確的位置,但對我們調(diào)試程序有很大影響拴疤,故需要取消重定向永部。
取消重定向的方式就是改變程序的鏈接地址,該地址需要通過調(diào)試確定呐矾。
ENTRY(relocate_code) x
x81 ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */ x
x82 subs r4, r0, r1 /* r4 <- relocation offset */ x
>x83 beq relocate_done /* skip relocation */ x
x84 ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */
通過訪問R0和R1寄存器苔埋,也確定新連接地址的值,也就是R0寄存器中的值蜒犯。