操作系统_再识(uboot start.S分析)

#include<config.h>

#include<version.h>

 

#ifdefined(CONFIG_S3C2410)

#include<s3c2410.h>

#elifdefined(CONFIG_S3C2440)//include/configs/smdk2440.h中定义。

#include<s3c2440.h>

#endif

 

#include<status_led.h>

 

/*************************************************************************

  Jump vector table as in table 3.1 in [1]

 *************************************************************************/

//.global声明一个符号可被其它文件引用,相当于声明了一个

//全局变量,.globl与.global相同。

//该部分为处理器的异常处理向量表。地址范围为

//0x0000 0000 ~0x0000 0020,刚好8条指令。

 

//声明全局变量 _start

.globl _start     /*系统复位位置,整个程序入口*/

_start: b      start_code    /*各个异常向量对应的相对跳转代码,0x00*/

     /*start_code用b,就是因为start_code在MMU建立前后都有可能发生*/

     /*其他的异常只有在MMU建立之后才会发生*/

        ldr     pc,_undefined_instruction  //未定义指令异常,0x04

        ldr     pc,_software_interrupt    //软中断异常,0x08

        ldr     pc,_prefetch_abort  //内存操作异常,0x0c

        ldr     pc,_data_abort     //数据异常,0x10

        ldr     pc,_not_used      //未适用,0x14

        ldr     pc,_irq          //慢速中断异常,0x18

        ldr     pc,_fiq         //快速中断异常,0x1c

 

//.word伪操作用于分配一段字内存单元(分配的单元都是字对齐的),并

//用伪操作中的expr初始化。.long与.int作用与之相同。

/*.word 表达式 ==> 就是在当前位置放一个word型的值,这个值就是"表达式"

;rWTCON: .word 0x15300000就是在当前地址,即_rWTCON处放一个值0x15300000*/

 

_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

 

 

/*.balign[wl]abs-expr, abs-expr, abs-expr

;增加位置计数器(在当前子段)使它指向规定的存储边界。

;第一个表达式参数(结果必须是纯粹的数字)是必需参数:边界基准,单位

为字节。

;例如, '.balign 8'向后移动位置计数器直至计数器的值等于8的倍数。

;如果位置计数器已经是8的倍数,则无需移动。

;第2个表达式参数(结果必须是纯粹的数字)给出填充字节的值,用这个值

填充位置计数器越过的地方。

;第2个参数(和逗点)可以省略。如果省略它,填充字节的值通常是0。

;但在某些系统上,如果本段标识为包含代码,而填充值被省略,则使用

no-op指令填充空白区。

;第3个参数的结果也必须是纯粹的数字,这个参数是可选的。如果存在第

3个参数,

;它代表本对齐命令允许跳过字节数的最大值。如果完成这个对齐需要跳

过的字节数比规定的最大值还多,

;则根本无法完成对齐。您可以在边界基准参数后简单地使用两个逗号,

以省略填充值参数(第二参数);

;如果您在想在适当的时候,对齐操作自动使用no-op指令填充

 

balignw和.balignl是.balign命令的变化形式。.balignw使用2个字节来填充空白区。

.balignl使用4字节来填充。例如,.balignw4,0x368d将地址对齐到4的倍数,如果它跳

过2个字节,GAS将使用0x368d填充这2个字节(字节的确切存放位置视处理器

的存储方式而定)

如果它跳过1或3个字节,则填充值不明确。

 

 

//它的含义是以16字节边界对齐,为了对齐而越过的地址以字为单位填冲

//值0xdeadbeef。我猜0xdeadbeef可能NOP指令。

        .balignl 16,0xdeadbeef  //对齐内存为16的倍数

/*************************************************************************

 *

 * Startup Code (called from the ARM resetexception vector)

 *

 * do important init only if we don't startfrom memory!

 * relocate armboot to ram

 * setup stack

 * jump to second stage

 *

 *************************************************************************/

 

// TEXT_BASE在开发板相关的目录中的config.mk文件中定义, 它定义了

// 代码在运行时所在的地址, 那么_TEXT_BASE中保存了这个地址

/*

 *保存变量的数据区,保存一些全局变量,用于BOOT程序从FLASH拷贝到RAM,或者

 其它的使用。

 *还有一些变量的长度是通过连接脚本里得到,实际上由编译器算出来的

 */

