Chinaunix首页 | 论坛 | 博客
  • 博客访问: 845375
  • 博文数量: 321
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 936
  • 用 户 组: 普通用户
  • 注册时间: 2013-02-23 11:25
文章分类

全部博文(321)

文章存档

2017年(1)

2016年(10)

2015年(61)

2014年(187)

2013年(62)

分类: 嵌入式

2013-03-28 23:20:48

/*
 *  armboot - Startup Code for ARM920 CPU-core
 *
 *  Copyright (c) 2001 Marius Gr鰃er
 *  Copyright (c) 2002 Alex Z黳ke
 *  Copyright (c) 2002 Gary Jennejohn
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */


#include
#include


/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */
/*
 * 全局入口为.globl_start
 * 设置异常向量
*/


.globl _start//@_start是GNU汇编器的默认入口标签========系统复位位置,整个程序入口
_start: b start_code//ARM体系结构规定在上电复位后的起始位置,必须有8条连续的跳转指令,通过硬件实现。
//相当于中断向量表
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


//@.word为GNU ARM汇编特有的伪操,作为分配一段字内存单元(分配的单元为字对齐的),可以使用.word把标志符作为常量使用。
//如_fiq:.word fiq即把fiq存入内存变量_fiq中,也即是把fiq放到地址_fiq中。
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort/*内存操作异常,0x0c*/
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq


.balignl 16,0xdeadbeef


.balignl 16,0xdeadbeef  //0x3c=60   4*(8+7)=60   //‘.balign 16’向后移动位置计数器直至计数器的值等于16的倍数。且使用0xdeadbeef来填充空白区
                       //该数字是个魔数。通常用于在启动时读取它并修改它为0,并与原值比较
                       //以判断它是从nor nand启动


/*
 *************************************************************************
 *
 * 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:
///* 保存变量的数据区 */
_TEXT_BASE:          //代码重定位后所在的地址
.word TEXT_BASE /*uboot映像在SDRAM中的重定位地址*/


.globl _armboot_start
_armboot_start:
.word _start


//在_armboot_start标号处,保存了_start的值,也就是说,_armboot_start是存放_start的地址。
/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start//@__bss_start定义在和开发板相关的u-boot.lds中,_bss_start保存的是__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
//上面这段代码,主要保存一些全局变量,用于BOOT程序从FLASH拷贝到RAM,或者其它的使用。




/*
 * the actual start code
 */


start_code:
/*
* set the cpu to SVC32 mode
* cpsr的低八位是:I F T M M M M M
*  中断禁止位:I F  Thumb位 模式位  svc为10011
*/
 
/*******************先设置为超级用户SVC******************************/

mrs r0,cpsr       /*状态寄存器读取指令*/
bic r0,r0,#0x1f   /*位清除指令*/
orr r0,r0,#0xd3   /*逻辑或操作指令*/  1101,0011
msr cpsr, r0 //11关中断,0,thumb模式位


@ bl coloured_LED_init
@ bl red_LED_on
//AT91RM9200 cpu
//#include  CONFIG_AT91RM9200DK,有没有定义,看包含的头文件
//#include
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)  //未定义
/*
* relocate exception table
*/
ldr r0, =_start
ldr r1, =0x0
mov r2, #16
copyex:
subs r2, r2, #1//sub带上了s用来更改进位标志,对于sub来说,若发生借位则C标志置0,没有则为1,这跟adds指令相反!要注意。
ldr r3, [r0], #4/*后索引,r0地址内容加载给r3后,r0+4*/
str r3, [r1], #4
bne copyex
#endif


