启动代码startups分析

启动代码startups分析
启动代码startups分析

启动代码start.s(相当于bootloader的前端代码),开机就执行的代码,即0x0000处放置的代码。给CPU一个合适的工作环境。面向CPU内核和外围硬件,所以一般用汇编编写。

1、在起始地址分配中断向量表即中断处理函数(CPU要求的),以为向量空间只有4字节,所以一般只是一个跳转指令,去别处执行。

2、之后初始化存储器系统

3、初始多个模式下的堆栈(模式切换时,硬件给SP置位)

4、初始化有特殊要求的外围设备,如LED灯、看门狗

5、初始化用户的执行环境(在FLASH中运行太慢了,把代码整体搬迁到RAM中)

6、切换处理器的工作模式

7、调用主程序

(没见到有存储控制器的配置代码,也没见到有时钟初始化代码)

下面分析,所给的2410的启动代码实现了以上的那些功能,实现得显然不全,或者不需要,或者在工程代码的其它部分实现。

读程序时注意,所有程序都是逐行顺序执行的,要看清跳转指令。

GET 2410addr.s //用到了2410addr.s中的寄存器地址宏定义

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; Some ARM920 CPSR bit discriptions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Pre-defined constants//预定义的变量,一下后续代码中使用方便,与CPSR相关USERMODE EQU 0x10

FIQMODE EQU 0x11

IRQMODE EQU 0x12

SVCMODE EQU 0x13

ABORTMODE EQU 0x17

UNDEFMODE EQU 0x1b

MODEMASK EQU 0x1f

NOINT EQU 0xc0

I_Bit * 0x80

F_Bit * 0x40

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; MMU Register discription ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;p15 CP 15

;c0 CN 0

;c1 CN 1

;c2 CN 2

;c3 CN 3

CtrlMMU * 1

CtrlAlign * 2

CtrlCache * 4

CtrlWBuff * 8

CtrlBigEnd * 128

CtrlSystem * 256

CtrlROM * 512

;initialization L0 is MMU FULL_ACCESS, DOMAIN, SECTION

TLB_L0_INIT * 0x0C02 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; Start here //执行代码从这里开始;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

//IMPORT ,定义表示这是一个外部变量的标号,不是在本程序定义的

//EXPORT ,表示本程序里面用到的变量提供给其他模块调用的。

//以上两个在汇编和C语言混合编程的时候用到

AREA Init,CODE,READONLY

IMPORT __use_no_semihosting_swi

IMPORT Enter_UNDEF //有点extern的感觉

IMPORT Enter_SWI

IMPORT Enter_PABORT

IMPORT Enter_DABORT

IMPORT Enter_FIQ

ENTRY //这是程序的入口

//中断/异常向量表(跳转),上电第一条就执行 b ColdReset,跳转到ColdReset。

b ColdReset

b Enter_UNDEF ;UndefinedInstruction

b Enter_SWI ;syscall_handler or SWI

b Enter_PABORT ;PrefetchAbort

b Enter_DABORT ;DataAbort

b . ;ReservedHandler

b IRQ_Handler ;IRQHandler

b Enter_FIQ ;FIQHandler

;deal with IRQ interrupt

EXPORT IRQ_Handler //IRQ中断处理子程序

IRQ_Handler

IMPORT ISR_IrqHandler //服务程序在外部定义

STMFD sp!, {r0-r12, lr}

BL ISR_IrqHandler //跳转至服务程序

LDMFD sp!, {r0-r12, lr}

SUBS pc, lr, #4

;=======

; ENTRY

;=======

EXPORT ColdReset

ColdReset //上电执行复位异常函数,就跳转到这里来ldr r0,=WTCON ;watch dog disable

//关闭看门狗,还没初始化完系统,防止没“喂狗”再次复位,写看门狗寄存器WTCON即可

ldr r1,=0x0

str r1,[r0]

ldr r0,=INTMSK //关闭所有中断

ldr r1,=0xffffffff ;all interrupt disable

str r1,[r0]

ldr r0,=INTSUBMSK//关闭所有次级中断

ldr r1,=0x7ff ;all sub interrupt disable, 2002/04/10

str r1,[r0]

;****************************************************

;* Initialize stacks * //进行堆栈初始化

;****************************************************

bl InitStacks ; Stack Setup for each MODE

//跳转到initstack,对各个模式下的堆栈进行初始化。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;; copy excption table to sram at 0x0//对堆栈初始化之后,进行域初始化;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

IMPORT |Load$$EXCEPTION_EXEC$$Base|

IMPORT |Image$$EXCEPTION_EXEC$$Base|

IMPORT |Image$$EXCEPTION_EXEC$$Length|

ldr r0, =|Load$$EXCEPTION_EXEC$$Base| ;source data

ldr r1, =|Image$$EXCEPTION_EXEC$$Base| ;place exception talbe at 0x0

ldr r2, =|Image$$EXCEPTION_EXEC$$Length|

exception_cploop//这段没读明白,但是猜测是将flash中的程序代码拷贝到SDRAM中运行

sub r2, r2, #4

ldmia r0!, {r3}

stmia r1!, {r3}

cmp r2, #0

bge exception_cploop

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;; start main function in C language//跳转到用户代码main() ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

IMPORT __main

BL __main ;Don't use main() because ......

B .

;****************************************************

;* The function for initializing stack *

;****************************************************

IMPORT UserStack//堆栈指针的值是在外部就定义好的。

IMPORT SVCStack

IMPORT UndefStack

IMPORT IRQStack

IMPORT AbortStack

IMPORT FIQStack

InitStacks

;Don't use DRAM,such as stmfd,ldmfd......

;SVCstack is initialized before

;Under toolkit ver 2.50, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1' //每个模式下都有自己的堆栈指针SP,我们对其进行设置的前提就是进入该模式,即对CPSR 进行置位,才能访问这个模式下的SP,模式切换的时候,硬件会自动给SP置我们赋给的值。对CPSR的操作时按照“读出—修改—写入”的步骤进行的。即先用mrs读出,再用msr写入。

mrs r0,cpsr

bic r0,r0,#MODEMASK

orr r1,r0,#UNDEFMODE|NOINT

msr cpsr_cxsf,r1 ;UndefMode//未定义模式堆栈初始化

ldr sp,=UndefStack

//cpsr_cxsf 下划线后表示域,即操作哪些位。

orr r1,r0,#ABORTMODE|NOINT

msr cpsr_cxsf,r1 ;AbortMode//中止模式堆栈初始化

ldr sp,=AbortStack

orr r1,r0,#IRQMODE|NOINT

msr cpsr_cxsf,r1 ;IRQMode//IRQ模式

ldr sp,=IRQStack

orr r1,r0,#FIQMODE|NOINT

msr cpsr_cxsf,r1 ;FIQMode//FIQ模式

ldr sp,=FIQStack

;bic r0,r0,#MODEMASK|NOINT//管理模式

orr r1,r0,#SVCMODE|NOINT

msr cpsr_cxsf,r1 ;SVCMode

ldr sp,=SVCStack

;USER mode is not initialized.//没有对用户模式下的堆栈进行初始化。

mov pc,lr ;The LR register may be not valid for the mode changes. //之前使用的BL指令,可以用LR指令返回bl Initialize stacks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;; End of Startup.c ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

各部分执行顺序如下图所示:

相关主题
相关文档
最新文档