第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > 三星uboot1.1.6源码分析——start.s(1)

三星uboot1.1.6源码分析——start.s(1)

时间:2020-02-05 11:00:04

相关推荐

三星uboot1.1.6源码分析——start.s(1)

虽然,分析start.s的文件在网上已经很多,但还是在这里对自己的分析做个记录,方便以后查看。

现在开始:

#include <config.h>

#include <version.h>

#ifdef CONFIG_ENABLE_MMU

#include <asm/proc/domain.h>

#endif

#include <regs.h>

#ifndef CONFIG_ENABLE_MMU 我们定义了#define CONFIG_ENABLE_MMU,所以这些用不到

#ifndef CFG_PHY_UBOOT_BASE

#define CFG_PHY_UBOOT_BASE CFG_UBOOT_BASE

#endif

#endif

上面这些宏的定义都在Smdk6410.h (include\configs)文件中,如下所示:

/* base address for uboot */

#ifdef CONFIG_ENABLE_MMU

#defineCFG_UBOOT_BASE 0xc7e00000

#else

#define CFG_UBOOT_BASE 0x57e00000

#endif

#define CFG_PHY_UBOOT_BASE MEMORY_BASE_ADDRESS + 0x7e00000

#define MEMORY_BASE_ADDRESS0x50000000

所以上面的CFG_PHY_UBOOT_BASE为0x57e00000

CFG_UBOOT_BASE为0xc7e00000

/*

*************************************************************************

*

* Jump vector table as in table 3.1 in [1]

*

*************************************************************************

*/

.globl _start在链接文件有如下内容:

---------------------------------------------------------------

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS

{

. = 0x00000000;

. = ALIGN(4);

.text :

{

cpu/s3c64xx/start.o(.text)

---------------------------------------------------------------

_start: b reset

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

_pad:

.word 0x12345678 /* now 16*4=64 */

.global _end_vect

_end_vect:

.balignl 16,0xdeadbeef

/*

--------------------------------------------------------------------------------------------------------------

上面这些就都不说了,网上有很多这上面的资料,讲的都很详细,忘记了再查。不过这些undefined_instruction、data_abort等在本文件的后面都有定义,我在前面把他们粘贴在下面,方便查看,如下所示:

/*

* exception handlers

*/

.align 5

undefined_instruction:

get_bad_stack

bad_save_user_regs

bl do_undefined_instruction

.align 5

software_interrupt:

get_bad_stack_swi

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 我们没有定义:#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */

.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

--------------------------------------------------------------------------------

1、其中get_bad_stack也在同一个文件中,如下所示:

.macro get_bad_stack

ldrr13, _armboot_start@ setup our mode stack (enter in banked mode)

其中有如下定义:

.globl _armboot_start

_armboot_start:

.word _start

subr13, r13, #(CFG_MALLOC_LEN)@ move past malloc pool

subr13, r13, #(CFG_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack

strlr, [r13]@ save caller lr in position 0 of saved stack

mrslr, spsr@ get the spsr

strlr, [r13, #4]@ save spsr in position 1 of saved stack

movr13, #MODE_SVC@ prepare SVC-Mode

@ msr spsr_c, r13

msr spsr, r13@ switch modes, make sure moves will execute

movlr, pc@ capture return pc

movspc, lr@ jump to next instruction & switch modes.

.endm

这个宏的功能应该是得到对应异常的堆栈指针。

2、其中bad_save_user_regs也在同一个文件中,如下所示:

/*

* use bad_save_user_regs for abort/prefetch/undef/swi ...

* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling

*/

下面这一段汇编代码还是很好理解的,最困难的可能就是stmia和ldmia这两个指令了,不过我在另外一篇我转载的博客中有很好的从实例中分析了这两个指令的用法。一看就能明了。

.macro bad_save_user_regs

sub sp, sp, #S_FRAME_SIZE@ carve out a frame on current user stack

其中有定义:#define S_FRAME_SIZE72

stmia sp, {r0 - r12}@ Save user registers (now in svc mode) r0-r12

ldr r2, _armboot_start

sub r2, r2, #(CFG_MALLOC_LEN)

sub r2, r2, #(CFG_GBL_DATA_SIZE+8)@ set base 2 words into abort stack

ldmia r2, {r2 - r3}@ get values for "aborted" pc and cpsr (into parm regs)

add r0, sp, #S_FRAME_SIZE@ grab pointer to old stack

add r5, sp, #S_SP

mov r1, lr

stmia r5, {r0 - r3}@ save sp_SVC, lr_SVC, pc, cpsr

mov r0, sp@ save current stack into r0 (param register)

.endm

其实这个宏的主要作用就是保存下面这些寄存器的内容,如下所示:

#define S_OLD_R068

#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

.macro irq_save_user_regs 和上面的作用差不多

sub sp, sp, #S_FRAME_SIZE

stmia sp, {r0 - r12}@ Calling r0-r12

add r8, sp, #S_PC@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.

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

3、

再来说说do_software_interrupt、do_data_abort等等类似与这些又在那里定义的呢?

它们都定义在:Interrupts.c (cpu\s3c64xx)文件中,如下所示:

void do_undefined_instruction(struct pt_regs *pt_regs)

{

printf("undefined instruction\n");

show_regs(pt_regs);

bad_mode();

}

void do_software_interrupt(struct pt_regs *pt_regs)

{

printf("software interrupt\n");

show_regs(pt_regs);

bad_mode();

}

void do_prefetch_abort(struct pt_regs *pt_regs)

{

printf("prefetch abort\n");

show_regs(pt_regs);

bad_mode();

}

void do_data_abort(struct pt_regs *pt_regs)

{

printf("data abort\n");

show_regs(pt_regs);

bad_mode();

}

void do_not_used(struct pt_regs *pt_regs)

{

printf("not used\n");

show_regs(pt_regs);

bad_mode();

}

void do_fiq(struct pt_regs *pt_regs)

{

printf("fast interrupt request\n");

show_regs(pt_regs);

bad_mode();

}

void do_irq(struct pt_regs *pt_regs)

{

printf("interrupt request\n");

show_regs(pt_regs);

bad_mode();

}

-------------------------------------------

其中又有

void bad_mode(void)

{

panic("Resetting CPU ...\n");

reset_cpu(0);

}

/* * reset the cpu by setting up the watchdog timer and let him time out */

void reset_cpu(ulong ignored)

{

printf("reset... \n\n\n");

#if defined(CONFIG_S3C6400)

SW_RST_REG = 0x6400;

#elif defined(CONFIG_S3C6410)

SW_RST_REG = 0x6410;

#elif defined(CONFIG_S3C6430)

SW_RST_REG = 0x6410;

#endif

/* loop forever and wait for reset to happen */

while (1)

{

if (serial_tstc())

{

serial_getc();

break;

}

}

/*NOTREACHED*/

}

---------------------------------------------------------------

好了这篇就说到这里了,下篇继续。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。