//TEXT_BASE定义在/board/smdk2410/config.mk中。

 

/*TEXT_BASE是代码执行的起始地址.编译产生的二进制文件必需下载到该地

址,因为所有的函数,全局变量等等定位都是以这个地址为参照的.

如果uboot中是TEXT_BASE就是设的0x33F80000, 那么必需download到这个地址的ram中才

能正常运行.

*/ 

_TEXT_BASE:  //_TEXT_BASE=TEXT_BASE.

                       .word   TEXT_BASE  /*uboot映像在SDRAM中的重定位地址*/

 

// 标号_start在前面有定义

       

.globl_armboot_start   // /*在_armboot_start标号处,保存了_start的值*/

_armboot_start:     //_armboot_start=_start

                               .word _start    /*_start是程序入口,链接完毕它的值应该是TEXT_BASE*/

 

/*

 * These are defined in the board-specificlinker script.

 */

//__bss_start是uboot 的bss段起始地址,那么uboot映像的大小就是__bss_start - _start;

//实际上,_armboot_start并没有实际意义,它只是在"ldr r2, _armboot_start"中用來寻

//址_start的值而已,_bss_start也是一样的道理,真正有意义的应该是_start和

//__bss_start本身。

 

.globl_bss_start  /*__bss_start是uboot 的bss段起始地址,*/

_bss_start:         /*uboot映像的大小就是__bss_start - _start*/

               .word __bss_start

 

.globl _bss_end

_bss_end:

               .word _end

 

#ifdefCONFIG_USE_IRQ

/* IRQ stack memory(calculated at run-time) */

.globlIRQ_STACK_START

IRQ_STACK_START:

                               .word   0x0badc0de

 

/* IRQ stack memory(calculated at run-time) */

.globlFIQ_STACK_START

FIQ_STACK_START:

                               .word 0x0badc0de

#endif

 

 

/* the actual startcode*/

start_code:/*复位启动子程序*/

        /*设置cpu运行在SVC32模式。共有7种模式*/   

        mrs     r0,cpsr  /*复制当前程序状态寄存器cpsr到r0*/

        bic     r0,r0,#0x1f  //这里使用位清除指令,把中断全部清除,只置位模式控制位

                                  //7种异常,共占0x00 - 0x16空间

        /*ORR{条件}{S} <dest>, <op 1>, <op 2>*/

       /*OR 将在两个操作数上进行逻辑或,把结果放置到目的寄存器中*/

        orr     r0,r0,#0xd3/*选择新模式,(现在设为超级保护模式)*/

       

        msr     cpsr,r0  /*设置cpsr为超级保护模式*/

   /*通过设置ARM的CPSR寄存器,让CPU运行在操作系统模式,为后面进行其它操作作好准备*/

 

//如果定义了CONFIG_AT91RM9200DK,CONFIG_AT91RM9200EK,CONFIG_AT91RM9200DF中的任意一个

//,就会执行其中的语句.这里没有用。

#if     defined(CONFIG_AT91RM9200DK) ||defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)

        /* relocate exception table*/

        ldr            r0,=_start

        ldr            r1,=0x0

        mov            r2,#16

copyex:

        subs    r2,r2,   #1

        ldr            r3,[r0], #4

        str            r3,[r1], #4

        bne            copyex

#endif

 

#ifdefined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

 

#ifdefined(CONFIG_S3C2400)

#define pWTCON 0x15300000

#define INTMSK 0x14400008     /*Interupt-Controller base addresses */

#define CLKDIVN 0x14800014     /*clock divisor register */

#elifdefined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

#define pWTCON 0x53000000 /*"看门狗定时器控制寄存器"的地址0x53000000*/ 

#define INTMSK 0x4A000008 /*"中断屏蔽寄存器"的地址:0x4A000008*/

#define INTSUBMSK      0x4A00001C /*针对INTMAK具体化的一个中断请求屏蔽寄存器,其地

                                                            址0x4A00001C */ 

#define LOCKTIME       0x4c000000  //锁时计数寄存器   

#define MPLLCON        0x4c000004  //MPLL寄存器

#define UPLLCON        0x4c000008  //UPLL寄存器

