1. 程式人生 > >uboot移植第二天——程式碼分析(2)

uboot移植第二天——程式碼分析(2)

今天是uboot移植學習第二天,通過csdn部落格記錄自己的學習過程,希望通過這個方法,使自己所學的知識得到複習和擴充套件,總結經驗發現不足,也希望自己的部落格能夠給人啟發,疑問的到解決。

uboot中start.S相關程式碼分析

這次主要對程式碼分析(1)的第一階段相關程式碼分析

  1. 設定為管理模式
reset:
    /*
     * set the cpu to SVC32 mode
     */
    mrs r0,cpsr①
    bic r0,r0,#0x1f②
    orr r0,r0,#0xd3③
    msr cpsr,r0④


CPSR 是當前的程式狀態暫存器(Current Program Status Register),
而 SPSR
是儲存的程式狀態暫存器(Saved Program Status Register) 1、 MRS指令 MRS指令的格式為: MRS{條件} 通用暫存器,程式狀態暫存器(CPSR或SPSR) MRS指令用於將程式狀態暫存器的內容傳送到通用暫存器中。該指令一般用在以

①:將cpsr(當前程式狀態暫存器)的值讀到r0中
②:清除r0中的後5位,因為在cpsr中第五位為模式設定位
③:將r0第五位或上0xd3
④:將r0的值寫入cpsr,這樣就將我們的處理器設定為了管理模式

2、turn off the watchdog——關閉看門狗

    ldr     r0, =pWTCON
    mov
r1, #0x0 str r1, [r0] 解釋:往pWTCON暫存器中寫0即可

3、mask all IRQs by setting all bits in the INTMR——關閉外部中斷

    ldr r1, =0x7fff
    ldr r0, =INTSUBMSK
    str r1, [r0]
    解釋:INTSUBMSK暫存器全寫1,就把中斷給mask了。INTSUBMSK暫存器如下:

這裡寫圖片描述
4、設定時鐘比例

    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr r0, =CLKDIVN
    mov r1, #3
str r1, [r0] 解析:The S3C2440A supports selection of Dividing Ratio between FCLK, HLCK and PCLK. This ratio is determined by HDIVN and PDIVN of CLKDIVN control register. 通過設定HDIVN and PDIVN of CLKDIVN的值確定時鐘的比例

這裡寫圖片描述

5、bl lowlevel_init——儲存控制器初始化

    ldr     r0, =SMRDATA
    ldr r1, _TEXT_BASE
    sub r0, r0, r1
    ldr r1, =BWSCON /* Bus Width Status Controller 0x48000000*/
    add     r2, r0, #13*4
解析:剛開始時程式碼和資料都只是儲存在norflash上記憶體中還沒有。
所以不能用連結地址讀取SMRDATA開始處的資料。
_TEXT_BASE:
.word TEXT_BASE  這個是我們的連結地址,即程式碼執行時所在的地址。
BWSCON:儲存控制器相關暫存器的起始暫存器
SMRDATA:表示13個暫存器的值得存放的開始地址(連結地址)在記憶體中,但現在不能讀取。
sub r0, r0, r1算出SMRDATA的相對地址(在norflash上13個暫存器的值得存放的開始地址)啟動時是可以讀取的,使得板子啟動時不在連線地址上時也能取SMRDATA中的值進行初始化儲存控制器。

注:
在重定位後,在我們的記憶體中(sdram)會有我們flash中的內容,在編譯時是按連結地址編譯,ldr r0, =SMRDATA中r0的值為記憶體中的地址(即在記憶體中13個暫存器的值得存放的開始地址,在flash中也有,TEXT_BASE 連結地址也是記憶體的地址,因此我們要計算出SMRDATA對於TEXT_BASE的相對偏移,這個相對偏移的值就是SMRDATA在flash的起始地址)。

6、重定位——即就是把falsh中的程式碼複製到ram中,本開發板複製到sdram中;

7、stack_setup——設定堆疊,因為接下來要調c函式,來進行更復雜的處理。

stack_setup:
    ldr r0, _TEXT_BASE      /* upper 128 KiB: relocated uboot   */
    sub r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
    sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo  

解析: 
r0
= TEXT_BASE
= 0x33D00000
而關於sub指令:
SUB : 減法
(Subtraction)
SUB{條件}{S} <dest>, <op 1>, <op 2>
dest = op_1 - op_2
SUB 用運算元 one 減去運算元 two,把結果放置到目的暫存器中。運算元 1 是一
個暫存器,運算元 2 可以是一個暫存器,被移位的暫存器,或一個立即值:
SUB R0, R1, R2 ; R0 = R1 - R2
SUB R0, R1, #256 ; R0 = R1 - 256
SUB R0, R2, R3,LSL#1 ; R0 = R2 - (R3 << 1)
減法可以在有符號和無符號數上進行

#CFG_MALLOC_LEN、#CFG_GBL_DATA_SIZE是巨集定義

8、clear_bss——清bss段,該段存放的是初始化為零或為未初始化的變數,只要額外的放在一個段就行,使用時取就行;
進入uboot的第二階段

clear_bss:
    ldr r0, _bss_start      /* find start of bss segment        */
    ldr r1, _bss_end        /* stop here                        */
    mov     r2, #0x00000000     /* clear                            */

clbss_l:str r2, [r0]        /* clear loop...                    */
    add r0, r0, #4
    cmp r0, r1
    ble clbss_l

解析:
此處的_bss_start是:
.globl _bss_start
_bss_start:
.word __bss_start
而_bss_end,是:
.globl _bss_end
_bss_end:
.word _end
對應的,__bss_start和_end,都在前面提到過的那個連結腳本里面:
u-boot-1.1.6\board\smdk2410\u-boot.lds中的:
__bss_start = .;
.bss : { *(.bss) }
_end = .;
即bss段的起始地址和結束地址
往裡面的值全部賦值為0

以上對uboot做了個非常粗略的分析,因本人初學記錄下的學習筆記,也希望能夠幫到正在學習uboot移植的學子,若有不對之處,望各位指出。