;定义堆栈的大小 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,"
The data at 0x000001fc must be 0x87654321.
Please 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 |