1. S3C2440大概的启动流程(NAND启动):
①设置CPU为SVC模式
②关闭看门狗
③屏蔽中断
④关闭MMU
⑤初始化时钟
⑥初始化内存(SDRAM)
⑦初始化栈指针(SP, R13)
⑧初始化NAND Flash
⑨拷贝代码从NAND到内存
⑩清除BSS段
最后,跳转至C语言的Main函数执行
2. 汇编语言源代码
.text
.global _start
_start:
b reset
ldr pc, _undifined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undifined_instruction: .word undifined_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 reset
undifined_instruction:
nop
software_interrupt:
nop
prefetch_abort:
nop
data_abort:
nop
not_used:
nop
irq:
sub lr, lr, #4
stmfd sp!, {r0-r12, lr} /* Save envrionment */
bl HandleIrq
ldmfd sp!, {r0-r12, pc}^ /* Recover envrionment, ^ take spsr to cpsr */
fiq:
nop
.global reset
reset:
bl set_svc
bl disable_watchdog
bl disable_interrupt
bl disable_mmu
bl init_clock
bl init_sdram
bl init_stack
bl nandflash_init
bl light_led
bl copy_to_ram
bl clean_bss
ldr pc, =gboot_main
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, #0x0
str r1, [r0]
mov pc, lr
disable_interrupt:
mvn r1, #0x0
ldr r0, =0x4a000008
str r1, [r0]
mov pc, lr
disable_mmu:
mcr p15,0,r0,c7,c7,0
mrc p15,0,r0,c1,c0,0
bic r0, r0, #0x00000007
mcr p15,0,r0,c1,c0,0
mov pc, lr
#define CLKDIVN 0x4c000014
#define MPLLCON 0x4c000004
#define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0))
init_clock:
ldr r0, =CLKDIVN
mov r1, #0x5 //FCLK : HCLK : PCLK = 1 : 4 : 8(Divide Ratio)
str r1, [r0]
mcr p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000
mcr p15,0,r0,c1,c0,0
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
0:
ldr r2, [r1], #4
str r2, [r0], #4
cmp r0, r3
bne 0b
mov pc, lr
#define copy_length 0x350000
copy_to_ram:
mov r0,#0x00
ldr r1,=_start
ldr r2,=EFI_driver_end
sub r2,r2,r1
mov ip,lr
bl nand_to_ram
mov lr,ip
mov pc,lr
init_stack:
msr cpsr_c, #0xd2 //Switch irq mode and set sps
ldr sp, =0x33000000
msr cpsr_c, #0xd3 //Switch back to SVC
ldr sp, =0x34000000
mov pc ,lr
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
cmp r0, r1
moveq pc, lr
clean_loop:
mov r2, #0
str r2, [r0], #4
cmp r0, r1
bne clean_loop
mov pc, lr
mem_data:
.long 0x22000000
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00018001
.long 0x00018001
.long 0x008c04f5
.long 0x000000b1
.long 0x00000030
.long 0x00000030
#define GPBCON 0x56000010
#define GPBDAT 0x56000014
light_led:
ldr r0, =GPBCON
mov r1, #0x400
str r1, [r0]
ldr r0, =GPBDAT
mov r1, #0x0
str r1, [r0]
mov pc, lr
3. 链接器脚本
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS {
. = 0x30004000;
. = ALIGN(4);
.text :
{
start.o (.text)
*(.text)
}
. = ALIGN(4);
.data :
{
*(.data)
}
. = ALIGN(4);
bss_start = .;
.bss :
{
*(.bss)
}
bss_end = .;
. = ALIGN(4);
boot_cmd_start = .;
.boot_cmd :
{
*(.boot_cmd)
}
boot_cmd_end = .;
. = ALIGN(4);
EFI_driver_start = .;
.EFI_driver :
{
*(.EFI_driver)
}
EFI_driver_end = .;
}
4. Makefile
CC := arm-linux-gcc
LD := arm-linux-ld
OBJCOPY := arm-linux-objcopy
CFLAGS := -fno-builtin -I$(shell pwd)/Include
export CFLAGS
all: start.o main.o Core/Core.o CommonLib/CommonLib.o Driver/Driver.o Test/Test.o Net/Net.o
arm-linux-ld -Tgboot.lds -o gboot.elf $^ -L /usr/local/arm/4.3.2/lib/gcc/arm-none-linux-gnueabi/4.3.2/armv4t -lgcc
arm-linux-objcopy -O binary gboot.elf gboot.bin
%.o : %.S
arm-linux-gcc -g -c $^
%.o : %.c
arm-linux-gcc $(CFLAGS) -g -c $^
Core/Core.o :
make -C Core all
Driver/Driver.o :
make -C Driver all
CommonLib/CommonLib.o :
make -C CommonLib all
Test/Test.o :
make -C Test all
Net/Net.o :
make -C Net all
.PHONY: clean
clean:
make -C Driver clean
make -C CommonLib clean
make -C Test clean
make -C Core clean
make -C Net clean
rm *.o *.elf *.bin