uboot第一階段詳細分析
時間:2018-08-16作者:華清遠見
uboot的第一階段設計的非常巧妙,幾乎都是用匯編語言實現的,下面我們一起來看看它的精妙之處吧! 首先我們來看一下它的鏈接腳本,通過它我們可以知道它整個程序的各個段是怎么存放的。
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
. = ALIGN(4);
. = ALIGN(4);
. = ALIGN(4);
. = ALIGN(4);
. = .;
. = ALIGN(4); 從它我們可以看到,uboot運行的第一個程序是cpu/arm920t/start.S,其他的都有注釋,就不多說了。 下面我們來看看在fs2410上通過nor flash啟動,u-boot的啟動流程: 電源一上電之后,pc指針從0x00000000 地址開始執行,也就是說這個時候程序跑在nor flash里面(別忘記,nor flash這個時候接在0x00000000地址,它是可以執行程序的只是速度沒有在ram里面執行快) 這個時候有人可能會問那s3c2410片內的4kRam映射到哪呢?通過查看芯片手冊這個時候它在0x40000000,如下圖:
現在我們知道是那個程序在哪里存儲,從哪個地址運行,下面我們來看看這段程序的匯編代碼:
在這里我們知道運行的第一條指令是b start_code,呵呵!看到這段代碼的時候許多人都認為_start的值是0x00000000,為什么是這個地址呢? 因為連接腳本上指定了。真的是這樣嗎?我們來看看我們編譯好之后,在u-boot目錄下有個System.map,這里面有各個變量的值,如下圖:
哈哈,_start的值怎么會是0x33f80000?這是因為在頂層的Makefile里面我們指定了它的連接地址。
看到那個 -o u-boot了嗎,就是通過它生成ELF格式的u-boot的,里面有個LDFLAGS變量,它是什么呢,我們繼續往下面看:
(頂層的config.mk里面有這個變量的說明) 看到了沒有,LDFLAGS里面除了指定鏈接腳本,如果TEXT_BASE不等于空,還加上了-Ttext$(TEXT_BASE),TEXT_BASE的值是多少呢?我們可以在board/samsung/smdk2410/config.mk里面有定義,它的值為0x33f80000。這樣我就可以知道為什么System.map的地址都是0x33f80000。 好我們來看第一條匯編指令b start_code,從System.map文件我們可以知道,這條指令相當于b 0x33f80050。"0x33f80050"?你是否有疑問,這個時候內存還沒有初始化呢,怎么能跳到內存中去了(sdram的起始地址0x30000000)。呵呵,其實不是這樣的。還記得b指令是相對跳轉指令嗎,它和代碼的位置是無關的,這種精妙的設計才使得后面的指令能繼續的執行。 下面我們繼續來看它的匯編指令:
呵呵,這段匯編代碼很好理解,就是設置CPU為 管理模式。
這段匯編代碼就不分析了,這是跟atmel相關的,我不管它,繼續下面:
這段匯編代碼也很好理解,就是關掉看門狗,然后關掉所有中斷。
哦哦,設置時鐘,還記得一上電FCLK是多少嗎,只有12MHZ。
呵呵!跳轉指令,我們來看看它做了什么,這樣我們先從名字上來猜猜它是什么意思?cpu初始化,初始化什么呢?繼續向下看:
呵呵,有英文注釋,清cache,關閉MMU。都是用協處理指令實現的,如果看不懂,可以看看協處理器指令。多了解一點就多知道一點,不是嗎? 從上面可以看到,還有一次跳轉bl lowlevel_init。這里面有干了一些什么呢,我們可以到board/samsung/smdk2410/ lowlevel_init.S去看。呵呵,這里我就不截圖了,其實我們只有知道,它在這里面干了初始化內存操作。 繼續往下面看:
呵呵,終于到重點部分了,代碼重定向。下面我們來看看它到底是怎么重定向的: Adr r0,_start 這條匯編指令的意思就是把_start當前代碼存儲的地址賦給r0,假如這段代碼存儲在SDRAM里面,那么r0的值就是0x30000000。現在這段代碼存儲在NOR Flash里面,所以r0的值就是
0x0000000 這條匯編指令的意思是把_TEXT_BASE的值作為地址,把這個地址的內容賦給r1,從下面可以知道:
_TEXT_BASE里面存儲的內容是TEXT_BASE,也就是0x33f80000,所以r1的值就是0x33f80000 Cmp r0,r1 將r0和r1做比較,此時r0 = 0x0000000,r1 = 0x33f80000,顯然不相等,那么執行的就是下面的匯編指令: ldr r2, _armboot_start
由此可以知道r2的值是_start,也就是0x33f80000,也是整個代碼的起始地址。 Ldr r3, _bss_start
由u-boot.lds的鏈接腳本可以知道,r3的值是整個代碼得結尾. Sub r2,r3,r2 這條指令的意思是r2 = r3 -r2,即r2 = 代碼結束 - 代碼開始,這樣得到的是r2 = 代碼的大小。 Add r2,r0,r2 這條指令的意思是r2 = r0 + r3,即 r2 = 代碼開始 + 代碼大小,這樣得到的是r2 = nor falsh 里面代碼的結尾 此時我們得到r0 = nor flash 代碼的起始位置,r1 = 0x33f80000(sdram :0x300000000 ~ 0x34000000)
呵呵,這個時候代碼就被從nor flash里面拷貝到sdram里面了。
這段代碼的意思是設置一些堆棧
這段代碼的意思是清bss段,
呵呵,終于看到pc指針的值被改變了。也就是這個時候,pc指針開始跳到sdram里面執行代碼,這也就到了第二階段(從語言階段),后面的代碼都是用C語言寫得了。先分析到這里,下次我們看第二階段。 uboot解析: 發表評論
|