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