uboot源码阅读(三)江湖的历史 uboot第一阶段start.S

时间:2022-01-25 15:07:36

有江湖的地方就会的历史,忘记历史就意味着背叛。每天打打杀杀,如果不小心就会有人在背后给自己来一刀,这就是背叛的滋味。不要忘记历史,这是前人的血的教训。

cpu/s3c64xx/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
#ifndef CFG_PHY_UBOOT_BASE
#define CFG_PHY_UBOOT_BASE      CFG_UBOOT_BASE
#endif
#endif

/*
* ARM处理器为特殊的任务或者专门的功能指定了3个寄存器:r13,r14,r15.
* 寄存器r13通常用作堆栈指针(sp),保存当前处理器模式的堆栈的栈顶。
* 寄存器r14又被称为连接寄存器(lr),保存调用子程序的返回地址。
* 寄存器r15是程序计数器(pc),其内容是处理器要取的下一条指令的地址。
* 两个状态寄存器:cpsr和spsr,分别是当前和备份的程序状态寄存器。
*/

/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */
/*
* ARM分支指令可以改变程序的执行流程或者调用子程序。这种指令使得一个程序可以使用子程序、if-then-else
* 结构及循环。执行流程的改变迫使程序计数器PC指向一个新的地址。
* B{<cond>}     lable     跳转  pc=lable
* BL{<cond>}    lable   带返回的跳转  pc=lable,lr=BL后面的第一条指令地址
* BX{<cond>}    Rm   跳转并切换状态 PC = Rm & 0xfffffffe,T=Rm&1
* BLX{<cond>}   lable | Rm 带返回的跳转并切换状态  pc = lable, T =1 pc =Rm & 0xfffffffe,T=Rm&1 lr=BLX后面的第一条指令地址
* 地址lable以一个有符号的相对于pc的偏移量保存在指令中,必须被限制在分支指令的约32MB范围内。T对应于cpsr中的Thumb位,如果指令设
* 置了T,那么ARM切换到Thumb状态。
*/
/*
* ldr属于load-store指令,它用于在存储器和处理器寄存器之间传输数据。load-store指令有三种类型:单寄存器传输指令
* 多寄存器传输指令和交换指令;
* 单寄存器传输指令用于把单个的数据传入或者传出一个寄存器。
* ldr/str  <cond> {B} Rd, addressing1 其中ldr是把一个字装入一个寄存器: Rd <--mem32[address];str是从一个寄存器保存一个字或者一个字节 Rd -->mem32[address]
*/
.globl _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所在的地址处放入四字节的数据,这个数据就是undefined_instruction标号
* 的地址.意思就是说在当前_undefined_instruction对应的地址中放的是undefined_instruction的地址
*/
/*
.word伪操作用于分配一段字内存单元(分配的单元都是字对齐的),并用伪操作中的expr初始化。.long和.int作用与之相同。
*/
_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
/*
 *************************************************************************
 *
 * Startup Code (reset vector)
 *
 * do important init only if we don't start from memory!
 * setup Memory and board specific bits prior to relocation.
 * relocate armboot to ram
 * setup stack
 *
 *************************************************************************
 */
/* 
* TEXT_BASE 在/board/config.mk文档中定义, 他定义了代码在运行时所在的地址, _TEXT_BASE中保存了这个地址
*/
_TEXT_BASE:
        .word   TEXT_BASE

/*
 * Below variable is very important because we use MMU in U-Boot.
 * Without it, we cannot run code correctly before MMU is ON.
 * by scsuh.
 */
_TEXT_PHY_BASE:
        .word   CFG_PHY_UBOOT_BASE

.globl _armboot_start/*声明全局标志. 声明的该标号_armboot_start可以被外部使用*/
_armboot_start:
        .word _start

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start /*预处理标号  目的:让_bss_start指向__bss_start标号所在的地址*/
_bss_start:
        .word __bss_start  /*在当前标号_bss_start所在的地址处放入__bss_start标号的地址*/ 

.globl _bss_end/*预处理标号 目的:让_bss_end指向_end标号所在的地址*/
_bss_end:
        .word _end

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START /*预处理标号 目的:让IRQ_STACK_START指向地址0x0badc0de(这个需要根据硬件更改)*/ 
IRQ_STACK_START:
        .word   0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
        .word 0x0badc0de
#endif

/*
 * the actual reset code
 */