#define CLKDIVN 0x4C000014     /*CPU时钟分频控制寄存器,地址0x4C000014*/ 

#endif

 

#ifdefined(CONFIG_S3C2410)

#defineINTSUBMSK_val  0x7ff

#define MPLLCON_val    ((0x90 << 12) + (0x7 << 4) +0x0)     /* 202 MHz */

#define UPLLCON_val    ((0x78 << 12) + (0x2 << 4) +0x3)

#define CLKDIVN_val    3 /* FCLK:HCLK:PCLK = 1:2:4 */

#elifdefined(CONFIG_S3C2440)

#defineINTSUBMSK_val  0xffff  //以便屏蔽INTSUBMSK的bit[15:0]对应的中断请求

#if(CONFIG_SYS_CLK_FREQ == 16934400)//晶振=16.9344M在include/configs/smdk2440.h中定义。

/*

Mpll = (2 * m *Fin) / (p * 2s)

m = (MDIV + 8), p =(PDIV + 2), s = SDIV

 

Upll = (m * Fin) /(p * 2s)

m = (MDIV + 8), p =(PDIV + 2), s = SDIV

 

MDIV=PLLCON[19:12];  PDIV=PLLCON[9:4];  SDIV=PLLCON[1:0];

*/

//# defineMPLLCON_val ((0x61 << 12) + (0x1<< 4) + 0x2)     /* 296.35 MHz */

//# defineUPLLCON_val ((0x3c << 12) + (0x4<< 4) + 0x2)     /*  47.98 MHz */

                                //MDIV=184        PDIV=2     SDIV=2                                

#define MPLLCON_val    ((184 << 12) + (2 << 4) + 2)   /*406M*/

                                //MDIV=60        PDIV=4     SDIV=2 

#define UPLLCON_val   ((60 << 12) + (4 << 4) +2)   /* 47M */

#elif(CONFIG_SYS_CLK_FREQ == 12000000)

#define MPLLCON_val    ((0x44 << 12) + (0x1 << 4) +0x1)     /* 304.00 MHz */

#define UPLLCON_val    ((0x38 << 12) + (0x2 << 4) +0x2)     /*  48.00 MHz */

#endif

#define CLKDIVN_val    7 /* FCLK:HCLK:PCLK = 1:3:6   CLKDIVN=7 */

                       //CPU  : 高速设备:  低速设备

#define CAMDIVN 0x4C000018

#endif

 

        //禁用看门狗

        ldr      r0, =pWTCON

        mov    r1, #0x0

        str      r1, [r0]

 

        /* mask all IRQs by setting all bits inthe INTMR - default*/

        /*在SVC模式下,屏蔽所有中断发生*/

        mov       r1, #0xffffffff

        ldr       r0, =INTMSK

        str       r1, [r0]

       

#ifdefined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

        ldr     r1,=INTSUBMSK_val  /*子中断同样屏蔽INTSUBMSK_val=0xffff*/

        ldr     r0,=INTSUBMSK

        str     r1,[r0]

 

/*To reduce PLLlock time, adjust the LOCKTIME register. */

        ldr    r0,=LOCKTIME

        ldr    r1,=0xffffff

        str    r1,[r0]       

#endif

 

    /* FCLK:HCLK:PCLK = 1:3:6*//* default FCLKis 406M MHz ! */

        ldr     r0,=CLKDIVN

        mov     r1,#CLKDIVN_val

        str     r1,[r0]

 

#ifdefined(CONFIG_S3C2440)

      /* Make sure we get FCLK:HCLK:PCLK =1:3:6 */

        ldr        r0, =CAMDIVN

        mov    r1, #0

        str       r1, [r0]

 

        /* Clock asynchronous mode */

        mrc    p15, 0, r1, c1, c0, 0

        orr     r1,   r1, #0xc0000000

        mcr    p15, 0, r1, c1, c0, 0

 

        ldr     r0,=UPLLCON

        ldr     r1,=UPLLCON_val

        str     r1,[r0]

       

        nop    

        nop

        nop

        nop

        nop

        nop

        nop

        nop

       

        ldr     r0,=MPLLCON

        ldr     r1,=MPLLCON_val

        str     r1,[r0]

//

#define GPJCON      0x560000D0

#define GPJDAT       0x560000D4

