U-BOOT中start.s包含S3C2440代碼分析(轉)

#include <config.h>
#include <version.h>

#if defined(CONFIG_S3C2410)
#include <s3c2410.h>
#elif defined(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_codeb,就是因爲start_codeMMU建立前後都有可能發生*/
     /*
其他的異常只有在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字節來填充。例如,.balignw 4,0x368d將地址對齊到4的倍數,如果它跳
2個字節,GAS將使用0x368d填充這2個字節(字節的確切存放位置視處理器
的存儲方式而定)
如果它跳過13個字節,則填充值不明確。


//
它的含義是以16字節邊界對齊,爲了對齊而越過的地址以字爲單位填衝
//
0xdeadbeef。我猜0xdeadbeef可能NOP指令。
.balignl 16,0xdeadbeef  //
對齊內存爲16的倍數
/*************************************************************************
*
* Startup Code (called from the ARM reset exception vector)
*
* do important init only if we don't start from 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-specific linker 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

#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


/* the actual start code*/
start_code:/*
復位啓動子程序*/
/*
設置cpu運行在SVC32模式。共有7種模式*/
mrs r0,cpsr  /*複製當前程序狀態寄存器cpsrr0*/
bic r0,r0,#0x1f  //這裏使用位清除指令,把中斷全部清除,只置位模式控制位
                          //7種異常,共佔0x00 - 0x16空間
/*ORR{
條件}{S}  <dest>, <op 1>, <op 2>*/
       /*OR
將在兩個操作數上進行邏輯或,把結果放置到目的寄存器中*/
orr r0,r0,#0xd3 /*選擇新模式,(現在設爲超級保護模式)*/

msr cpsr,r0  /*
設置cpsr爲超級保護模式*/
   /*通過設置ARMCPSR寄存器,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

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

#if defined(CONFIG_S3C2400)
#define pWTCON 0x15300000
#define INTMSK 0x14400008 /* Interupt-Controller base addresses */
#define CLKDIVN 0x14800014 /* clock divisor register */
#elif defined(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

#if defined(CONFIG_S3C2410)
#define INTSUBMSK_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 */
#elif defined(CONFIG_S3C2440)
#define INTSUBMSK_val 0xffff  //
以便屏蔽INTSUBMSKbit[15:0]對應的中斷請求
#if (CONFIG_SYS_CLK_FREQ == 16934400)//晶振=16.9344Minclude/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];
*/
//# define MPLLCON_val ((0x61 << 12) + (0x1 << 4) + 0x2) /* 296.35 MHz */
//# define UPLLCON_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 in the INTMR - default*/
/*
SVC模式下,屏蔽所有中斷髮生*/
mov   r1, #0xffffffff
ldr   r0, =INTMSK
str   r1, [r0]

#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
ldr r1, =INTSUBMSK_val  /*
子中斷同樣屏蔽INTSUBMSK_val=0xffff*/
ldr r0, =INTSUBMSK
str r1, [r0]

/*To reduce PLL lock time, adjust the LOCKTIME register. */
        ldr     r0,=LOCKTIME
        ldr     r1,=0xffffff
        str     r1,[r0]
#endif

    /* FCLK:HCLK:PCLK = 1:3:6*//* default FCLK is 406M MHz ! */
ldr r0, =CLKDIVN
mov r1, #CLKDIVN_val
str r1, [r0]

#if defined(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
#ifndef CONFIG_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

#if defined(CONFIG_AT91RM9200) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
#ifndef CONFIG_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     /*比較R0R1,調試的時候不需要重定位。 */
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 */
#if defined(CONFIG_S3C2410)
@ reset NAND
mov r1, #S3C2410_NAND_BASE
ldr r2, =0xf842 @ initial value enable tacls=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]
#elif defined(CONFIG_S3C2440)
        /*
NAND閃存中把U-BOOT拷貝到RAM*/
mov r1, #S3C2440_NAND_BASE //S3C2440_NAND_BASE=0x4E000000
ldr r2, =0xfff0 @ initial value tacls=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 nand controller
str r3, [r1, #oNFCONT]//oNFCONT=0x04
#endif  //if defined(CONFIG_S3C2410)

#if 0
@ get ready to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=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 /* malloc area                      */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
#ifdef CONFIG_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 for abort-stack    */
#endif   //#if 0

@ copy u-boot to RAM
ldr r0, _TEXT_BASE //
置第1個參數: UBOOTRAM中的起始地址
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內容進行比較, 如果完全相同, 則表示搬移成功
#ifdef CONFIG_DEBUG_LL
bad_nand_read:
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
1: b 1b @ infinite loop
#endif

ok_nand_read:
#ifdef CONFIG_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:
#ifdef CONFIG_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結構體地址空間*/
#ifdef CONFIG_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寄存器這裏完成的功能:失效IcacheDcache,禁能MMUcache
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
//
關鍵的初始化子程序。
cpu_init_crit:
/*  flush v4 I/D caches  |
失效指令cache和數據cache       */
mov r0, #0
//
使I/D cache失效:將寄存器r0的數據傳送到協處理器p15c7中。C7寄存器
//
位對應cp15中的cache控制寄存器
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
//
使TLB操作寄存器失效:將r0數據送到cp15c8c7中。C8對應TLB操作
//
寄存器
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

/*
* disable MMU stuff and caches
*/
/*   disable MMU stuff and caches |  
禁能MMUcache       */
mrc p15, 0, r0, c1, c0, 0 //先把c1c0寄存器的各位置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.
@
#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
stmia sp, {r0 - r12} @ Calling r0-r12
ldr r2, _armboot_start
sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
sub r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
ldmia r2, {r2 - r3} @ get pc, cpsr
add r0, sp, #S_FRAME_SIZE @ restore sp_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} @ Calling r0-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 mode stack
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 caller lr / spsr
mrs lr, spsr
str     lr, [r13, #4]

mov r13, #MODE_SVC @ prepare SVC-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

#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
發佈了12 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章