/*
* 复位向量是处理器上电后执行的第一条指令的位置。这条指令使处理器跳转到初始化代码处。
*/
/*
* 处理器模式决定了哪些寄存器是活动的以及对cpsr的访问权。处理器复位时则进入到管理模式(Supervisor,SVC)
*/
reset:
        /*
         * set the cpu to SVC32 mode
         */
     /*
 * ARM指令集提供了2条指令,可以直接控制程序状态寄存器(psr)。MRS指令用于把cpsr或者spsr的值传送到一个寄存器。
 * MSR与MRS相反,把一个寄存器的内容传送到cpsr或者spsr。这两条指令可用于对cpsr和spsr进行读/写操作。
 */
        mrs     r0,cpsr
        bic     r0,r0,#0x1f /*EC: 模式位清零*//*bic是位清零(Bit Clear)指令,本语句是把r0的Bit[4:0]位清零(由0x1F指示),然后把结果写入r0中。*/
        orr     r0,r0,#0xd3 /*EC: 工作模式位设置为10011,为管理模式,irq fiq设置为1,屏蔽中断*/
                    /*orr指令是按位求或,本语句是r0的 Bit7,Bit6,Bit4,Bit1,Bit0 置为1,其它位保持不变。*/
        msr     cpsr,r0/*把寄存器r0的值传送到cpsr(当前程序状态寄存器)*/
/*执行完上述操作后,cpsr中的 I=1, F=1, T保持不变(默认为0),M[4:0]=10011,意思是禁止IRQ,禁止FIQ,工作在ARM状态,工作在SVC32模式。*/
/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */
         /*
         * we do sys-critical inits only at reboot,
         * not when booting from ram!
         */
cpu_init_crit:
        /*
         * flush v4 I/D caches
         *//*数据处理指令对于存放在寄存器中的数据进行操作。*/
        mov     r0, #0
/*协处理器指令用于扩展指令集P协处理器指令可用于提供附加的计算能力,有可用于控制包括cache和内存
 * 管理的存储子系统。协处理器指令包括数据处理指令,寄存器传输指令及内存传输指令。协处理器指令只用于带
 * 有协处理器的ARM内核。
 * CDP {<cond>} cp, opcode1, Cd, Cn{,opcode2}  协处理器数据处理 -- 在协处理器内部执行一个数据处理操作
 * <MRC/MCR> {<cond>} cp, opcode1, Rd, Cn, Cm{,opcode2} 协处理器寄存器传输 -- 把数据送入/取出协处理器寄存器
 * <LDC/STC> {<cod>} cp, Cd, addressing  协处理器内存比较 -- 从协处理器装载/存储一个内存数据块
 * 其中:cp域代表协处理器的编号,为p0~P15. opcode域描述要在协处理器中进行的操作。Cn, Cm及Cd描述在协处理器中的寄存器。
 * 协处理器15(CP15)是为系统控制预留的,如内存管理,写缓冲控制,cache控制及寄存器识别等。
 * MRC p15,0,r10,c0,c0,0 把协处理器15寄存器c0的内容拷贝到r10中,cp15寄存器c0中包含处理器标识,其内容拷贝到通用寄存器r10
 */ 
        mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
        mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */

        /*
         * disable MMU stuff and caches
         */
        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

        /* Peri port setup */
        ldr     r0, =0x70000000
        orr     r0, r0, #0x13
        mcr     p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)

#ifdef CONFIG_BOOT_ONENAND
        ldr     r0, =0x70000000         @ onenand controller setup
        orr     r0, r0, #0x100000
        ldr     r1, =0x4000
        orr     r1, r1, #0xe0
        str     r1, [r0]

#if defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430)
        orr     r0, r0, #300            @ disable watchdog
        mov     r1, #1
        str     r1, [r0]

        mov     r1, #0x23000000         @ start buffer register
        orr     r1, r1, #0x30000
        orr     r1, r1, #0xc800
#else
        mov     r1, =0x20000000         @ start buffer register
        orr     r1, r1, #0xc30000
        orr     r1, r1, #0xc800