//========针对S3C2400和S3C2410进行特殊处理==========
#ifdef CONFIG_S3C24X0
/* turn off the watchdog */
//S3C2440A datasheet.pdf
# if defined(CONFIG_S3C2400)//未定义
#  define pWTCON 0x15300000//关闭看门狗定时器的自动复位功能并屏蔽所有中断,上电后看门狗为开,中断为关
#  define INTMSK 0x14400008 /* Interupt-Controller base addresses */
#  define CLKDIVN 0x14800014 /* clock divisor register */
#else//执行
#  define pWTCON 0x53000000
#  define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
#  define INTSUBMSK 0x4A00001C
#  define CLKDIVN 0x4C000014 /* clock divisor register */
# endif
#define CLK_CTL_BASE 0x4C000000 /* tekkaman */
#define MDIV_405 0x7f << 12 /* tekkaman */
#define PSDIV_405 0x21 /* tekkaman */
#define MDIV_200 0xa1 << 12 /* tekkaman */
#define PSDIV_200 0x31 /* tekkaman */


//关闭看门狗
ldr r0, =pWTCON/*disable*/
mov r1, #0x0
str r1, [r0]//对于S3C2440和S3C2410的WTCON寄存器的[0]控制允许或禁止看门狗定时器的复位输出功能,设置为“0”禁止复位功能。


/*
* mask all IRQs by setting all bits in the INTMR - default
*/
//到C第二阶段有enable_interrupts (); 来使能中断  
//关闭总中断
mov r1, #0xffffffff     ////关闭所有中断服务
ldr r0, =INTMSK /*中断is masked*/
str r1, [r0]

//关闭子中断
# if defined(CONFIG_S3C2410)//十一个。。。。。。未定义
ldr r1, =0x7ff//INTMSK寄存器的32位和INTSUBMSK寄存器的低11位每一位对应一个中断
ldr r0, =INTSUBMSK
str r1, [r0]
# endif


#if defined(CONFIG_S3C2440)//十五个。。。。。。
ldr r1, =0x7fff
ldr r0, =INTSUBMSK
str r1, [r0]
#endif


//设置分频比。主FCLK=MCLK=400MHZ,HCLK=100,PCLK=50,所以是1:4:8
// 因为FCLK != HCLK,所以为异步模式,要协处理器
#if defined(CONFIG_S3C2440)
/* FCLK:HCLK:PCLK = 1:4:8    fclk=405MHZ ==> 230页*/
ldr r0, =CLKDIVN
mov r1, #5//101
str r1, [r0]


// 协处理器,异步模式的时候
mrc p15, 0, r1, c1, c0, 0 //P215
orr r1, r1, #0xc0000000
mcr p15, 0, r1, c1, c0, 0

//主时钟  MPLL
mov r1, #CLK_CTL_BASE /*P226 set MPll--su*/
mov r2, #MDIV_405
add r2, r2, #PSDIV_405
str r2, [r1, #0x04] /* MPLLCON tekkaman */


#else
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]



mrc p15, 0, r1, c1, c0, 0
orr r1, r1, #0xc0000000
mcr p15, 0, r1, c1, c0, 0 /*write ctrl register tekkaman*/


