EasyARM2200开发板学习笔记:启动代码分析

来源:互联网 发布:canvasjs.min.js 编辑:程序博客网 时间:2024/04/29 00:10
 

;定义堆栈的大小

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    ;IRQFIQ禁止, 中断模式

        LDR     SP, StackIrq     ;设置中断模式堆栈指针,指向StackIrq

;设置快速中断模式堆栈

        MSR     CPSR_c, #0xd1    ;IRQFIQ禁止, 快速中断模式

        LDR     SP, StackFiq     ;设置快速中断模式堆栈指针,指向StackFiq

;设置中止模式堆栈

        MSR     CPSR_c, #0xd7    ;IRQFIQ禁止, 中止模式

        LDR     SP, StackAbt     ;设置中止模式堆栈指针,指向StackAbt

;设置未定义模式堆栈

        MSR     CPSR_c, #0xdb    ;IRQFIQ禁止, 未定义模式

        LDR     SP, StackUnd     ;设置未定义模式堆栈指针,指向StackUnd

;设置系统模式堆栈

        MSR     CPSR_c, #0xdf    ;IRQFIQ禁止, 系统模式

        LDR     SP, =StackUsr    ;设置系统模式堆栈指针,指向StackUsr

 

        MOV     PC, R0           ;返回

 

ResetInit

;复位入口

;初始化外部总线控制器,根据目标板决定配置

 

        LDR     R0, =PINSEL2     ;PINSEL2的地址赋给RO

    IF :DEF: EN_CRP              ;判断是否有预定义EN_CRP

        LDR     R1, =0x0f814910  ;PINSEL2.20, 禁止JTAG调试

    ELSE

        LDR     R1, =0x0f814914  ;PINSEL2.21, 使能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