一.存储八个异常跳转表,以及七个异常地址,一个内存标志,deadbeef 表示以上内存禁止操作
.globl _start _start: b start_code 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 .balignl 16,0xdeadbeef
二.存储地址标号变量,比如 bss_start ,_start 标号的地址。
_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三.开始代码:
1.使cpu进入svc模式
mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr, r0
2.关闭看门狗。
ldr r0, =pWTCON mov r1, #0x0 str r1, [r0]
3.关中断,以及子中断。
mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] # if defined(CONFIG_S3C2410) ldr r1, =0x7ff ldr r0, =INTSUBMSK str r1, [r0] # endif #if defined(CONFIG_S3C2440) ldr r1, =0x7fff ldr r0, =INTSUBMSK str r1, [r0] #endif
4.设置时钟寄存器,使 FCLK = 400M HCLK = 100M PCLK = 50M
/* FCLK:HCLK:PCLK = 1:4:8 */ ldr r0, =CLKDIVN mov r1, #5 str r1, [r0] mrc p15, 0, r1, c1, c0, 0 orr r1, r1, #0xc0000000 mcr p15, 0, r1, c1, c0, 0 mov r1, #CLK_CTL_BASE mov r2, #MDIV_405 add r2, r2, #PSDIV_405 str r2, [r1, #0x04] /* MPLLCON tekkaman */5.初始化内存以及MMU,进入cpu_init_crit函数
(1) 使数据cache和指令cache无效
mov r0, #0 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
(2) 关闭MMU
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
(3) 进入lowlevel_init.S, 初始化内存。因为内存所用芯片是与开发板有关,所以这个文件在/board里面
mov ip, lr bl lowlevel_init
6.判断代码位置,比较_start 的地址和 _TEXT_BASE 是否相同,如果相同说明代码是在内存中,否则就在内部RAM中,或者NorFlash中.
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_setup7.判断启动方式,采用读取BWSCON寄存器中内容的方式,是NANDFALSH或者NARFLASH启动是由引脚OM【1:0】决定的,而他们的状态影响 BWSCON【2:1】,
如果OM【1:0】=00,BWSCON【2:1】=00,为NANDFLASH启动,否则为NORFLASH启动.
#define rBWSCON 0x48000000 mov r0, #rBWSCON ldr r0, [r0] bic r0, r0, #0xfffffff5 /* BWSCON[2:1] is controled by OM[1:0] */ cmp r0, #0 /* when OM[1:0] is 00,BSWCON[2:1]=00, nand flash boot */ bne relocate /* norflash boot */四.复制代码到内存
(1) 复位NANDFLASH,初始化堆栈指针,为进入C函数做好准备。
#define LENGTH_UBOOT 0x60000 #define NAND_CTL_BASE 0x4E000000 #ifdef CONFIG_S3C2440 /* Offset */ #define oNFCONF 0x00 #define oNFCONT 0x04 #define oNFCMD 0x08 #define oNFSTAT 0x20 @ reset NAND mov r1, #NAND_CTL_BASE ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) ) str r2, [r1, #oNFCONF] ldr r2, [r1, #oNFCONF] ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control str r2, [r1, #oNFCONT] ldr r2, [r1, #oNFCONT] ldr r2, =(0x6) @ RnB Clear str r2, [r1, #oNFSTAT] ldr r2, [r1, #oNFSTAT] mov r2, #0xff @ RESET command strb r2, [r1, #oNFCMD] mov r3, #0 @ wait nand1: add r3, r3, #0x1 cmp r3, #0xa blt nand1 nand2: ldr r2, [r1, #oNFSTAT] @ wait ready tst r2, #0x4 beq nand2 ldr r2, [r1, #oNFCONT] orr r2, r2, #0x2 @ Flash Memory Chip Disable str r2, [r1, #oNFCONT] @ get read to call C functions (for nand_read()) ldr sp, DW_STACK_START @ setup stack pointer mov fp, #0 @ no previous frame, so fp=0 @ copy U-Boot to RAM ldr r0, =TEXT_BASE mov r1, #0x0 mov r2, #LENGTH_UBOOT
(2) 调用/board/chuangwaiyuntian/mini2440/nand_read.c 中的 nand_read_ll 函数将u-boot 复制到内存。
bl nand_read_ll
(3) 验证是否复制成功,主要检查在地址0x0 和地址_TEXT_BASE处的以后4K代码是否完全一样。如果一样就正常执行,否则死在这里了。
bad_nand_read: loop2: b loop2 @ infinite loop ok_nand_read: @ verify mov r0, #0 ldr r1, =TEXT_BASE mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes go_next: ldr r3, [r0], #4 ldr r4, [r1], #4 teq r3, r4 bne notmatch subs r2, r2, #4 beq stack_setup bne go_next notmatch: loop3: b loop3 @ infinite loop2 NORFLASH启动
(1) 简单的拷贝代码
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
五.初始化堆栈,就是将堆栈指针指向一个确切的地址
stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ sub r0, r0, #CONFIG_SYS_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 */
六.清除bss段
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 ble clbss_l
七.跳转到第二阶段的 start_armboot 函数执行。
ldr pc, _start_armboot _start_armboot: .word start_armboot