本文所有資料來至互聯網,筆者加以整理和歸納,僅供以後複習
對於uboot的start.S,主要做的事情就是系統的各個方面的初始化。
從大的方面分,可以分成這幾個部分:
- 設置CPU模式
- 關閉看門狗
- 關閉中斷
- 設置堆棧sp指針
- 清除bss段
- 異常中斷處理
1、分析.globl _start
Directive | Description | Syntax | Example |
---|---|---|---|
.global | Makes symbol visible to the linker | .global symbol | .global MyAsmFunc |
.globl | Same as .global | .globl symbol | .globl MyOtherAsmFunc |
所以,意思很簡單,就是相當於C語言中的Extern,聲明此變量,並且告訴鏈接器此變量是全局的,外部可以訪問
所以,你可以看到
board\開發板名\u-boot.lds
中,有用到此變量:
ENTRY(_start)
即指定入口爲_start,而由下面的_start的含義可以得知,_start就是整個start.S的最開始,即整個uboot的代碼的開始。
2、分析 _start: b reset
start的值,也就是這個代碼的位置了,此處即爲代碼的最開始,相對的0的位置。
在程序開始運行的時候,如果是從NorFlash或NandFlash啓動,那麼其地址是0,
_start=0
如果是重新relocate代碼之後,就是我們定義的值了,即,在
board\
開發板名
\config.mk
中的:
TEXT_BASE = 0x33D00000
表示是代碼段的基地址,即
_start=TEXT_BASE=0x33D00000
2、分析 LDR
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
LDR R0,[R1] ;將存儲器地址爲R1的字數據讀入寄存器R0。
LDR R0,[R1,R2] ;將存儲器地址爲R1+R2的字數據讀入寄存器R0。
LDR R0,[R1,#8] ;將存儲器地址爲R1+8的字數據讀入寄存器R0。
LDR R0,[R1,R2]! ;將存儲器地址爲R1+R2的字數據讀入寄存器R0,並將新地址R1+R2寫入R1。
LDR R0,[R1,#8]! ;將存儲器地址爲R1+8的字數據讀入寄存器R0,並將新地址R1+8寫入R1。
LDR R0,[R1],R2 ;將存儲器地址爲R1的字數據讀入寄存器R0,並將新地址R1+R2寫入R1。
LDR R0,[R1,R2,LSL#2]! ;將存儲器地址爲R1+R2×4的字數據讀入寄存器R0,並將新地址R1+R2×4寫入R1。
LDR R0,[R1],R2,LSL#2 ;將存儲器地址爲R1的字數據讀入寄存器R0,並將新地址R1+R2×4寫入R1。
3、分析 .word
_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
表 1.2. .word的語法
Directive Description Syntax Example .word Define word expr (32bit numbers) .word expr {, …} .word 144511, 0x11223
所以上面的含義,以_undefined_instruction爲例,就是,此處分配了一個word=32bit=4字節的地址空間,裏面存放的值是undefined_instruction。
而此處_undefined_instruction也就是該地址空間的地址了。用C語言來表達就是:
_undefined_instruction = &undefined_instruction
或
*_undefined_instruction = undefined_instruction
在後面的代碼,我們可以看到,undefined_instruction也是一個標號,即一個地址值,對應着就是在發生“未定義指令”的時候,系統所要去執行的代碼。
(其他幾個對應的“軟件中斷”,“預取指錯誤”,“數據錯誤”,“未定義”,“(普通)中斷”,“快速中斷”,也是同樣的做法,跳轉到對應的位置執行對應的代碼。)
3、分析 .balignl
.balignl 16,0xdeadbeef
表 1.3. balignl的語法
Directive Description Syntax Example .balignl Word align the following code to alignment byte boundary (default=4). Fill skipped words with fill (default=0 or NOP). If the number of bytes skipped is greater than max, then don't align (default=alignment ). .balignl {alignment} {, fill} {, max} .balignl
所以意思就是,接下來的代碼,都要16字節對齊,不足之處,用0xdeadbeef填充。
其中關於所要填充的內容0xdeadbeef,此處0xdeadbeef本身沒有真正的意義,但是很明顯,字面上的意思是,(壞)死的牛肉。
雖然其本身沒有實際意義,但是其是在十六進制下,能表示出來的,爲數不多的,可讀的單詞之一了。
另外一個相對常見的是:0xbadc0de,意思是bad code,壞的代碼,注意其中的o是0,因爲十六進制中是沒有o的。
這些“單詞”,相對的作用是,使得讀代碼的人,以及在查看程序運行結果時,容易看懂,便於引起注意。
4、分析 _TEXT_BASE 和_armboot_start
/*
*************************************************************************
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* setup Memory and board specific bits prior to relocation.
* relocate armboot to ram
* setup stack
*
*************************************************************************
*/
_TEXT_BASE:
.word TEXT_BASE
/*
* Below variable is very important because we use MMU in U-Boot.
* Without it, we cannot run code correctly before MMU is ON.
* by scsuh.
*/
/* 此處的<pre name="code" class="objc">CFG_PHY_UBOOT_BASE應該在某處定義
*/_TEXT_PHY_BASE: .word CFG_PHY_UBOOT_BASE.globl _armboot_start_armboot_start: .word _start
TEXT_BASE在\board\開發板名\config.mk
中定義
同理,此含義可用C語言表示爲:
*(_armboot_start) = _start
5、分析 bss_start和_bss_end
/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
關於_bss_start和_bss_end都只是兩個標號,對應着此處的地址。
而兩個地址裏面分別存放的值是__bss_start和_end,這兩個的值,根據註釋所說,是定義在開發板相關的鏈接腳本里面的,我們此處的開發板相關的鏈接腳本是:
board\開發板名\
u-boot.lds
__bss_start = .;
.bss : { *(.bss) }
_end = .;
詳細解析參考博客:http://www.crifan.com/about/me/