4.分析Makefile第一个文件start.S
引言:start.S是Makefile编译运行的第一个文件,它做了如下工作:
1.首先跳到reset
2.设置为管理模式
3.关看门狗
4.关中断
5.如果SDRAM没有初始化,就cpu初始化,这里跳到cpu_init_crit
6.设置存储器
7.初始化栈(为了使用c库)Set up the stack
8._TEXT_BASE=0x33F80000 设置链接地址
9.初始化时钟
10.重定位(把flash的代码重定位到SDRAM的链接地址上去)relocate U-Boot to RAM
11.清bss,所谓bss,就是初始值为0或没有赋值的静态变量或全局变量,清除,免得浪费空间,,在u-boot.lds有bss 第1-11点为u-boot的硬件初始化,为第一阶段
12.调用c函数start_armboot,这里实现u-boot更复杂的功能,为第二阶段,实现如串口,flash读写擦除,网卡,启动内核等功能
代码如下:(按1-12顺序跳读)
-
include <config.h>
-
#include <version.h>
-
-
.globl _start
-
_start: b reset //1.首先跳到reset --85行
-
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
-
-
_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
-
-
.balignl 16,0xdeadbeef
-
-
-
/*
-
*************************************************************************
-
*
-
* Startup Code (reset vector)
-
*
-
* do important init only if we don't start from memory!
-
* relocate armboot to ram
-
* setup stack
-
* jump to second stage
-
*
-
*************************************************************************
-
*/
-
-
_TEXT_BASE:
-
.word TEXT_BASE
-
-
.globl _armboot_start
-
_armboot_start:
-
.word _start
-
-
/*
-
* These are defined in the board-specific linker script.
-
*/
-
.globl _bss_start
-
_bss_start:
-
.word __bss_start
-
-
.globl _bss_end
-
_bss_end:
-
.word _end
-
-
.globl FREE_RAM_END
-
FREE_RAM_END:
-
.word 0x0badc0de
-
-
.globl FREE_RAM_SIZE
-
FREE_RAM_SIZE:
-
.word 0x0badc0de
-
-
.globl PreLoadedONRAM
-
PreLoadedONRAM:
-
.word 0
-
-
#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
-
-
-
/*
-
* the actual reset code
-
*/
-
-
reset:
-
/*
-
* set the cpu to SVC32 mode //2.设置为管理模式
-
*/
-
mrs r0,cpsr
-
bic r0,r0,#0x1f
-
orr r0,r0,#0xd3
-
msr cpsr,r0
-
-
/* turn off the watchdog */
-
#if defined(CONFIG_S3C2400)
-
# define pWTCON 0x15300000
-
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
-
# define CLKDIVN 0x14800014 /* clock divisor register */
-
#elif defined(CONFIG_S3C2410)
-
# define pWTCON 0x53000000
-
# define INTMOD 0X4A000004
-
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
-
# define INTSUBMSK 0x4A00001C
-
# define CLKDIVN 0x4C000014 /* clock divisor register */
-
#endif
-
-
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) //3.关看门狗
-
ldr r0, =pWTCON
-
mov r1, #0x0
-
str r1, [r0]
-
-
/*
-
* mask all IRQs by setting all bits in the INTMR - default //4.关中断
-
*/
-
mov r1, #0xffffffff
-
ldr r0, =INTMSK
-
str r1, [r0]
-
# if defined(CONFIG_S3C2410)
-
ldr r1, =0x3ff
-
ldr r0, =INTSUBMSK
-
str r1, [r0]
-
# endif
-
-
#if 0
-
/* FCLK:HCLK:PCLK = 1:2:4 */
-
/* default FCLK is 120 MHz ! */
-
ldr r0, =CLKDIVN
-
mov r1, #3
-
str r1, [r0]
-
#endif
-
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
-
-
/*
-
* we do sys-critical inits only at reboot,
-
* not when booting from ram!
-
*/
-
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-
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 */
-
blne cpu_init_crit //5.如果SDRAM没有初始化,就cpu初始化,这里跳到cpu_init_crit
-
#endif
-
-
/* 7.初始化栈(为了使用c库)Set up the stack 8._TEXT_BASE=0x33F80000 */
-
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 */
-
-
#ifdef CONFIG_USE_IRQ
-
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
-
#endif
-
sub sp, r0, #12 /* leave 3 words for abort-stack */
-
-
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-
bl clock_init //9.初始化时钟
-
#endif
-
-
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
-
relocate: /* 10.重定位(把flash的代码重定位到SDRAM的链接地址上去)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 clear_bss
-
-
ldr r2, _armboot_start
-
ldr r3, _bss_start
-
sub r2, r3, r2 /* r2 <- size of armboot */
-
#if 1
-
bl CopyCode2Ram /* r0: source, r1: dest, r2: size */
-
#else
-
add r2, r0, r2 /* r2 <- source end address */
-
-
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
-
#endif
-
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
-
-
clear_bss://11.清bss,所谓bss,就是初始值为0或没有赋值的静态变量或全局变量,清除,免得浪费空间,,在u-boot.lds有bss 第1-11点为u-boot的硬件初始化,为第一阶段
-
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
-
-
SetLoadFlag:
-
/* Set a global flag, PreLoadedONRAM */
-
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 */
-
ldr r2, =PreLoadedONRAM
-
mov r3, #1
-
streq r3, [r2]
-
-
#if 0
-
/* try doing this stuff after the relocation */
-
ldr r0, =pWTCON
-
mov r1, #0x0
-
str r1, [r0]
-
-
/*
-
* mask all IRQs by setting all bits in the INTMR - default
-
*/
-
mov r1, #0xffffffff
-
ldr r0, =INTMR
-
str r1, [r0]
-
-
/* FCLK:HCLK:PCLK = 1:2:4 */
-
/* default FCLK is 120 MHz ! */
-
ldr r0, =CLKDIVN
-
mov r1, #3
-
str r1, [r0]
-
/* END stuff after relocation */
-
#endif
-
-
ldr pc, _start_armboot
-
-
_start_armboot: .word start_armboot //12.调用c函数start_armboot,这里实现u-boot更复杂的功能,为第二阶段,实现如串口,flash读写擦除,网卡,启动内核等功能
-
-
-
/*
-
*************************************************************************
-
*
-
* CPU_init_critical registers
-
*
-
* setup important registers
-
* setup memory timing
-
*
-
*************************************************************************
-
*/
-
-
-
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-
cpu_init_crit:
-
/*
-
* flush v4 I/D caches
-
*/
-
mov r0, #0
-
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
-
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
-
-
/*
-
* disable MMU stuff and caches
-
*/
-
mrc p15, 0, r0, c1, c0, 0
-
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
-
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
-
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
-
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
-
mcr p15, 0, r0, c1, c0, 0
-
-
/*
-
* before relocating, we have to setup RAM timing
-
* because memory timing is board-dependend, you will
-
* find a lowlevel_init.S in your board directory.
-
*/
-
mov ip, lr
-
bl lowlevel_init //6.设置存储器
-
mov lr, ip
-
mov pc, lr
-
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
-
-
/*
-
*************************************************************************
-
*
-
* Interrupt handling
-
*
-
*************************************************************************
-
*/
-
-
@
-
@ IRQ stack frame.
-
@
-
#define S_FRAME_SIZE 72
-
-
#define S_OLD_R0 68
-
#define S_PSR 64
-
#define S_PC 60
-
#define S_LR 56
-
#define S_SP 52
-
-
#define S_IP 48
-
#define S_FP 44
-
#define S_R10 40
-
#define S_R9 36
-
#define S_R8 32
-
#define S_R7 28
-
#define S_R6 24
-
#define S_R5 20
-
#define S_R4 16
-
#define S_R3 12
-
#define S_R2 8
-
#define S_R1 4
-
#define S_R0 0
-
-
#define MODE_SVC 0x13
-
#define I_BIT 0x80
-
-
/*
-
* use bad_save_user_regs for abort/prefetch/undef/swi ...
-
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
-
*/
-
-
.macro bad_save_user_regs
-
sub sp, sp, #S_FRAME_SIZE
-
stmia sp, {r0 - r12} @ Calling r0-r12
-
ldr r2, _armboot_start
-
sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
-
sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
-
ldmia r2, {r2 - r3} @ get pc, cpsr
-
add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
-
-
add r5, sp, #S_SP
-
mov r1, lr
-
stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
-
mov r0, sp
-
.endm
-
-
.macro irq_save_user_regs
-
sub sp, sp, #S_FRAME_SIZE
-
stmia sp, {r0 - r12} @ Calling r0-r12
-
add r8, sp, #S_PC
-
stmdb r8, {sp, lr}^ @ Calling SP, LR
-
str lr, [r8, #0] @ Save calling PC
-
mrs r6, spsr
-
str r6, [r8, #4] @ Save CPSR
-
str r0, [r8, #8] @ Save OLD_R0
-
mov r0, sp
-
.endm
-
-
.macro irq_restore_user_regs
-
ldmia sp, {r0 - lr}^ @ Calling r0 - lr
-
mov r0, r0
-
ldr lr, [sp, #S_PC] @ Get PC
-
add sp, sp, #S_FRAME_SIZE
-
subs pc, lr, #4 @ return & move spsr_svc into cpsr
-
.endm
-
-
.macro get_bad_stack
-
ldr r13, _armboot_start @ setup our mode stack
-
sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
-
sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
-
-
str lr, [r13] @ save caller lr / spsr
-
mrs lr, spsr
-
str lr, [r13, #4]
-
-
mov r13, #MODE_SVC @ prepare SVC-Mode
-
@ msr spsr_c, r13
-
msr spsr, r13
-
mov lr, pc
-
movs pc, lr
-
.endm
-
-
.macro get_irq_stack @ setup IRQ stack
-
ldr sp, IRQ_STACK_START
-
.endm
-
-
.macro get_fiq_stack @ setup FIQ stack
-
ldr sp, FIQ_STACK_START
-
.endm
-
-
/*
-
* exception handlers
-
*/
-
.align 5
-
undefined_instruction:
-
get_bad_stack
-
bad_save_user_regs
-
bl do_undefined_instruction
-
-
.align 5
-
software_interrupt:
-
get_bad_stack
-
bad_save_user_regs
-
bl do_software_interrupt
-
-
.align 5
-
prefetch_abort:
-
get_bad_stack
-
bad_save_user_regs
-
bl do_prefetch_abort
-
-
.align 5
-
data_abort:
-
get_bad_stack
-
bad_save_user_regs
-
bl do_data_abort
-
-
.align 5
-
not_used:
-
get_bad_stack
-
bad_save_user_regs
-
bl do_not_used
-
-
@ thisway.diy, 2006.06.24
-
.globl Launch
-
.align 4
-
Launch:
-
mov r7, r0
-
@ diable interrupt
-
@ disable watch dog timer
-
mov r1, #0x53000000
-
mov r2, #0x0
-
str r2, [r1]
-
-
ldr r1,=INTMSK
-
ldr r2,=0xffffffff @ all interrupt disable
-
str r2,[r1]
-
-
ldr r1,=INTSUBMSK
-
ldr r2,=0x7ff @ all sub interrupt disable
-
str r2,[r1]
-
-
ldr r1, = INTMOD
-
mov r2, #0x0 @ set all interrupt as IRQ (not FIQ)
-
str r2, [r1]
-
-
@
-
mov ip, #0
-
mcr p15, 0, ip, c13, c0, 0 @ /* zero PID */
-
mcr p15, 0, ip, c7, c7, 0 @ /* invalidate I,D caches */
-
mcr p15, 0, ip, c7, c10, 4 @ /* drain write buffer */
-
mcr p15, 0, ip, c8, c7, 0 @ /* invalidate I,D TLBs */
-
mrc p15, 0, ip, c1, c0, 0 @ /* get control register */
-
bic ip, ip, #0x0001 @ /* disable MMU */
-
mcr p15, 0, ip, c1, c0, 0 @ /* write control register */
-
-
@ MMU_EnableICache
-
@mrc p15,0,r1,c1,c0,0
-
@orr r1,r1,#(1<<12)
-
@mcr p15,0,r1,c1,c0,0
-
-
@ clear SDRAM: the end of free mem(has wince on it now) to the end of SDRAM
-
ldr r3, FREE_RAM_END
-
ldr r4, =PHYS_SDRAM_1+PHYS_SDRAM_1_SIZE @ must clear all the memory unused to zero
-
mov r5, #0
-
-
ldr r1, _armboot_start
-
ldr r2, =On_Steppingstone
-
sub r2, r2, r1
-
mov pc, r2
-
On_Steppingstone:
-
2: stmia r3!, {r5}
-
cmp r3, r4
-
bne 2b
-
-
@ set sp = 0 on sys mode
-
mov sp, #0
-
-
@ add by thisway.diy 2006.06.26, switch to SVC mode
-
msr cpsr_c, #0xdf @ set the I-bit = 1, diable the IRQ interrupt
-
msr cpsr_c, #0xd3 @ set the I-bit = 1, diable the IRQ interrupt
-
ldr sp, =0x31ff5800
-
-
nop
-
nop
-
nop
-
nop
-
-
mov pc, r7 @ Jump to PhysicalAddress
-
nop
-
mov pc, lr
-
-
#ifdef CONFIG_USE_IRQ
-
-
.align 5
-
irq:
-
/* add by www.100ask.net to use IRQ for USB and DMA */
-
sub lr, lr, #4 @ the return address
-
ldr sp, IRQ_STACK_START @ the stack for irq
-
stmdb sp!, { r0-r12,lr } @ save registers
-
-
ldr lr, =int_return @ set the return addr
-
ldr pc, =IRQ_Handle @ call the isr
-
int_return:
-
ldmia sp!, { r0-r12,pc }^ @ return from interrupt
-
-
.align 5
-
fiq:
-
get_fiq_stack
-
/* someone ought to write a more effiction fiq_save_user_regs */
-
irq_save_user_regs
-
bl do_fiq
-
irq_restore_user_regs
-
-
#else
-
-
.align 5
-
irq:
-
get_bad_stack
-
bad_save_user_regs
-
bl do_irq
-
-
.align 5
-
fiq:
-
get_bad_stack
-
bad_save_user_regs
-
bl do_fiq
-
-
#endif