;定义堆栈的大小
FIQ_STACK_LEGTH EQU 0
IRQ_STACK_LEGTH EQU 9*8 ;每层嵌套需要9个字堆栈,允许8层嵌套
ABT_STACK_LEGTH EQU 0
UND_STACK_LEGTH EQU 0
;处理器模式常量定义
NoInt EQU 0x80 ;禁止IRQ中断
USR32Mode EQU 0x10 ;用户模式
SVC32Mode EQU 0x13 ;管理模式
SYS32Mode EQU 0x1f ;系统模式
IRQ32Mode EQU 0x12 ;中断模式
FIQ32Mode EQU 0x11 ;快速中断模式
PINSEL2 EQU 0xE002C014
BCFG0 EQU 0xFFE00000
BCFG1 EQU 0xFFE00004
BCFG2 EQU 0xFFE00008
BCFG3 EQU 0xFFE0000C
;引入的外部标号在这声明
IMPORT FIQ_Exception ;快速中断异常处理程序
IMPORT __main ;C语言主程序入口
IMPORT TargetResetInit ;目标板基本初始化
IMPORT StackUsr ;用户模式栈
IMPORT bottom_of_heap ;用户模式堆
IMPORT SoftwareInterrupt ;软件中断处理程序
;给外部使用的标号在这声明
EXPORT Reset
EXPORT __rt_div0
EXPORT __user_initial_stackheap
CODE32
AREA vectors,CODE,READONLY
ENTRY
;中断向量表
Reset
LDR PC, ResetAddr ;复位入口,程序在系统中执行的第一条指令
LDR PC, UndefinedAddr ;未定义指令异常入口地址
LDR PC, SWI_Addr ;软件中断入口地址
LDR PC, PrefetchAddr ;取指令中止异常入口地址
LDR PC, DataAbortAddr ;取数据中止异常入口地址
DCD 0xb9205f80 ;保留向量,值是其它中断向量累加和的补码
LDR PC, [PC, #-0xff0] ;中断请求IRQ入口地址
LDR PC, FIQ_Addr ;快速中断请求FIQ入口地址
ResetAddr DCD ResetInit
UndefinedAddr DCD Undefined
SWI_Addr DCD SoftwareInterrupt
PrefetchAddr DCD PrefetchAbort
DataAbortAddr DCD DataAbort
Nouse DCD 0
IRQ_Addr DCD 0
FIQ_Addr DCD FIQ_Handler
;未定义指令
Undefined
B Undefined ;发生未定义指令异常时执行死循环
;取指令中止
PrefetchAbort
B PrefetchAbort ;发生取指令中止异常时执行死循环
;取数据中止
DataAbort
B DataAbort ;发生取数据中止异常时执行死循环
;快速中断
FIQ_Handler
STMFD SP!, {R0-R3, LR} ;现场保护,将R0-R3, LR入栈
BL FIQ_Exception ;调用快速中断异常处理程序
LDMFD SP!, {R0-R3, LR} ;异常中断返回
SUBS PC, LR, #4 ;PC指向中断前没有被执行的指令
InitStack
;初始化堆栈
MOV R0, LR
;设置中断模式堆栈
MSR CPSR_c, #0xd2 ;IRQ和FIQ禁止, 中断模式
LDR SP, StackIrq ;设置中断模式堆栈指针,指向StackIrq
;设置快速中断模式堆栈
MSR CPSR_c, #0xd1 ;IRQ和FIQ禁止, 快速中断模式
LDR SP, StackFiq ;设置快速中断模式堆栈指针,指向StackFiq
;设置中止模式堆栈
MSR CPSR_c, #0xd7 ;IRQ和FIQ禁止, 中止模式
LDR SP, StackAbt ;设置中止模式堆栈指针,指向StackAbt
;设置未定义模式堆栈
MSR CPSR_c, #0xdb ;IRQ和FIQ禁止, 未定义模式
LDR SP, StackUnd ;设置未定义模式堆栈指针,指向StackUnd
;设置系统模式堆栈
MSR CPSR_c, #0xdf ;IRQ和FIQ禁止, 系统模式
LDR SP, =StackUsr ;设置系统模式堆栈指针,指向StackUsr
MOV PC, R0 ;返回
ResetInit
;复位入口
;初始化外部总线控制器,根据目标板决定配置
LDR R0, =PINSEL2 ;将PINSEL2的地址赋给RO
IF :DEF: EN_CRP ;判断是否有预定义EN_CRP宏
LDR R1, =0x0f814910 ;PINSEL2.2=0, 禁止JTAG调试
ELSE
LDR R1, =0x0f814914 ;PINSEL2.2=1, 使能JTAG调试
ENDIF
STR R1, [R0]
LDR R0, =BCFG0 ;初始化存储器组0的配置寄存器
LDR R1, =0x1000ffef
STR R1, [R0]
LDR R0, =BCFG1 ;初始化存储器组1的配置寄存器
LDR R1, =0x1000ffef
STR R1, [R0]
; LDR R0, =BCFG2 ;初始化存储器组2的配置寄存器
; LDR R1, =0x2000ffef
; STR R1, [R0]
; LDR R0, =BCFG3 ;初始化存储器组3的配置寄存器
; LDR R1, =0x2000ffef
; STR R1, [R0]
BL InitStack ;跳转到初始化堆栈代码段
BL TargetResetInit ;跳转到目标板基本初始化
B __main ;跳转到c语言入口
__user_initial_stackheap ;库函数初始化堆和栈
MOV pc,lr
__rt_div0 ;整数除法除数为0错误处理函数
B __rt_div0
StackIrq DCD IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4
StackFiq DCD FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4
StackAbt DCD AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4
StackUnd DCD UndtStackSpace + (UND_STACK_LEGTH - 1)* 4
IF :DEF: EN_CRP
IF . >= 0x1fc ;判断当前代码地址是否已超过0x1FC
INFO 1,"/nThe data at 0x000001fc must be 0x87654321.
/nPlease delete some source before this line."
ENDIF
CrpData
WHILE . < 0x1fc ;未到0x1FC则填充NOP指令
NOP
WEND
CrpData1
DCD 0x87654321 ;在0x1FC处放置0x87654321,启动加密功能
ENDIF
;/* 分配堆栈空间 */
AREA MyStacks, DATA, NOINIT, ALIGN=2
IrqStackSpace SPACE IRQ_STACK_LEGTH * 4 ;中断模式堆栈空间
FiqStackSpace SPACE FIQ_STACK_LEGTH * 4 ;快速中断模式堆栈空间
AbtStackSpace SPACE ABT_STACK_LEGTH * 4 ;中止义模式堆栈空间
UndtStackSpace SPACE UND_STACK_LEGTH * 4 ;未定义模式堆栈
END
//
LDR PC, [PC, #-0xff0] VICVectAddr寄存器的地址0xFFFFF030,PC当前位置是0x18,读出的值为0x18+8 = 0x20,0x20-0xff0 = 0xFFFFF030