#define GPJUP          0x560000D8

/*

        LDR  R0,   = GPJCON

        LDR  R1,   = 0x15555

        STR  R1,   [R0]

        LDR  R0,   = GPJUP

        LDR  R1,   = 0x1f

        STR  R1,   [R0]

        LDR  R0,   = GPJDAT 

//    LDR  R1,   = 0xffff

        LDR  R1,   = 0x00

        STR  R1,   [R0]

*/

#endif

 

#endif  /* CONFIG_S3C2400 || CONFIG_S3C2410 */

 

        /*

         *we do sys-critical inits only at reboot,

         *not when booting from ram!

         */

        //bl     LED_FLASH

#ifndefCONFIG_SKIP_LOWLEVEL_INIT

/*这些初始化代码在系统重启的时候执行,运行时热复位从RAM中启动不执行*/

        bl      cpu_init_crit

#endif

#if 1

        LDR  R0,   = GPJCON

        LDR  R1,   = 0x15555

        STR  R1,   [R0]

        LDR  R0,   = GPJUP

        LDR  R1,   = 0x1f

        STR  R1,   [R0]

        LDR  R0,   = GPJDAT

        LDR  R1,   = 0x00

        STR  R1,   [R0]

#endif

       

#ifdefined(CONFIG_AT91RM9200) || defined(CONFIG_S3C2410) ||defined(CONFIG_S3C2440)

#ifndefCONFIG_SKIP_RELOCATE_UBOOT

#ifndefCONFIG_S3C2410_NAND_BOOT

//NOR_BOOT :

relocate:      /* 把U-BOOT重新定位到RAM*/

         //r0=0;

        adr     r0,_start             /* r0是代码的当前位置*/

        //r1=TEXT_BASE = 0x33F80000

        ldr     r1,_TEXT_BASE /*测试判断是从FLASH启动,还是RAM  */

        cmp    r0, r1     /*比较R0、R1,调试的时候不需要重定位。 */

        beq    stack_setup  /*如果R0等于R1,跳到重定位代码。*/

 

        //如果不是从RAM运行的话,则将代码拷贝到_TEXT_BASE标识的RAM中。

        /*准备重新定义代码。*/

        ldr     r2,_armboot_start//_armboot_start=_start

        ldr     r3,_bss_start  //

        sub     r2,r3, r2             /* r2得到armboot的大小*/

        add     r2,r0, r2             /* r2得到要复制代码的末尾地址*/

//kaobei guo cheng

copy_loop:/*重新定位代码*/

        ldmia   r0!,{r3-r10}          /*从源地址[r0]复制,r0指向_start(=0)*/

        stmia   r1!,{r3-r10}          /*复制到目的地址[r1],r1指向_TEXT_BASE(=0x33F80000)*/

        cmp     r0,r2                 /* 复制数据块直到源数据末尾地址[r2]*/

        ble     copy_loop

#else /* NAND_BOOT*/

//relocate:

copy_myself:

        /* mov  r10,lr */