#endif

        sub     r0, r1, #0x0400         @ start address1 register

        ldr     r2, [r1, #0x84]         @ ecc bypass
        orr     r2, r2, #0x100
        str     r2, [r1, #0x84]

        mov     r3, #0x0                @ DFS, FBA
        str     r3, [r0, #0x00]
        str     r3, [r0, #0x04]         @ select dataram for DDP as 0

        mov     r4, #0x104              @ interrupt register
        mov     r5, #0x0002             @ FPA, FSA
        mov     r6, #0x0800             @ BSA

onenand_bl1_load:
        str     r5, [r0, #0x1c]         @ save FPA, FSA
        orr     r6, r6, #0x02           @ BSC
        str     r6, [r1, #0x00]         @ save BSA, BSC
        str     r3, [r1, r4]            @ clear interrupt
        str     r3, [r1, #0x80]         @ write load command

        mov     r7, #0x100              @ need small delay

onenand_wait_loop1:
        subs    r7, r7, #0x1
        bne     onenand_wait_loop1

        add     r5, r5, #0x2            @ next FPA, FSA
        sub     r6, r6, #0x2
        add     r6, r6, #0x200          @ next BSA
        cmp     r5, #0x8
        bne     onenand_bl1_load
#endif

        /*
         * Go setup Memory and board specific bits prior to relocation.
         */
        bl      lowlevel_init   /* go setup pll,mux,memory */

        /* when we already run in ram, we don't need to relocate U-Boot.
         * and actually, memory controller must be configured before U-Boot
         * is running in ram.
         */
        ldr     r0, =0xff000fff
        bic     r1, pc, r0              /* r0 <- current base addr of code */
        ldr     r2, _TEXT_BASE          /* r1 <- original base addr in ram */
        bic     r2, r2, r0              /* r0 <- current base addr of code */
        cmp     r1, r2                  /* compare r0, r1                  */
        beq     after_copy              /* r0 == r1 then skip flash copy   */

#ifdef CONFIG_BOOT_NOR                  /* relocate U-Boot to RAM */
        adr     r0, _start              /* r0 <- current position of code   */
        ldr     r1, _TEXT_PHY_BASE      /* r1 <- destination                */
        ldr     r2, _armboot_start
        ldr     r3, _bss_start
        sub     r2, r3, r2              /* r2 <- size of armboot            */
        add     r2, r0, r2              /* r2 <- source end address         */

nor_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     nor_copy_loop
        b       after_copy
#endif

#ifdef CONFIG_BOOT_NAND
        mov     r0, #0x1000
        bl      copy_from_nand
#endif

#ifdef CONFIG_BOOT_MOVINAND
        ldr     sp, _TEXT_PHY_BASE
        bl      movi_bl2_copy
        b       after_copy
#endif

#ifdef CONFIG_BOOT_ONENAND
        ldr     sp, =0x50000000         @ temporary stack

#ifdef CONFIG_S3C6400
        mov     r1, =0x20000000         @ start buffer register
        orr     r1, r1, #0xc30000
        orr     r1, r1, #0xc800
#else
        mov     r1, #0x23000000         @ start buffer register
        orr     r1, r1, #0x30000
        orr     r1, r1, #0xc800
#endif

        ldr     r2, [r1, #0x84]         @ ecc bypass
        orr     r2, r2, #0x100
        str     r2, [r1, #0x84]

        sub     r0, r1, #0x0400         @ start address1 register

        str     r3, [r0, #0x00]
        str     r3, [r0, #0x04]         @ select dataram for DDP as 0

        mov     r4, #0x104              @ interrupt register

        mov     r6, #0x0c00             @ fixed dataram1 sector number
        str     r6, [r1, #0x00]

        mov     r3, #0x0                @ DFS, FBA
        mov     r5, #0x0000             @ FPA, FSA
        ldr     r9, =CFG_PHY_UBOOT_BASE @ destination

onenand_bl2_load:
        str     r3, [r0, #0x00]         @ save DFS, FBA
        str     r5, [r0, #0x1c]         @ save FPA, FSA

        mov     r7, #0x0                @ clear interrupt
        str     r7, [r1, r4]
        str     r7, [r1, #0x80]         @ write load command

        mov     r8, #0x1000
onenand_wait_loop2:
        subs    r8, r8, #0x1
        bne     onenand_wait_loop2

onenand_wait_int:                       @ wait INT and RI
        ldr     r7, [r1, r4]
        mov     r8, #0x8000
        orr     r8, r8, #0x80
        tst     r7, r8
        beq     onenand_wait_int

        mov     r7, #0x0                @ clear interrupt
        str     r7, [r1, r4]

        mov     r8, #0xc00              @ source address (dataram1)
        mov     r10, #0x40              @ copy loop count (64 = 2048 / 32)

        stmia   sp, {r0-r7}             @ backup

onenand_copy_to_ram:
        ldmia   r8!, {r0-r7}
        stmia   r9!, {r0-r7}
        subs    r10, r10, #0x1
        bne     onenand_copy_to_ram

        ldmia   sp, {r0-r7}             @ restore

        add     r5, r5, #0x4            @ next FPA
        cmp     r5, #0x100              @ last FPA?
        bne     onenand_bl2_load

        /* next block */
        mov     r5, #0x0                @ reset FPA
        add     r3, r3, #0x1            @ next FBA
        cmp     r3, #0x2                @ last FBA?
        bne     onenand_bl2_load
        b       after_copy
#endif

#ifdef CONFIG_BOOT_ONENAND_IROM
        ldr     sp, _TEXT_PHY_BASE
        bl      onenand_bl2_copy
        b       after_copy
#endif

after_copy:
        ldr     r0, =ELFIN_GPIO_BASE
        ldr     r1, =0xC00
        str     r1, [r0, #GPPDAT_OFFSET]
        ldr     r1, [r0, #GPFPUD_OFFSET]
        bic     r1, r1, #0xc0000000
        orr     r1, r1, #0x80000000
        str     r1, [r0, #GPFPUD_OFFSET]
        ldr     r1, [r0, #GPFDAT_OFFSET]
        orr     r1, r1, #0x8000
        str     r1, [r0, #GPFDAT_OFFSET]
        ldr     r1, [r0, #GPFCON_OFFSET]
        bic     r1, r1, #0xc0000000
        orr     r1, r1, #0x40000000
        str     r1, [r0, #GPFCON_OFFSET]


#ifdef CONFIG_ENABLE_MMU
enable_mmu:
        /* enable domain access */
        ldr     r5, =0x0000ffff
        mcr     p15, 0, r5, c3, c0, 0           @ load domain access register

        /* Set the TTB register */
        ldr     r0, _mmu_table_base
        ldr     r1, =CFG_PHY_UBOOT_BASE
        ldr     r2, =0xfff00000
        bic     r0, r0, r2
        orr     r1, r0, r1
        mcr     p15, 0, r1, c2, c0, 0

        /* Enable the MMU */
mmu_on:
        mrc     p15, 0, r0, c1, c0, 0
        orr     r0, r0, #1                      /* Set CR_M to enable MMU */
        mcr     p15, 0, r0, c1, c0, 0
        nop
        nop
        nop
        nop
#endif

skip_hw_init:
        /* Set up the stack                                                 */
stack_setup:
#ifdef CONFIG_MEMORY_UPPER_CODE
        ldr     sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0xc)
#else
        ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
        sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
        sub     r0, r0, #CFG_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    */

#endif

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

        ldr     pc, _start_armboot

_start_armboot:
        .word start_armboot   /*c运行环境已经准备好,通过直接跳转代码进入第二阶段*/

#ifdef CONFIG_ENABLE_MMU
_mmu_table_base:
        .word mmu_table
#endif

/*
 * copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND)
 * r0: size to be compared
 * Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size
 */
        .globl copy_from_nand
copy_from_nand:
        mov     r10, lr         /* save return address */

        mov     r9, r0
        /* get ready to call C functions */
        ldr     sp, _TEXT_PHY_BASE      /* setup temp stack pointer */
        sub     sp, sp, #12
        mov     fp, #0                  /* no previous frame, so fp=0 */
        mov     r9, #0x1000
        bl      copy_uboot_to_ram

3:      tst     r0, #0x0
        bne     copy_failed

        ldr     r0, =0x0c000000
        ldr     r1, _TEXT_PHY_BASE
1:      ldr     r3, [r0], #4
        ldr     r4, [r1], #4
        teq     r3, r4
        bne     compare_failed  /* not matched */
        subs    r9, r9, #4
        bne     1b

4:      mov     lr, r10         /* all is OK */
        mov     pc, lr

copy_failed:
        nop                     /* copy from nand failed */
        b       copy_failed

compare_failed:
        nop                     /* compare failed */
        b       compare_failed

/*
 * we assume that cache operation is done before. (eg. cleanup_before_linux())
 * actually, we don't need to do anything about cache if not use d-cache in U-Boot
 * So, in this function we clean only MMU. by scsuh
 *
 * void theLastJump(void *kernel, int arch_num, uint boot_params);
 */
#ifdef CONFIG_ENABLE_MMU
        .globl theLastJump
theLastJump:
        mov     r9, r0
        ldr     r3, =0xfff00000
        ldr     r4, _TEXT_PHY_BASE
        adr     r5, phy_last_jump
        bic     r5, r5, r3
        orr     r5, r5, r4
        mov     pc, r5
phy_last_jump:
        /*
         * disable MMU stuff
         */
        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

        mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */

        mov     r0, #0
        mov     pc, r9
#endif
/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE    72

#define S_OLD_R0        68
#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

#define MODE_SVC 0x13
#define I_BIT    0x80

/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 */

        .macro  bad_save_user_regs
        sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current user stack
        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

        .macro  irq_save_user_regs
        sub     sp, sp, #S_FRAME_SIZE
         /* 
 * 将r0~r12共13个寄存器的数据都转到sp上句空出的空间里面.具体过程是:先将r0中断数据转到sp指向的地
 * 址处,然后将sp调整到sp+4位置处,再将r1中的数据转过去,以此类推...
 */  
        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

        .macro  irq_restore_user_regs
        /*
 * 将sp所对应的堆栈的数据送到r0~r14个寄存器中,因为lr就是r14. IA:表示先传送,再递增地址
 * (4字节递增) ^:这里不涉及R15,所以只是想告诉CPU使用的是用户模式下的寄存器r0~r14
 */  
        ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
        mov     r0, r0
        ldr     lr, [sp, #S_PC]                 @ Get PC
        add     sp, sp, #S_FRAME_SIZE
        subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
        .endm

        .macro get_bad_stack
        ldr     r13, _armboot_start             @ setup our mode stack (enter in banked mode)
        sub     r13, r13, #(CFG_MALLOC_LEN)     @ move past malloc pool
        sub     r13, r13, #(CFG_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack

        str     lr, [r13]                       @ save caller lr in position 0 of saved stack
        mrs     lr, spsr                        @ get the spsr
        str     lr, [r13, #4]                   @ save spsr in position 1 of saved stack

        mov     r13, #MODE_SVC                  @ prepare SVC-Mode
        @ msr   spsr_c, r13
        msr     spsr, r13                       @ switch modes, make sure moves will execute
        mov     lr, pc                          @ capture return pc
        movs    pc, lr                          @ jump to next instruction & switch modes.
        .endm

        .macro get_bad_stack_swi
        sub     r13, r13, #4                    @ space on current stack for scratch reg.
        str     r0, [r13]                       @ save R0's value.
        ldr     r0, _armboot_start              @ get data regions start
        sub     r0, r0, #(CFG_MALLOC_LEN)       @ move past malloc pool
        sub     r0, r0, #(CFG_GBL_DATA_SIZE+8)  @ move past gbl and a couple spots for abort stack
        str     lr, [r0]                        @ save caller lr in position 0 of saved stack
        mrs     r0, spsr                        @ get the spsr
        str     lr, [r0, #4]                    @ save spsr in position 1 of saved stack
        ldr     r0, [r13]                       @ restore r0
        add     r13, r13, #4                    @ pop stack entry
        .endm

        .macro get_irq_stack                    @ setup IRQ stack
        ldr     sp, IRQ_STACK_START
        .endm

        .macro get_fiq_stack                    @ setup FIQ stack
        ldr     sp, FIQ_STACK_START
        .endm

/*
 * 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

        .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
        .align 5
.global arm1136_cache_flush
arm1136_cache_flush:
                mcr     p15, 0, r1, c7, c5, 0   @ invalidate I cache
                mov     pc, lr                  @ back to caller

#if defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_CINTEGRATOR)
/* Use the IntegratorCP function from board/integratorcp/platform.S */
#elif defined(CONFIG_S3C64XX)
/* For future usage of S3C64XX*/
#else
        .align  5
.globl reset_cpu
reset_cpu:
        ldr     r1, rstctl      /* get addr for global reset reg */
        mov     r3, #0x2        /* full reset pll+mpu */
        str     r3, [r1]        /* force reset */
        mov     r0, r0
_loop_forever:
        b       _loop_forever
rstctl:
        .word   PM_RSTCTRL_WKUP

#endif
在这一刻,我真的迷惘了,知道了江湖的成份,但是想详细了解江湖还是这么困难。但我知道我已经没有了退路,江湖我会战胜你的!

转载请注明出处:http://blog.csdn.net/ecbtnrt/article/details/6630085