今天總算看完了,理解完了,理解清楚了,看透了start.S~~~~~~
本來不想寫的,想想還是輕描淡寫吧:好理解的一筆帶過,難理解的重點介紹。
.globl _start
_start: b reset
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
.balignl 16,0xdeadbeef
_start 全局變量,uboot代碼入口,在uboot中偏移地址_start_offset=0。除了reset中斷外,其他中斷都跳到SDRAM中去執行中斷,因此,用add指令,增加跳轉范圍。用LDR也是可以的,不過得另外定義一些變量,不如add省事,呵呵~~至于.balignl 16,0xdeadbeef網上都是說將地址對齊為16的倍數。為什么要對齊呢??不知道
*************************************************************************************************
_TEXT_BASE:
.word TEXT_BASE
.globl _armboot_start
_armboot_start:
.word _start
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
全局變量定義聲明:
_TEXT_BASE:全局變量指示uboot將被放在SDRAM中的地址,初始化為TEXT_BASE,在uboot\board\dave\B2\config.mk中賦值
_armboot_start:全局變量,指示uboot起始地址,初始化為_start,與_bss_start共同構成uboot的大小(sizeof(uboot)=_bss_start-_armboot_start)
_bss_start:BSS:Block Started by Symbol segment,全局變量,定義在uboot\board\dave\B2\u-boot.lds。用來存放未初始化的全局變量的一塊內存。_bss_start:BSS段起始地址
_bss_start:BSS段結束地址,_bss_start-_bss_end=sizeof(BSS)
*************************************************************************************************
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif
如果要用到IRQ和FIQ就設置相應堆棧
*************************************************************************************************
接著寫吧,有點難繼續下:
reset:
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0x13
msr cpsr,r0
@系統上電復位后設置成SVC模式
@寄存器操作方法:讀----修改-----回寫
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
bl lowlevel_init
#endif
@如果沒有定義CONFIG_SKIP_LOWLEVEL_INIT(顧名思義:跳過底層初始化)
@沒有定義的話那就跳進去進行初始化吧。
@cpu_init_crit函數在本文本中 后面介紹
@lowlevel_init在\uboot\board\dave\B2\lowlevel_init.S 完成存儲器初始化(<1.4的uboot不是這個名稱,好像是memap.S??大概是這個名字)
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
@如果沒有定義CONFIG_SKIP_RELOCATE_UBOOT(顧名思義:跳過重定位)
@那就要進行重定位判斷了
@先判斷uboot放置的地址,是在flash還是在SDRAM中。如果在flash中,則要重定位,即把uboot代碼整個搬@移至SDRAM中TEXT_BASE地址處;如果在SDRAM中,則不需要搬移,直接跳到堆棧設置。
@關于怎么判斷的,詳見日志:uboot relocate
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
@如果要搬移的話,計算uboot的大小
@并將整個搬移后的地址放入r2,以進行判斷是否搬運完了
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
@代碼搬移,每次搬運r3-r10個
@如果源地址和目標地址不一樣,則說明沒搬運完
adr r0, real_vectors
add r2, r0, #1024
ldr r1, =0x0c000000
add r1, r1, #0x08
vector_copy_loop:
ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r0, r2
ble vector_copy_loop
@將flash地址中的中斷向量表搬移到SDRAM中,構成二級中斷向量表
@當有中斷到來時,先跳轉到flash地址的中斷向量表(0x00000000),再在程序開始處的跳轉指令跳轉到
@SDRAM中的中斷向量表(0x0c000000)
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
@結束重定位,進行堆棧設置
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
@按照uboot存儲器映射圖,uboot被映射到SDRAM的高端。而在SDRAM地址減生長方向依次為
@CFG_MALLOC_LEN,CFG_GBL_DATA_SIZE,IRQ&FIQ(if define) abort_stack(12B)
@CFG_ENV_SIZE:環境變量存儲空間,緊接著MALLOC_LEN的前面(1024)
@MALLOC_LEN:定義在\ uboot\include\config\B2.h 為malloc()函數預留的數據空間
@同時包含CFG_ENV_SIZE,大小為(CFG_ENV_SIZE + 128*1024)
@GBL_DATA_SIZE:全局信息表gd的數據空間(128)
@IRQ&FIQ:如果定義了的話就分配
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
@如果定義了CONFIG_USE_IRQ 則分配IRQ和FIQ堆棧
sub sp, r0, #12 /* leave 3 words for abort-stack */
@分配12個字節空間為用戶棧
@注:CFG_MALLOC_LEN + CFG_GBL_DATA_SIZE + CONFIG_USE_IRQ + 12 =
@TEXT_BASE - SDRAM_start
ldr pc, _start_armboot
_start_armboot: .word start_armboot
@跳轉到_start_armboot
@_start_armboot用start_armboot初始化,即第一個C函數
*************************************************************************************************
#define INTCON (0x01c00000+0x200000)
#define INTMSK (0x01c00000+0x20000c)
#define LOCKTIME (0x01c00000+0x18000c)
#define PLLCON (0x01c00000+0x180000)
#define CLKCON (0x01c00000+0x180004)
#define WTCON (0x01c00000+0x130000)
@cpu初始化相關的一些寄存器名宏定義
*************************************************************************************************
cpu_init_crit:
/* disable watch dog */
ldr r0, =WTCON
ldr r1, =0x0
str r1, [r0]
@關閉看門狗
*************************************************************************************************
ldr r1,=INTMSK
ldr r0, =0x03fffeff
str r0, [r1]
ldr r1, =INTCON
ldr r0, =0x05
str r0, [r1]
@屏閉所有中斷,只開啟timer5做linux時鐘
*************************************************************************************************
ldr r1, =LOCKTIME
ldrb r0, =800
strb r0, [r1]
@設置時鐘鎖定延遲時間
#if CONFIG_S3C44B0_CLOCK_SPEED==66
ldr r0, =0x34031 /* 66MHz (Quartz=11MHz) */
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
ldr r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz */
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
@如果定義了一些系統時鐘的相關宏定義則設置相應的PLLCON
@當然自己也可以定義自己想要的時鐘 只需設置相應的值即可
str r0, [r1]
ldr r1,=CLKCON
ldr r0, =0x7ff8
str r0, [r1]
@使能所有模塊的時鐘
mov pc, lr
返回調用處