天天看点

s3c2440启动BL1代码

//start.S
.text
.global _start
_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

undefined_instruction:
    nop
software_interrupt:
    nop
prefetch_abort:
    nop
data_abort:
    nop
not_used:
    nop
irq:
    nop
fiq:
    nop

reset:
    bl set_svc
    bl disable_watchdog
    bl disable_interrupt
    bl disable_mmu  
    bl clock_init   
    bl init_sdram   
    bl copy_to_ram
    bl init_stack
    bl clean_bss
    ldr pc,=gboot_main   @ go to C function
    @bl light_led



set_svc:
    mrs r0,cpsr
    bic r0,r0,#0x1f
    orr r0,r0,#0xd3
    msr cpsr,r0

    mov pc,lr

#define pWTCON 0x53000000
disable_watchdog:
    ldr r0,=pWTCON
    mov r1,#0x00
    str r1,[r0]

    mov pc,lr

disable_interrupt:
@ set cpsr I&F
    mrs r0,cpsr
    orr r0,r0,#0xc0
    msr cpsr,r0

    mov pc,lr

@ set MASK
    mvn r1,#0x00
    ldr r0,=
    str r1,[r0]

    mov pc,lr

disable_mmu:
    @ disable I/D cache
    mcr p15,,r0,c7,c7,

    @ read p15 to r0
    mrc p15,,r0,c1,c0,
    @ modify r0
    bic r0,r0,#0x00000007
    @ write r0 to p15
    mcr p15,,r0,c1,c0, 

    mov pc,lr

#define CLKDIVN 0x4c000014
#define MPLLCON 0x4c000004   
#define MPLL_405MHz ((127<<12)|(2<<4)|(1<<0))
clock_init:
    @ set FCLK:HCLK:PCLK = ::
    ldr r0,=CLKDIVN
    mov r1,#0x5
    str r1,[r0]

    @MMU_setAsyncBusMode
    mrc p15,,r0,c1,c0,
    orr r0,r0,#0xc0000000
    mcr p15,,r0,c1,c0,

    @ set FCLK = MHz
    ldr r0,=MPLLCON
    ldr r1,=MPLL_405MHz
    str r1,[r0]
    mov pc,lr

#define mem_contrl 0x48000000
init_sdram:
    ldr r0,=mem_contrl
    add r3,r0,#4*13
    adrl r1,mem_data

@ use loop to realize   
:
    ldr r2,[r1],#4
    str r2,[r0],#4
    cmp r0,r3
    bne b           @ if r0 != r3 ,jump to before

    mov pc,lr

mem_data:
    .long    @BWSCON
    .long    @BANKCON0
    .long    @BANKCON1
    .long    @BANKCON2
    .long    @BANKCON3
    .long    @BANKCON4
    .long    @BANKCON5
    .long    @BANKCON6
    .long    @BANKCON7
    .long    @REFRESH
    .long    @BANKSIZE
    .long    @MRSRB6
    .long    @MRSRB7


#define GPBCON 0x56000010
#define GPBDAT 0x56000014

light_led:
    ldr r0,=GPBCON
    ldr r1,=
    str r1,[r0]

    ldr r0,=GPBDAT
    ldr r1,=
    str r1,[r0] 

    mov pc,lr

copy_to_ram:
    ldr r0,=
    ldr r1,=
    add r3,r0,#4*1024

copy_loop:
    ldr r2,[r0],#4
    str r2,[r1],#4
    cmp r0,r3
    bne copy_loop

    mov pc,lr

@  + MB()
init_stack:
    ldr sp,=
    mov pc,lr

clean_bss:
    ldr r0,=bss_start
    ldr r1,=bss_end
    cmp r0,r1
    moveq pc,lr          @ r0 == r1 ,back 
clean_loop:
    mov r2,#0
    str r2,[r0],#4
    cmp r0,r1
    bne clean_loop       @ r0 != r1 ,loop
    mov pc,lr
           
//main.c
int gboot_main()
{
    ...
    return ;
}
           
//gboot.lds

OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
    . = ;
    . = ALIGN();
    .text :
    {
        start.o(.text)
        *(.text)
    }
    . = ALIGN();
    .data :
    {
        *(data)
    }

    . = ALIGN();
    bss_start = .;
    .bss :
    {
        *(.bss)
    }
    bss_end = .;

}

           
//Makefile

all: start.o main.o
    arm-linux-ld -T gboot.lds -o gboot.elf $^
    arm-linux-objcopy -O binary gboot.elf gboot.bin

%.o: %.S
    arm-linux-gcc -nostdlib -g -c $^
%.o: %.c
    arm-linux-gcc -nostdlib -g -c $^


.PHONY: clean
clean:
    rm *.o *.elf *.bin
           

在Makefile文件中,如果没有 -nostdlib ,则会出现:

[[email protected] example]# make
arm-linux-gcc -g -c start.S
arm-linux-gcc -g -c main.c
arm-linux-ld -Tgboot.lds -o gboot.elf start.o main.o
main.o:(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr0'
make: *** [all] 错误 1
           

问题解决:arm-none-linux-gnueabi-gcc加上-nostdlib选项即可

机理

-nostdlib

不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。

这个选项常用于编译内核、bootloader等程序,它们不需要启动文件、标准库文件。

C语言程序执行的第一条指令。并不是main函数。生产一个C程序的可执行文件时编译器通常会在我们的代码上加几个被称为启动文件的代码–crt1.o、crti.o、

crtend.o等,他们是标准库文件。这些代码设置C程序的堆栈等,然后调用main函数。他么依赖于操作系统,在裸板上无法执行,所以我们自己写一个。

问题已经找到答案了,我们自己写的crt0.S就是一个启动文件,他设置好堆栈后调用main函数。因此,我们不需要系统自带的启动文件。