AT91RM9200启动代码start.s解读与学习笔记(3)

接着讲,这次让我们来具体分析一下,我们就按照该文件的执行顺序来进行分析:

首先,程序入口地址进入后,第一条指令便是

b	ResetHandler

 

直接跳到标号ResetHandler处,执行复位后的处理程序,这段程序是:

ResetHandler
	;Set up User Mode, set User Mode Stack and disable interrupts	
	msr	CPSR_c, #(SVCMODE|I_BIT|F_BIT)

 

这句代码做了一件事,让系统进入管理模式,并且屏蔽IRQ和FIQ中断,这里用到了cpsr寄存器,该寄存器是程序状态寄存器,具体用法我的博客的另外一篇文章有简单的介绍。用到的汇编指令msr是将寄存器的值或者立即数放入程序状态寄存器中。

接下来,程序将顺序执行,有如下代码:

	ldr     r1, = AT91C_BASE_CKGR	; Get the CKGR Base Address
	ldr 	r0, = AT91C_CKGR_MOSCEN:OR:AT91C_CKGR_OSCOUNT
	str     r0, [r1, #CKGR_MOR]

 

该段代码的作用是使能主振荡器,并制定慢时钟的周期数作为主振荡器的启动时间。

接下来,重定向异常向量表:

; relocate exeception table	 
	adr	r0, ResetEntry
	mov	r1, #0
	mov	r2, #16
copyex
	subs	r2, r2, #1
	ldr	r3, [r0], #4
	str	r3, [r1], #4
	bne	copyex	

 

adr指令是获取ReserEntry标号地址赋予r0,接下来进行的是一个循环,目的是将ResetEntry地址对应的指令赋予地址0x0处,即起始地址处,同理,循环16次即把其他的中断服务程序首地址也放在起始地址处,每次地址加4,即一个字。而起始地址处是9200固定的中断跳转的地方。所以,本段代码实现了将中断服务程序的首地址放到中断向量表中,有中断的时候会执行跳转,到中断服务程序继续执行。

接下来进行基本的初始化:

IMPORT	LowLevelInit
	
;	ldr	r1, =0x204000;=SVCStack
;	bic	r1, r1, #3				; Insure word alignement
;	mov	sp, r1					; Init stack SYS
	mov	sp, #0x204000
	
	bl 	LowLevelInit

 

先声明lowlevelinit函数来自外部,实际上来自init.c文件中,然后初始化了管理模式的堆栈,然后进行函数调用,执行一些初始化工作,该初始化工作的内容在这里就不多讲了,主要包含PLL初始化,中断控制器的初始化,SDRAM初始化,isr初始化,时钟计数器初始化,调试串口初始化,串口配置等工作。

然后进行的是堆栈初始化:

;Initialize stacks
	bl	InitStacks

 

也采用的是程序调用的方式,程序代码如下:

;function initializing stacks
InitStacks
	;Don't use DRAM,such as stmfd,ldmfd......
	;SVCstack is initialized before
	;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
	mrs	r0,cpsr                  ;读取程序状态寄存器
	bic	r0,r0,#MODEMASK          ;清楚寄存器的低五位
	orr	r1,r0,#UNDEFMODE|NOINT   ;修改寄存器的值,使工作在未定义模式,禁用中断
	msr	cpsr_cxsf,r1		;UndefMode;回写到程序状态寄存器中,执行改变工作模式的操作
	ldr	sp,=UndefStack          ;获得未定义模式的堆栈地址
	
	orr	r1,r0,#ABORTMODE|NOINT
	msr	cpsr_cxsf,r1		;AbortMode
	ldr	sp,=AbortStack

	orr	r1,r0,#IRQMODE|NOINT
	msr	cpsr_cxsf,r1		;IRQMode
	ldr	sp,=IRQStack
    
	orr	r1,r0,#FIQMODE|NOINT
	msr	cpsr_cxsf,r1		;FIQMode
	ldr	sp,=FIQStack

	bic	r0,r0,#MODEMASK|NOINT
	orr	r1,r0,#SVCMODE
	msr	cpsr_cxsf,r1		;SVCMode
	ldr	sp,=SVCStack
	
	;USER mode has not be initialized.
	
	mov	pc,lr 
	;The LR register won't be valid if the current mode is not SVC mode.

 

该段程序主要实现的是各种模式下的堆栈的初始化工作。学过单片机我们知道,我们在进行函数调用和中断的时候,都会用到堆栈,为什么我们用单片机的时候没有涉及到堆栈的初始化呢,那是因为我们在用单片机的时候,基本上只有一种模式,,一个堆栈,而ARM则有很多种模式,各个模式的堆栈是不一样的,所以就涉及到了各个模式要初始化不同的堆栈地址,这就是我们这段程序的目的。

根据第一个未定义模式的注释我们可以了解后面几种模式的操作,都是一样的,读取,修改,回写的方法。最后的一个mov指令进行子程序返回。

下一次再接着讲,今天先到这儿~~~~

posted @ 2010-05-21 21:40  东 哥  阅读(977)  评论(0编辑  收藏  举报