#ifdefined(CONFIG_S3C2410)

        @ reset NAND

        mov     r1,#S3C2410_NAND_BASE

        ldr     r2,=0xf842            @ initial value enabletacls=3,rph0=6,rph1=0

        str     r2,[r1, #oNFCONF]

        ldr     r2,[r1, #oNFCONF]

        bic     r2,r2, #0x800         @ enable chip

        str     r2,[r1, #oNFCONF]

        mov     r2,#0xff              @ RESET command

        strb    r2,[r1, #oNFCMD]

        mov     r3,#0                 @ wait

1:      add     r3,r3, #0x1

        cmp     r3,#0xa

        blt     1b

2:      ldr     r2,[r1, #oNFSTAT]     @ wait ready

        tst     r2,#0x1

        beq     2b

        ldr     r2,[r1, #oNFCONF]

        orr     r2,r2, #0x800         @ disable chip

        str     r2,[r1, #oNFCONF]

#elifdefined(CONFIG_S3C2440)

        /*从NAND闪存中把U-BOOT拷贝到RAM*/

        mov     r1,#S3C2440_NAND_BASE //S3C2440_NAND_BASE=0x4E000000

        ldr     r2,=0xfff0            @ initial valuetacls=3,rph0=7,rph1=7

        ldr     r3,[r1, #oNFCONF] //oNFCONF=0x00

        orr     r3,r3, r2

        str     r3,[r1, #oNFCONF]//oNFCONF=0x00

 

        ldr     r3,[r1, #oNFCONT] //oNFCONT=0x04

        orr     r3,r3, #1             @ enable nandcontroller

        str     r3,[r1, #oNFCONT]//oNFCONT=0x04

#endif  //if defined(CONFIG_S3C2410)

 

#if 0

        @ get ready to call C functions (fornand_read())

        ldr     sp,DW_STACK_START     @ setup stack pointer

        mov     fp,#0                 @ no previous frame, sofp=0

#else

        ldr     r0,_TEXT_BASE         /* upper 128 KiB:relocated uboot   */

       

        /* CFG_MALLOC_LEN=(CFG_ENV_SIZE +2048*1024) =0x210000 ;   CFG_ENV_SIZE     = 0x10000

             CFG_GBL_DATA_SIZE=128    */

        sub     r0,r0, #CFG_MALLOC_LEN        /* mallocarea                      */

        sub     r0,r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */

#ifdefCONFIG_USE_IRQ /*include/configs/smdk2440.h*/

        sub     r0,r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)  //8K+4K

#endif

        sub     sp,r0, #12            /* leave 3 words forabort-stack    */

#endif   //#if 0

 

        @ copy u-boot to RAM

        ldr     r0,_TEXT_BASE //置第1个参数: UBOOT在RAM中的起始地址

        mov    r1, #0x0   //设置第2个参数:NAND闪存的起始地址

        //CFG_UBOOT_SIZE=0x40000=256k

        mov     r2,#CFG_UBOOT_SIZE  // 设置第3个参数: U-BOOT的长度(256KB)

        bl      nand_read_ll   //调用nand_read_whole(),把NAND闪存中的数据读入到RAM中

 

        tst     r0,#0x0 // 如果函数的返回值为0,表示执行成功

        beq     ok_nand_read  //执行内存比较,把RAM中的前4K内容与NAND闪存中的前4K内容进行比较, 如果完全相同, 则表示搬移成功

#ifdefCONFIG_DEBUG_LL

bad_nand_read:

        ldr     r0,STR_FAIL

        ldr     r1,SerBase

        bl      PrintWord

1:      b       1b             @ infinite loop

#endif

 

ok_nand_read:

#ifdefCONFIG_DEBUG_LL

        ldr     r0,STR_OK

        ldr     r1,SerBase

        bl      PrintWord

#endif

 

        @ verify

        mov     r0,#0

        @ldr    r1,=0x33f00000

        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     done_nand_read

        bne     go_next

notmatch:

#ifdefCONFIG_DEBUG_LL

        sub     r0,r0, #4

        ldr     r1,SerBase

        bl      PrintHexWord

        ldr     r0,STR_FAIL

        ldr     r1,SerBase

        bl      PrintWord

#endif

 

#if 1

        LDR  R0,   = GPJDAT

        LDR  R1,   = 0x4

        STR  R1,   [R0]

#endif

1:      b       1b

done_nand_read:

#if 1

        LDR  R0,   = GPJDAT

        LDR  R1,   = 0x2

        STR  R1,   [R0]

#endif

 

#endif /* NAND_BOOT*/

#endif  /* CONFIG_SKIP_RELOCATE_UBOOT */

#endif

        /* 初始化堆栈*/

stack_setup:

        ldr     r0,_TEXT_BASE         /*上面是128kib重定位的u-boot*/

        /*在smdk244.h中定义 #define CFG_MALLOC_LEN           (CFG_ENV_SIZE + 2048*1024)

                            #define CFG_ENV_SIZE         0x10000

                          #define CFG_GBL_DATA_SIZE   128     */

        sub     r0,r0, #CFG_MALLOC_LEN        /*向下是内存分配空间*/

        sub     r0,r0, #CFG_GBL_DATA_SIZE /*然后是bdinfo结构体地址空间*/

#ifdefCONFIG_USE_IRQ  //在 smdk2440.h中定义。

    /*在smdk244.h中定义#define CONFIG_STACKSIZE_IRQ (8*1024)      

                                                #define CONFIG_STACKSIZE_FIQ       (4*1024) */

        sub     r0,r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

        sub     sp,r0, #12            /*为 abort-stack 预留3个字,得到最终sp指针初始值*/

 

clear_bss:

        ldr     r0,_bss_start         /*找到bss 段起始地址。*/

        ldr     r1,_bss_end           /* bss 段末尾地址。*/

        mov r2, #0x00000000            /* 清零。*/

 

clbss_l:str    r2, [r0]               /*bss段地址空间清零循环。。。*/

        add     r0,r0, #4

        cmp     r0,r1

        ble     clbss_l

#if 1

        LDR  R0,   = GPJDAT

        LDR  R1,   = 0x1

        STR  R1,   [R0]

#endif

     /*跳转到start_armboot函数入口,_start_armboot字保存函数入口指针*/

        ldr     pc,_start_armboot

 

//_start_armboot=start_armboot

//pc=start_armboot;

//去执行void start_armboot (void),在lib_arm/boarb.c中。

_start_armboot: .word start_armboot

 

 

/*

 *************************************************************************

 *

 * CPU_init_critical registers

 *

 * setup important registers

 * setup memory timing

 *

 *************************************************************************

 */

 

//功能:设置CP15寄存器这里完成的功能:失效Icache和Dcache,禁能MMU和cache

#ifndefCONFIG_SKIP_LOWLEVEL_INIT

//关键的初始化子程序。

cpu_init_crit:

         /* flush v4 I/D caches  | 失效指令cache和数据cache       */

        mov     r0,#0

        //使I/D cache失效:将寄存器r0的数据传送到协处理器p15的c7中。C7寄存器

        //位对应cp15中的cache控制寄存器

        mcr     p15,0, r0, c7, c7, 0  /* flush v3/v4 cache */

        //使TLB操作寄存器失效:将r0数据送到cp15的c8、c7中。C8对应TLB操作

        //寄存器

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

 

        /*

         *disable MMU stuff and caches

         */

         /*  disable MMU stuff and caches |   禁能MMU和cache       */

        mrc     p15,0, r0, c1, c0, 0 //先把c1和c0寄存器的各位置0(r0 = 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

 

        /*

         *before relocating, we have to setup RAM timing

         *because memory timing is board-dependend, you will

         *find a lowlevel_init.S in your board directory.

         */

        mov     ip,lr

#if     defined(CONFIG_AT91RM9200DK) ||defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)

 

#else

        bl      lowlevel_init  //位于board/smdk2440/lowlevel_init.S:用于完成芯片存储器的初始化,

                                     //执行完成后返回

#endif

        mov     lr,ip

        mov     pc,lr

#endif /*CONFIG_SKIP_LOWLEVEL_INIT */

 

/*

 *************************************************************************

 *

 * Interrupt handling

 *

 *************************************************************************

 */

 

@

@ IRQ stack frame.

@

#defineS_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_SVC0x13

#define I_BIT  0x80

 

/*

 * use bad_save_user_regs forabort/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

        stmia   sp,{r0 - r12}                 @ Callingr0-r12

        ldr     r2,_armboot_start

        sub     r2,r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)

        sub     r2,r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2words into abort stack

        ldmia   r2,{r2 - r3}                  @ get pc, cpsr

        add     r0,sp, #S_FRAME_SIZE          @ restoresp_SVC

 

        add     r5,sp, #S_SP

        mov     r1,lr

        stmia   r5,{r0 - r3}                  @ save sp_SVC,lr_SVC, pc, cpsr

        mov     r0,sp

        .endm

 

        .macro  irq_save_user_regs

        sub     sp,sp, #S_FRAME_SIZE

        stmia   sp,{r0 - r12}                 @ Callingr0-r12

        add    r8, sp, #S_PC

        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

        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 modestack

        sub     r13,r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)

        sub     r13,r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack

 

        str     lr,[r13]                      @ save callerlr / spsr

        mrs     lr,spsr

        str    lr, [r13, #4]

 

        mov     r13,#MODE_SVC                 @ prepareSVC-Mode

        @ msr   spsr_c,r13

        msr     spsr,r13

        mov     lr,pc

        movs    pc,lr

        .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

        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

 

#ifdefCONFIG_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 moreeffiction 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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值