Bootstrap-v1.14代码分析摘要
- crt0_gnu.S
.section start 定义start代码段
.text 定义为text段,text
段保存代码,是只读和可执行的,后面那些指令都属于.text
段。
#include "include/part.h" 包含头文件
.globl reset 声明 reset 符号,方便其它函数调用,其实是一个代码的起始地址
.align 4 后面以4字节对齐
reset: 即reset代码,即程序最开始的入口 详见elf32-littlearm.lds
/* Exception vectors (should be a branch to be detected as a valid code by the rom */
_exception_vectors:
b reset_vector /* reset */
b undef_vector /* Undefined Instruction */
b swi_vector /* Software Interrupt */
b pabt_vector /* Prefetch Abort */
b dabt_vector /* Data Abort */
.word _edata /* Size of the image for SAM-BA */
b irq_vector /* IRQ : read the AIC */
b fiq_vector /* FIQ */
undef_vector:
b undef_vector
swi_vector:
b swi_vector
pabt_vector:
b pabt_vector
dabt_vector:
b dabt_vector
rsvd_vector:
b rsvd_vector
irq_vector:
b irq_vector
fiq_vector:
b fiq_vector
[C2] reset_vector:
/* Init the stack */
_init_stack:
ldr sp,=TOP_OF_MEM[C3]
#if 0
/* PD0 on */
ldr r1, =0xfffff800
mov r2, #0x00000001
str r2, [r1, #0x000]
str r2, [r1, #0x010]
str r2, [r1, #0x034]
#else
/* PB21 on */
ldr r1, =0xfffff400
mov r2, #0x00200000
str r2, [r1, #0x000]
str r2, [r1, #0x010]
str r2, [r1, #0x034]
[C4] #endif
#ifdef CFG_NORFLASH
/*
* When running from NOR, we must relocate to SRAM prior to resetting
* the clocks and SMC timings.
*/
_relocate_to_sram:
#if 0
/* relocation is slow, disable the watchdog or it will trigger */
ldr r1, =0xFFFFFD44
mov r2, #0x00008000
str r2, [r1]
#endif
mov r1, #0
ldr r3, =_stext
ldr r4, =_edata
1:
cmp r3, r4
ldrcc r2, [r1], #4
strcc r2, [r3], #4
bcc 1b
ldr pc, =_setup_clocks
#endif /* CFG_NORFLASH */
_setup_clocks:
/* Test if main oscillator is enabled */
ldr r0,=AT91C_PMC_SR
ldr r1, [r0]
[C6] ldr r2,=AT91C_PMC_MOSCS
ands r1, r1, r2[C7]
bne _switch_to_mosc[C8]
/* Enable the main oscillator */
_enable_mosc:
ldr r0,=AT91C_PMC_MOR
mov r1, #(0x40 << 8)
ldr r2,=AT91C_CKGR_MOSCEN
orr r1, r1, r2
str r1, [r0]
[C9] ldr r0,=AT91C_PMC_SR
1:
ldr r1, [r0]
ldr r2,=AT91C_PMC_MOSCS
ands r1, r1, r2
beq 1b[C10]
/* Test if MCK == SLOW CLOCK */
_switch_to_mosc:
ldr r0,=AT91C_PMC_MCKR
ldr r1,=AT91C_PMC_CSS
ldr r2, [r0]
and r2, r2, r1[C11]
mov r1, #0
cmp r1, r2
/* No => Do nothing */
bne _init_bss
[C12] /* Yes => Switch to the main oscillator */
ldr r1,=AT91C_PMC_CSS_MAIN_CLK
ldr r2,=AT91C_PMC_PRES_CLK
orr r1, r1, r2
str r1, [r0][C13]
ldr r0,=AT91C_PMC_SR
1:
ldr r1, [r0]
ldr r2,=AT91C_PMC_MCKRDY
ands r1, r1, r2
beq 1b
/* Copy the data section in RAM at .data link address */
_init_data:
ldr r2, =_lp_data
ldmia r2, {r1, r3, r4}
1:
cmp r3, r4
ldrcc r2, [r1], #4
strcc r2, [r3], #4
bcc 1b
/* Initialize the bss segment */
_init_bss:
adr r2, _lp_bss
ldmia r2, {r3, r4}
mov r2, #0
1:
cmp r3, r4
strcc r2, [r3], #4
bcc 1b
/* Branch on C code Main function (with interworking) */
_branch_main:
ldr r4, = main
mov lr, pc
bx r4
/* Branch to the application at the end of the bootstrap init */
_go:
ldr r1, =MACH_TYPE
mov lr, pc
bx r0[C19]
.align
_lp_data:
.word _etext
.word _sdata
.word _edata
_lp_bss:
.word _sbss
.word _ebss
[C1]中断向量表
[C2]各种中断后即进入死循环,除了复位中断
[C3]初始化堆栈起始位置
在makefile里即能查到该地址为0x304000
Arm9堆栈模式为满递减,即向址小的方向增长
后面会调用C函数,调用C前需要设好栈
[C4]PIOB:
PIO_PER=0X00200000
PIO_OER=0X00200000
PIO_CODR=0X00200000
即设置PB21使能、输出模式、端口清零,即点亮led
[C5]没有定义不分析
[C6]读AT91C_PMC_SR寄存器的值放到R1中
[C7]R1=r1&r2
即是AT91C_PMC_SR寄存器的值与AT91C_PMC_MOSCS位
即是检测片外主晶振是否稳定建立
[C8]Bne不为零即跳转
即是上面检测到片外晶振稳定AT91C_PMC_MOSCS位为1时跳转到
_switch_to_mosc [C8]代码段
[C9]AT91C_PMC_MOR=0x4001
AT91C_CKGR_MOSCEN表示全能外部时钟
0x40即是指定外部时钟建立时间:64*8个slow clock周期
[C10]循环检测AT91C_PMC_SR寄存器里的AT91C_PMC_MOSCS位,以检测外部时钟是否建立
相当于
While(!((*AT91C_PMC_SR)& AT91C_PMC_MOSCS)));
[C11](*AT91C_PMC_MCKR)& AT91C_PMC_CSS
[C12]AT91C_PMC_CSS不为零即跳到_init_bss
如果是Slow Clock is selected.就继续顺序执行
[C13]*AT91C_PMC_MCKR=
AT91C_PMC_CSS_MAIN_CLK| AT91C_PMC_PRES_CLK
AT91C_PMC_MCKR=0x0001
即选择片外时钟,且不分频12MHz
[C14]循环检测AT91C_PMC_MCKRDY位,即检测切换片外时钟是否成功。
[C15]建立时钟
[C16]初始化数据段
R1=_etext
R3=_sdata
R4=_edata
比较的r3和r4
如果r3<r4
则r1地址内容传给的R2 并且r1=r1+4 即地址递增4个字节
然后r2数据存储到r3地址中,且
R3=r3+4 ,即地址递增4个字节
如果r3<r4即循环继续
查看 编译完的map文件
_etext 和_sdata都为0x00301e48
符合lds链接文件
即将自个重新copy了一遍
[C17]程序理解同_init_data
将bss段全部清零
[C18]保存返回地址
跳转到main函数
[C19]保存返回地址
此时R0中即是JUMP_ADDR
即执行u-boot代码,并且形参为
MACH_TYPE