微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 2440启动代码和中断处理过程

2440启动代码和中断处理过程

时间:11-09 来源:互联网 点击:
启动代码与Bootloader不同,主要是指进入C语言之前的汇编代码,网上都称为是bootloader的stage1,一般通用的内容包括:
(1) 定义程序入口点
(2)设置异常向量表
(3)初始化存储系统
(4)初始化用户程序的执行环境
(5)初始化堆栈指针寄存器,改变处理器的模式
(6)设置FIQ/IRQ中断处理程序入口
(7)进入C程序

1、编译器选择
GBLL THUMBCODE
[ {CONFIG} = 16
THUMBCODE SETL {TRUE}
CODE32
|
THUMBCODE SETL {FALSE}
]
因为处理器分为16位/32位两种工作状态,程序的编译器也是分16位和32两种编译方式,所以这段程序用于根据处理器工作状态确定编译器编译方式,程序不难理解,主要解释一下符号“[ | ]”的意思,上面的程序是指:
if({CONFIG} = 16 )
{ THUMBCODE SETL {TRUE}
CODE32 }
else
THUMBCODE SETL {FALSE}
2、宏定义
MACRO
$HandlerLabelHANDLER$HandleLabel
$HandlerLabel
sub sp,sp,#4
stmfd sp!,{r0}
ldrr0,=$HandleLabel
ldrr0,[r0]
strr0,[sp,#4]
ldmfdsp!,{r0,pc}
MEND
$HandlerLabel是宏的地址标号,HANDLER是宏名,$HandleLabel是宏的参数,$标号在宏指令展开时,标号会替换为用户定义的符号。在此后,所有遇到$HandlerLabel HANDLER $HandleLabel这种形式的表达式都会被展开成$HandlerLabel到MEND之间的函数。
例如:ADC_IRQ HANDLER HandleADC即代表如下函数,语句ldr pc,=ADC_IRQ的作用也就是跳转到这个函数:
ADC_IRQ
sub sp,sp,#4
stmfd sp!,{r0}
ldrr0,=HandleADC
ldrr0,[r0]
strr0,[sp,#4]
ldmfdsp!,{r0,pc}
这段程序用于把ADC中断服务程序的首地址装载到pc中,跳转到中断处理函数,称之为“加载程序”。HandleADC是一个地址标号,它的内容就是ADC中断服务程序的地址标号,即文件最后的那个表HandleADC # 4所示,将HandleADC # 4中的4换成中断服务程序的地址标号即是,程序在这里定义了一个数据区,存放各种中断服务程序的首地址。每个字空间都有一个标号,以Handle***命名。

3、寄存器及堆栈设置
按照上面的顺序,可以比较容易读懂启动代码的作用,主要就是通过设置特殊功能寄存器来达到对系统参数的设定。依次禁止看门狗,中断,设定时钟控制寄存器,存储器控制寄存器等等。
由于各个工作模式下的堆栈指针是相互独立的,所以要分别进入各个模式下设置其堆栈指针,基本上都差不多,比如未定义指令模式下的设置:
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1
ldr sp,=UndefStack
UnderStack是在程序后面用UnderStack # 256建立的一个堆栈空间的首地址,这部分空间建立在RAM中,256字节空间的堆栈大小。

4、初始化用户程序的执行环境
之前在44B0里的启动代码里还有包括把ROM里的程序拷贝到RAM中并跳转到RAM运行程序,也就是把加载状态下的程序按照编译连接时的设置重新排布成运行时的程序状态,以达到符号能够正确连接的目的,这里是涉及到了所谓的映像文件,但是2410这里没有这一段,即程序的加载态就是它的运行态,所以要求烧写程序时必须要把它烧写在设置的RO地址上,否则程序将不能正确执行。下面这段程序实现RW数据初始化,只是把数据段复制到高地址,如果没有设置RW的话这段代码也不会执行。
;Copy and paste RW data/zero initialized data
ldr r0, =|Image$$RO$$Limit| ; Get pointer to ROM data
ldr r1, =|Image$$RW$$Base| ; and RAM copy
ldr r3, =|Image$$ZI$$Base|

;Zero init base => top of initialised data
cmp r0, r1 ; Check that they are different
beq %F2
1
cmp r1, r3
ldrcc r2, [r0], #4
strcc r2, [r1], #4
bcc %B1
2
ldr r1, =|Image$$ZI$$Limit|
mov r2, #0
3
cmp r3, r1 ; Zero init
strcc r2, [r3], #4
bcc %B3
b %F1(B1)的意思是在临近的地址标号跳转,F是向后寻找,B是向前寻找。

5、说说映象文件
用ADS编译产生的映像文件有.axf、.bin、.hex等等格式,就拿要直接烧进Flash里的.bin文件来说,在其他书上看到有这么句话“映像文件一般由域组成,域由最多三个输出段(RO,RW,ZI)组成,输出段又由输入段组成。”
对于这段话,前两句是比较好理解的,域就是整个映像文件,对于大部分程序来说就只有一个域,也就是烧进Flash里的那部分东东,称作加载域;输出段就是用AREA定义的RO,Rw,一般就这两个,拿前面的bootloader来说,整体框架是这样的:
AREA Init,CODE,READONLY ;<--RO段
ENTRY
Entry;<--CODE部分
… …
SMRDATA DATA ;<--DATA部分
… …
AREARamData, DATA, READWRITE ;<--RW段
… …

然而对于输出段又由输入段组成却着实糊涂了好一阵,输入段是指源程序的代码(CODE)部分和数据(DATA)部分。上面这个框架中,在RO输出段的Entry下开始一系列的

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top