mov r1, #CLK_CTL_BASE /* tekkaman*/
mov r2, #MDIV_200
add r2, r2, #PSDIV_200
str r2, [r1, #0x04]
#endif
#endif /* CONFIG_S3C24X0 */




/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
//在重新定位之前,要进行RAM初始化
//如果没有定义的话。执行ifndef
//用bl 会把下一条要 执行的地址放在lr.
#ifndef CONFIG_SKIP_LOWLEVEL_INIT//mini2440.h===undef
bl cpu_init_crit//bl 带返回的跳转指令
#endif


/***************** CHECK_CODE_POSITION ******************************************/
//考虑要不要搬运代码
//比较  _start 和_TEXT_BASE,如果两者相等,说明是直接加载到内存中的自主启动
//  如果不等,则说明是nand或者nor启动
adr r0, _start /* r0 <- current position of code   *///地址为0
ldr r1, _TEXT_BASE /* test if we run from flash or RAM *///?board/mini2440/config.mk==0x33F80000


cmp     r0, r1                  /* 测试判断是从Flash启动,还是已经在SDRAM运行  */
beq     stack_setup             //痰进过重定位代码
//相等的话是加载启动,直接跳到设置堆栈;不相等的话判断是nand或者是nor
/***************** CHECK_CODE_POSITION ******************************************/


//不相等的话,判断是nor或者是nand启动
//从nor启动时0地址是NOR,0x40000000是SRAM
//从nand启动时,0x40000000是SRAM的地址,0地址也是SRAM的地址
//这里把0x4000003C地址的内容改为
//0,看#0x3c地址的内容是否也该为0.如果是改为0则是NAND启动
//0x3c地址放的是一个魔数,如0xdeadbeef
/***************** CHECK_BOOT_FLASH ******************************************/
ldr r1, =( (4<<28)|(3<<4)|(3<<2) ) /* address of Internal SRAM  0x4000003C*/
mov r0, #0 /* r0 = 0 */
str r0, [r1]




mov r1, #0x3c /* address of men  0x0000003C*/
ldr r0, [r1]
cmp r0, #0
bne relocate  //不相等,则是从nor启动


/* recovery  从NAND启动,则把魔数还原 */
ldr r0, =(0xdeadbeef)//相等的话是nand启动,把之前那个 0x4000003C上的数据还原
ldr r1, =( (4<<28)|(3<<4)|(3<<2) )
str r0, [r1]
/***************** CHECK_BOOT_FLASH ******************************************/






/***************** NAND_BOOT *************************************************/


#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
//初始化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  //调用C函数把代码从NAND拷贝到内存
ldr r0, =TEXT_BASE   //目的地址U-BOOT加载到内存的地址
mov r1, #0x0         //源地址//从0地址开始搬
mov r2, #LENGTH_UBOOT  //长度 算一下U-BOOT的长度
bl nand_read_ll    //跳到这个函数里面去执行搬运
//返回成功返回给R0;
tst r0, #0x0     //拷贝成功返回0
beq ok_nand_read//返回成功


bad_nand_read:    //拷贝不成功则停在这里
loop2://搬运失败;根据返回值是0-成功,非0失败
b loop2 @ infinite loop


//返回成功还要进行校验
ok_nand_read:      //从0地址和TEXT_BASE分别取0x400内容出来对比验证
@ 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//不相等,搬运有问题,跳到loop3
subs r2, r2, #4
beq stack_setup//搬完,跳回设置堆栈
bne go_next


notmatch://不相等
loop3:
b loop3 @ infinite loop
#endif


#ifdef CONFIG_S3C2410


/* Offset */
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFSTAT 0x10


@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =0xf830 @ initial value
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
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1


nand2:
ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x1
beq nand2

ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #oNFCONF]

@ 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
bl nand_read_ll  //跳到C语言那边去搬运
tst r0, #0x0 //因为我们c那边成功的话,返回0,如果相等,则成功。
beq ok_nand_read


bad_nand_read:  //拷贝不成功
loop2:
b loop2 @ infinite loop 死循环




ok_nand_read: //搬运成功
//把nand flash 前面的一小段代码加载出来和加载到内存里面的内容进行比较。
                  ;//校验其中一部分代码
@ 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   // r2为测试部分的大小 r2=0x400
beq stack_setup   //跳到堆栈设置处 //搬运完
bne go_next //未搬完,继续搬


notmatch:
loop3:
b loop3 @ infinite loop


#endif
/***************** NAND_BOOT *************************************************/






/***************** NOR_BOOT *************************************************/
//地址修正
relocate: /* relocate U-Boot to RAM    */
      /*********** CHECK_FOR_MAGIC_NUMBER***************/
ldr r1, =(0xdeadbeef)
cmp r0, r1
bne loop3
      /*********** CHECK_FOR_MAGIC_NUMBER***************/


adr r0, _start /* r0 <- current position of code   */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
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
/***************** NOR_BOOT *************************************************/


/* Set up the stack 从_TEXT_BASE开始往下分配栈空间 */
//设置堆栈
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot   */
//预留一部分地址用来存放变量
sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area              */
//@CFG_MALLOC_LEN=128*1024+CFG_ENV_SIZE=128*1024+0x1@0000=192K
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_start----_bss_end中的数据清零
//u-boot.lds
//清楚BSS段
clear_bss:
ldr r0, _bss_start /* find start of bss segment        *///u-boot.lds
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


//跳到阶段二C语言中去
//这边的ldr是指令,加载内容,伪指令,加载地址
ldr pc, _start_armboot//加载_start_armboot的内容。===_start_armboot的内容又是start_armboot


#if defined(CONFIG_MINI2440_LED)
#define GPIO_CTL_BASE 0x56000000
#define oGPIO_B 0x10
#define oGPIO_CON 0x0
/* R/W, Configures the pins of the port */
#define oGPIO_DAT 0x4
#define oGPIO_UP 0x8
/* R/W, Pull-up disable register */
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_B
ldr r2, =0x295551
str r2, [r1, #oGPIO_CON]
mov r2, #0xff
str r2, [r1, #oGPIO_UP]
ldr r2, =0x1c1
str r2, [r1, #oGPIO_DAT]
#endif


_start_armboot: .word start_armboot
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x10000
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4 


/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */
//主要设置CP15,禁止MMU。


#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*
* flush v4 I/D caches
*/
//初始化cache 
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */  //C7高速缓存和写缓存控制
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */  //C8 TLB控制(存储保护和控制)


/*
* disable MMU stuff and caches
*/
//关闭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   //r0=****,****,****,****,**01,**00,0***,*010
mcr p15, 0, r0, c1, c0, 0
     //C1是一个控制寄存器,它控制MMU(MPU)的使能,数据Cache或统一Cache的使能,指令Cache的使能,写缓冲使能等


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




//设置内存区控制期。具体值由厂商或硬件工程师提供。在UBOOT中的设置文件是
//board/gec2440/lowlevel_init.S
//先保存之前的lr,防止在BL时,lr把之前的覆盖掉了
mov ip, lr          //从子程序跳到孙程序 呵呵
bl lowlevel_init


mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */


/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */


@
@ IRQ stack frame.    //  这些定义个别没用到,发生异常时,ro r1 r2等现场保护的偏移量。如.macro bad_save_user_regs有使用
@
#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
 */


// ;保存中断前的r0-r12,sp_SVC, lr_SVC, pc, cpsr
.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)
sub r2, r2, #(CONFIG_SYS_MALLOC_LEN)
/* set base 2 words into abort stack */
sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
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 r7, sp, #S_PC
stmdb r7, {sp, lr}^ @ Calling SP, LR
str lr, [r7, #0] @ Save calling PC
mrs r6, spsr
str r6, [r7, #4] @ Save CPSR
str r0, [r7, #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
/* return & move spsr_svc into cpsr */
subs pc, lr, #4
.endm


//;以_armboot_start为基址,向下作为堆栈,存放lr,spsr
.macro get_bad_stack
ldr r13, _armboot_start @ setup our mode stack
sub r13, r13, #(CONFIG_STACKSIZE)
sub r13, r13, #(CONFIG_SYS_MALLOC_LEN)
/* reserve a couple spots in abort stack */
sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8)


str lr, [r13] @ save caller lr / spsr
mrs lr, spsr
str lr, [r13, #4]


mov r13, #MODE_SVC @ //prepare SVC-Mode  10011  把spsr设置为SVC-Mode
@ msr spsr_c, r13
msr spsr, r13
mov lr, pc   @//把下下个指令给lr
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        ;macro
bad_save_user_regs   ;macro
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:
//Apollo +
/*
get_irq_stack
irq_save_user_regs
bl do_irq
irq_restore_user_regs
*/
    /* use IRQ for USB and DMA */
        sub    lr, lr, #4             @ the return address
        ldr    sp, IRQ_STACK_START     @ the stack for irq
       stmdb   sp!,  { r0-r12,lr }     @ save registers
        
        ldr    lr, =int_return         @ set the return addr
        ldr    pc, =IRQ_Handle         @ call the isr
int_return:
        ldmia  sp!, { r0-r12,pc }^    @ return from interrupt
//Apollo -


.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

阅读(1243) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~