u-boot.lds의 ENTRY부분에서 _start로 제어가 넘겨졌었다.
이 _start는 start.S에 선언되어 있다.
start.S를
보도록 하자.
/*
* A EEEE SSSS OOO PPPP
* A A E
S O O P P
* AAAAA EEEE SSSS O O PPPP
* A
A E S O O P
* A A EEEE SSSS OOO P
*
*
An Entertainment Solution On a Platform (AESOP) is a completely Open
Source
* based graphical user environment and suite of
applications for PDAs and other
* devices running Linux. It is
included in various embedded Linux distributions
* such as
OpenZaurus - http://www.aesop-embedded.org
*
*
*
This program is free software; you can redistribute it and/or modify
*
it under the terms of the GNU General Public License as published by
*
the Free Software Foundation; either version 2 of the License, or
*
(at your option) any later version.
*
* This program is
distributed in the hope that it will be useful,
* but WITHOUT ANY
WARRANTY; without even the implied warranty of
* MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public
License for more details.
*
*
* Title : start.S
* Author
:
* Created date : 2005. 06. 26. 23:20:34 KST
* Description
:
*
* $Revision: 1.1.1.1 $
* $Log: start.S,v $
* Revision
1.1.1.1 2005/06/27 17:03:41 linuxpark
* Initial import.
*
*
*
*/
#ident "@(*) $Header:
/cvsroot/aesop-embedded/u-boot-aesop/cpu/arm920t/start.S,v 1.1.1.1
2005/06/27 17:03:41 linuxpark Exp $"
/*
* armboot - Startup Code for ARM920 CPU-core
*
*
Copyright (c) 2001 Marius Gr?er <mag@sysgo.de>
* Copyright (c)
2002 Alex Z?ke <azu@sysgo.de>
* Copyright (c)
2002 Gary Jennejohn <gj@denx.de>
* Copyright (c) 2005
Junyoung Song <jun0song@kornet.net>
*
*
See file CREDITS for list of people who contributed to this
*
project.
*
* This program is free software; you can redistribute
it and/or
* modify it under the terms of the GNU General Public
License as
* published by the Free Software Foundation; either
version 2 of
* the License, or (at your option) any later version.
*
*
This program is distributed in the hope that it will be useful,
*
but WITHOUT ANY WARRANTY; without even the implied warranty of
*
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU
General Public License for more details.
*
* You should have
received a copy of the GNU General Public License
* along with this
program; if not, write to the Free Software
* Foundation, Inc., 59
Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <version.h>
/*
*************************************************************************
*
*
Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/
.globl _start
_start: b reset /* exception의 처음인 0x00000000번지이다. 이 명령에 의해 reset로
branch한다. reset는 좀 더 아래에 선언되어있다.*/
ldr pc,
_undefined_instruction /* exception vector 설정 */
ldr pc,
_software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc,
_not_used
ldr pc, _irq
ldr pc, _fiq
/* exception vector의 위치 정의 word(4byte)로 정의한것.
*/
_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
#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
*/
/*******************************************************
* 5가지 동작을 한다.
* 1) CPU를 Supervisor mode로 set
2)interrupt를 disable
* 3)watchdog을 turn off 4)clock을 setting
5)memory를 setting
*/
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f // mode bit(하위 5bit)를 클리어 한다.
orr r0,r0,#0xd3 // interrupt를 disable, supervisor mode로 한다.
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) || defined(CONFIG_S3C2440)
/* 만약에 S3C2440이면 아래 정의된 주소로 레지스터가 잡힌다. 자세한
레지스터용도및 주소는 S3C2440의 데이터시트를 참조하세요*/
# define
pWTCON 0x53000000
# define INTMSK 0x4A000008 /* Interupt-Controller
base addresses */
# define INTSUBMSK 0x4A00001C
# define
CLKDIVN 0x4C000014 /* clock divisor register */
#endif
/* 2440이나 2410이면 아래와 같이 watchdog을 turn off하고
클럭을 셋팅한다는 내용이다. 필자의 대상보드는 2440이므로 분석 pass*/
#if
defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
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,
=INTMSK
str r1, [r0]
# if
defined(CONFIG_S3C2410) /* 2410일 경우 interrupt submask register를
masking한다. */
ldr r1, =0x3ff /* 11bit이므로 */
ldr r0, =INTSUBMSK
str r1,
[r0]
# endif
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0,
=CLKDIVN
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C2400 ||
CONFIG_S3C2410 */
/* 만약 2440이면 아래와 같이 watchdog을 turn off하고
클럭을 셋팅한다. 필자가 사용하는 보드가 나왔다. 분석 들어간다.역시 자세한 사항은 S3C2440의 데이터시트를 참조하길
바란다.*/
#if defined(CONFIG_S3C2440)
ldr r0, =pWTCON /* r0로 pWTCON이 들어있는 번지 로딩 */
mov r1,
#0x0 /* r1에 0을 넣고 */
str r1,
[r0] /* r1의 값을 r0가 가리키는 곳의 내용으로 넣는다. */
/* mask all IRQs by setting all bits in the
INTMR - default *//* 부팅시 방해될 수 있는 인터럽트를 마스크한다. */
mov r1,
#0xffffffff
ldr r0, =INTMSK /* INTMSK가 있는 번지
로딩 */
str r1, [r0] /* INTMSK가 있는 번지에
0xffffffff을 넣는다. */
ldr r1, =0x7fff /*
r1에 0x7fff이 있는 번지 로딩 */
ldr r0, =INTSUBMSK /* r0에 INTSUBMSK가 있는 번지 로딩 */
str r1,
[r0] /* INTSUBMSK가 있는 번지에 0x7fff를 넣는다. */
/* FCLK:HCLK:PCLK = 1:3:6 */ @ clock setting
/*
default FCLK is 379.2 MHz ! */
ldr r0, =CLKDIVN @ CLKDIVN의 주소 0x4C000014
mov r1, #7 /* #7 = 0b0111, HDIVN = 3,
PDIVN = 1
str r1, [r0] /* FCLK :
HCLK : PCLK = 379.2 : 379.2/3 : 379.2/6
/* ghcstop add, ==> Clock asynchronous mode */
mrc
p15, 0, r1, c1, c0, 0 /* read ctrl
register */
orr r1, r1, #0xc0000000
mcr p15, 0, r1, c1, c0, 0 /* write ctrl register */
#endif /* CONFIG_S3C2440 */
/*
* we do sys-critical inits only at reboot,
* not when
booting from ram!
*/
#ifdef CONFIG_INIT_CRITICAL
bl cpu_init_crit /*
cpu_init_crit 서브루틴을 호출한다. cpu_init_crit는 좀 더 아래에 선언되어 있다.*/
#endif
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
/* memsetup.s 에서 복귀하여 armboot를 ram으로 재배치한다. */
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
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /*
r2 <- size of armboot */
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
/* Set up the stack */
stack_setup: /* stackpoint를 설정. */
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 */
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
bne clbss_l
#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 /* Board.c에 포함되어 있는
_start_armboot함수로 branch한다. 실제 위치는 아래 선언된 start_armboot의 위치이다. 여기서
start.s의 동작은 완료되고 이제 RAM에서 남은 부팅절차가 수행된다. */
_start_armboot: .word
start_armboot
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
/* @
************************************************************************* @
* @
*
CPU_init_critical registers
*
* setup important registers
*
setup memory timing
*
*************************************************************************
*/
/* 이 루틴에서 p15는 CP15(coprocessor)를 말하고, c0~c15는 해당 coprocessor의
register를 말하는 것이다. */
/* mcr은 register to coprocessor, mrc는
coprocessor to register */
cpu_init_crit:
/*
* flush v4 I/D caches
*/
mov r0, #0 /* flush : 기억장치 내부의 내용을 지우는 것. 자세한 사항은 S3C2440의 데이터시트를
참조하길 바란다.*/
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
memsetup.S in your board directory.
*/
mov ip, lr /* 다시 bl을 이용하므로 lr을 ip레지스터로 이동. */
bl memsetup /* memsetup을 호출
-> go to the memsetup.s 여기에서 memsetup.s로 제어가 넘어간다. memsetup.s는
/board/aesop2440/에 위치해있다. memsetup은 다음 포스트에 올리겠다. 넘어가보자. */
mov lr,
ip /* 서브루틴을 요청햇던 곳으로 이동하기 위해서 ip값을 lr레지스터로
이동. */
mov pc, lr /* 서브루틴을 호출한 곳으로 복귀. 위쪽 reset의 마지막 부분이었다. */
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
/*
*************************************************************************
*
*
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
#ifdef CONFIG_USE_IRQ
.align 5
irq:
get_irq_stack
irq_save_user_regs
bl
do_irq
irq_restore_user_regs
.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
.align 5
.globl reset_cpu
reset_cpu:
#ifdef CONFIG_S3C2400
bl disable_interrupts
#
ifdef CONFIG_TRAB
bl disable_vfd
# endif
ldr r1, _rWTCON
ldr r2,
_rWTCNT
/* Disable watchdog */
mov r3, #0x0000
str r3, [r1]
/*
Initialize watchdog timer count register */
mov r3, #0x0001
str r3,
[r2]
/* Enable watchdog timer; assert reset at timer timeout */
mov r3,
#0x0021
str r3, [r1]
_loop_forever:
b _loop_forever
_rWTCON:
.word 0x15300000
_rWTCNT:
.word 0x15300008
#else
/* ! CONFIG_S3C2400 */
mov ip, #0
mcr p15, 0, ip, c7,
c7, 0 @ invalidate cache
mcr p15, 0, ip, c8, c7,
0 @ flush TLB (v4)
mrc p15, 0, ip, c1, c0, 0
@ get ctrl register
bic ip, ip, #0x000f @
............wcam
bic ip, ip, #0x2100 @
..v....s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl
register
mov pc, r0
#endif /* CONFIG_S3C2400 */
---------------
출처 : http://blog.naver.com/idrukawa/100054113199