最全的uboot start.S分析

来源:互联网 发布:数据分析师 招聘 编辑:程序博客网 时间:2024/06/04 19:33
#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_code用b,就是因为start_code在MMU建立前后都有可能发生*/     /*其他的异常只有在MMU建立之后才会发生*/ldrpc, _undefined_instruction  //未定义指令异常,0x04ldrpc, _software_interrupt    //软中断异常,0x08ldrpc, _prefetch_abort  //内存操作异常,0x0cldrpc, _data_abort     //数据异常,0x10ldrpc, _not_used      //未适用,0x14ldrpc, _irq          //慢速中断异常,0x18 ldrpc, _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个字节(字节的确切存放位置视处理器的存储方式而定)。如果它跳过1或3个字节,则填充值不明确。//它的含义是以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..wordTEXT_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_STARTIRQ_STACK_START:.word0x0badc0de/* IRQ stack memory (calculated at run-time) */.globl FIQ_STACK_STARTFIQ_STACK_START:.word 0x0badc0de#endif/* the actual start code*/start_code:/*复位启动子程序*//*设置cpu运行在SVC32模式。共有7种模式*/mrsr0,cpsr  /*复制当前程序状态寄存器cpsr到r0*/bicr0,r0,#0x1f  //这里使用位清除指令,把中断全部清除,只置位模式控制位                          //7种异常,共占0x00 - 0x16空间/*ORR{条件}{S}  <dest>, <op 1>, <op 2>*/       /*OR 将在两个操作数上进行逻辑或,把结果放置到目的寄存器中*/orrr0,r0,#0xd3 /*选择新模式,(现在设为超级保护模式)*/msrcpsr,r0  /*设置cpsr为超级保护模式*/   /*通过设置ARM的CPSR寄存器,让CPU运行在操作系统模式,为后面进行其它操作作好准备*///如果定义了CONFIG_AT91RM9200DK,CONFIG_AT91RM9200EK,CONFIG_AT91RM9200DF中的任意一个//,就会执行其中的语句.这里没有用。#ifdefined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)/* relocate exception table*/ldrr0, =_startldrr1, =0x0movr2, #16copyex:subsr2, r2,   #1ldrr3, [r0], #4strr3, [r1], #4bnecopyex#endif#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)#if defined(CONFIG_S3C2400)#define pWTCON0x15300000#define INTMSK0x14400008/* Interupt-Controller base addresses */#define CLKDIVN0x14800014/* clock divisor register */#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)#define pWTCON0x53000000  /*"看门狗定时器控制寄存器"的地址0x53000000*/  #define INTMSK0x4A000008 /*"中断屏蔽寄存器"的地址:0x4A000008 */#define INTSUBMSK0x4A00001C /*针对INTMAK具体化的一个中断请求屏蔽寄存器,其地                                                             址0x4A00001C */  #define LOCKTIME0x4c000000  //锁时计数寄存器    #define MPLLCON 0x4c000004  //MPLL寄存器#define UPLLCON 0x4c000008  //UPLL寄存器#define CLKDIVN0x4C000014/*CPU时钟分频控制寄存器,地址0x4C000014*/  #endif#if defined(CONFIG_S3C2410)#define INTSUBMSK_val0x7ff#define MPLLCON_val((0x90 << 12) + (0x7 << 4) + 0x0)/* 202 MHz */#define UPLLCON_val((0x78 << 12) + (0x2 << 4) + 0x3)#define CLKDIVN_val3 /* FCLK:HCLK:PCLK = 1:2:4 */#elif defined(CONFIG_S3C2440)#define INTSUBMSK_val0xffff  //以便屏蔽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 = SDIVUpll = (m * Fin) / (p * 2s)m = (MDIV + 8), p = (PDIV + 2), s = SDIVMDIV =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_val7 /* FCLK:HCLK:PCLK = 1:3:6   CLKDIVN=7  */                       //CPU  : 高速设备:  低速设备#define CAMDIVN0x4C000018#endif        //禁用看门狗ldr       r0, =pWTCONmov     r1, #0x0str       r1, [r0]/* mask all IRQs by setting all bits in the INTMR - default*//*在SVC模式下,屏蔽所有中断发生*/mov  r1, #0xffffffffldr  r0, =INTMSKstr  r1, [r0]#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)ldrr1, =INTSUBMSK_val  /*子中断同样屏蔽INTSUBMSK_val=0xffff*/ldrr0, =INTSUBMSKstrr1, [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 ! */ldrr0, =CLKDIVNmovr1, #CLKDIVN_valstrr1, [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, 0ldrr0,=UPLLCONldrr1,=UPLLCON_valstrr1,[r0]nopnopnopnopnopnopnopnopldrr0,=MPLLCONldrr1,=MPLLCON_valstrr1,[r0]//#define GPJCON      0x560000D0#define GPJDAT       0x560000D4#define GPJUP0x560000D8/*        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中启动不执行*/blcpu_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;adrr0, _start/* r0是代码的当前位置*///r1=TEXT_BASE = 0x33F80000ldrr1, _TEXT_BASE/*测试判断是从FLASH启动,还是RAM  */cmp     r0, r1     /*比较R0、R1,调试的时候不需要重定位。 */beq     stack_setup  /*如果R0等于R1,跳到重定位代码。*///如果不是从RAM运行的话,则将代码拷贝到_TEXT_BASE标识的RAM中。/*准备重新定义代码。*/ldrr2, _armboot_start//_armboot_start=_startldrr3, _bss_start  //subr2, r3, r2/* r2得到armboot的大小*/addr2, r0, r2/* r2得到要复制代码的末尾地址*///kaobei guo chengcopy_loop:/*重新定位代码*/ldmiar0!, {r3-r10}/*从源地址[r0]复制,r0指向_start(=0)*/stmiar1!, {r3-r10}/*复制到目的地址[r1],r1指向_TEXT_BASE(=0x33F80000)*/cmpr0, r2/* 复制数据块直到源数据末尾地址[r2]*/blecopy_loop#else /* NAND_BOOT *///relocate:copy_myself:/* movr10, lr */#if defined(CONFIG_S3C2410)@ reset NANDmovr1, #S3C2410_NAND_BASEldrr2, =0xf842@ initial value enable tacls=3,rph0=6,rph1=0strr2, [r1, #oNFCONF]ldrr2, [r1, #oNFCONF]bicr2, r2, #0x800@ enable chipstrr2, [r1, #oNFCONF]movr2, #0xff@ RESET commandstrbr2, [r1, #oNFCMD]movr3, #0@ wait1:addr3, r3, #0x1cmpr3, #0xablt1b2:ldrr2, [r1, #oNFSTAT]@ wait readytstr2, #0x1beq2bldrr2, [r1, #oNFCONF]orrr2, r2, #0x800@ disable chipstrr2, [r1, #oNFCONF]#elif defined(CONFIG_S3C2440)        /*从NAND闪存中把U-BOOT拷贝到RAM*/movr1, #S3C2440_NAND_BASE //S3C2440_NAND_BASE=0x4E000000ldrr2, =0xfff0@ initial value tacls=3,rph0=7,rph1=7ldrr3, [r1, #oNFCONF] //oNFCONF=0x00orrr3, r3, r2strr3, [r1, #oNFCONF]//oNFCONF=0x00ldrr3, [r1, #oNFCONT] //oNFCONT=0x04orrr3, r3, #1@ enable nand controllerstrr3, [r1, #oNFCONT]//oNFCONT=0x04#endif  //if defined(CONFIG_S3C2410)#if 0@ get ready to call C functions (for nand_read())ldrsp, DW_STACK_START@ setup stack pointermovfp, #0@ no previous frame, so fp=0#elseldrr0, _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*/subr0, r0, #CFG_MALLOC_LEN/* malloc area                      */subr0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */#ifdef CONFIG_USE_IRQ  /*include/configs/smdk2440.h*/subr0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)  //8K+4K#endifsubsp, r0, #12/* leave 3 words for abort-stack    */#endif   //#if 0@ copy u-boot to RAMldrr0, _TEXT_BASE //置第1个参数: UBOOT在RAM中的起始地址mov     r1, #0x0   //设置第2个参数:NAND闪存的起始地址//CFG_UBOOT_SIZE=0x40000=256kmovr2, #CFG_UBOOT_SIZE  // 设置第3个参数: U-BOOT的长度(256KB)blnand_read_ll   //调用nand_read_whole(),把NAND闪存中的数据读入到RAM中tstr0, #0x0 // 如果函数的返回值为0,表示执行成功beqok_nand_read  //执行内存比较,把RAM中的前4K内容与NAND闪存中的前4K内容进行比较, 如果完全相同, 则表示搬移成功#ifdef CONFIG_DEBUG_LLbad_nand_read:ldrr0, STR_FAILldrr1, SerBaseblPrintWord1:b1b@ infinite loop#endifok_nand_read:#ifdef CONFIG_DEBUG_LLldrr0, STR_OKldrr1, SerBaseblPrintWord#endif@ verifymovr0, #0@ldrr1, =0x33f00000ldrr1, _TEXT_BASEmovr2, #0x400@ 4 bytes * 1024 = 4K-bytesgo_next:ldrr3, [r0], #4ldrr4, [r1], #4teqr3, r4bnenotmatchsubsr2, r2, #4beqdone_nand_readbnego_nextnotmatch:#ifdef CONFIG_DEBUG_LLsubr0, r0, #4ldrr1, SerBaseblPrintHexWordldrr0, STR_FAILldrr1, SerBaseblPrintWord#endif#if 1        LDR   R0,   = GPJDAT        LDR   R1,   = 0x4        STR   R1,   [R0]#endif1:b1bdone_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:ldrr0, _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_SIZE128*/subr0, r0, #CFG_MALLOC_LEN/*向下是内存分配空间*/subr0, 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) */subr0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)#endifsubsp, r0, #12/*为 abort-stack 预留3个字,得到最终sp指针初始值*/clear_bss:ldrr0, _bss_start/*找到bss 段起始地址。*/ldrr1, _bss_end/* bss 段末尾地址。*/mov r2, #0x00000000/* 清零。*/clbss_l:strr2, [r0]/*bss 段地址空间清零循环。。。*/addr0, r0, #4cmpr0, r1bleclbss_l#if 1        LDR   R0,   = GPJDAT        LDR   R1,   = 0x1        STR   R1,   [R0]#endif     /*跳转到start_armboot函数入口,_start_armboot字保存函数入口指针*/ldrpc, _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 #ifndef CONFIG_SKIP_LOWLEVEL_INIT//关键的初始化子程序。cpu_init_crit: /*  flush v4 I/D caches  | 失效指令cache和数据cache       */movr0, #0//使I/D cache失效:将寄存器r0的数据传送到协处理器p15的c7中。C7寄存器//位对应cp15中的cache控制寄存器mcrp15, 0, r0, c7, c7, 0/* flush v3/v4 cache *///使TLB操作寄存器失效:将r0数据送到cp15的c8、c7中。C8对应TLB操作//寄存器mcrp15, 0, r0, c8, c7, 0/* flush v4 TLB *//* * disable MMU stuff and caches */ /*   disable MMU stuff and caches |   禁能MMU和cache       */ mrcp15, 0, r0, c1, c0, 0 //先把c1和c0寄存器的各位置0(r0 = 0)bicr0, r0, #0x00002300@ clear bits 13, 9:8 (--V- --RS)bicr0, r0, #0x00000087@ clear bits 7, 2:0 (B--- -CAM)orrr0, r0, #0x00000002@ set bit 2 (A) Alignorrr0, r0, #0x00001000@ set bit 12 (I) I-Cachemcrp15, 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. */movip, lr#ifdefined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)#elsebllowlevel_init  //位于board/smdk2440/lowlevel_init.S:用于完成芯片存储器的初始化,                             //执行完成后返回#endifmovlr, ipmovpc, lr#endif /* CONFIG_SKIP_LOWLEVEL_INIT *//* ************************************************************************* * * Interrupt handling * ************************************************************************* */@@ IRQ stack frame.@#define S_FRAME_SIZE72#define S_OLD_R068#define S_PSR64#define S_PC60#define S_LR56#define S_SP52#define S_IP48#define S_FP44#define S_R1040#define S_R936#define S_R832#define S_R728#define S_R624#define S_R520#define S_R416#define S_R312#define S_R28#define S_R14#define S_R00#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 */.macrobad_save_user_regssubsp, sp, #S_FRAME_SIZEstmiasp, {r0 - r12}@ Calling r0-r12ldrr2, _armboot_startsubr2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)subr2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stackldmiar2, {r2 - r3}@ get pc, cpsraddr0, sp, #S_FRAME_SIZE@ restore sp_SVCaddr5, sp, #S_SPmovr1, lrstmiar5, {r0 - r3}@ save sp_SVC, lr_SVC, pc, cpsrmovr0, sp.endm.macroirq_save_user_regssubsp, sp, #S_FRAME_SIZEstmiasp, {r0 - r12}@ Calling r0-r12add     r8, sp, #S_PCstmdb   r8, {sp, lr}^                   @ Calling SP, LRstr     lr, [r8, #0]                    @ Save calling PCmrs     r6, spsrstr     r6, [r8, #4]                    @ Save CPSRstr     r0, [r8, #8]                    @ Save OLD_R0movr0, sp.endm.macroirq_restore_user_regsldmiasp, {r0 - lr}^@ Calling r0 - lrmovr0, r0ldrlr, [sp, #S_PC]@ Get PCaddsp, sp, #S_FRAME_SIZEsubspc, lr, #4@ return & move spsr_svc into cpsr.endm.macro get_bad_stackldrr13, _armboot_start@ setup our mode stacksubr13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)subr13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stackstrlr, [r13]@ save caller lr / spsrmrslr, spsrstr     lr, [r13, #4]movr13, #MODE_SVC@ prepare SVC-Mode@ msrspsr_c, r13msrspsr, r13movlr, pcmovspc, lr.endm.macro get_irq_stack@ setup IRQ stackldrsp, IRQ_STACK_START.endm.macro get_fiq_stack@ setup FIQ stackldrsp, FIQ_STACK_START.endm/* * exception handlers */.align  5undefined_instruction:get_bad_stackbad_save_user_regsbl do_undefined_instruction.align5software_interrupt:get_bad_stackbad_save_user_regsbl do_software_interrupt.align5prefetch_abort:get_bad_stackbad_save_user_regsbl do_prefetch_abort.align5data_abort:get_bad_stackbad_save_user_regsbl do_data_abort.align5not_used:get_bad_stackbad_save_user_regsbl do_not_used#ifdef CONFIG_USE_IRQ.align5irq:get_irq_stackirq_save_user_regsbl do_irqirq_restore_user_regs.align5fiq:get_fiq_stack/* someone ought to write a more effiction fiq_save_user_regs */irq_save_user_regsbl do_fiqirq_restore_user_regs#else.align5irq:get_bad_stackbad_save_user_regsbl do_irq.align5fiq:get_bad_stackbad_save_user_regsbl do_fiq#endif
原创粉丝点击