//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函数。因此,我们不需要系统自带的启动文件。