您的位置 首页 国产IC

2440发动代码和中止处理进程

启动代码与Bootloader不同,主要是指进入C语言之前的汇编代码,网上都称为是bootloader的stage1,一般通用的内容包括:(1)定义程序入口…

发动代码与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下开端一系列的汇编指令操作,这个应该是CODE输入段,而SMRDATA DATA引领DCD用于拓荒一片数据存储空间,这部分应该是DATA输入段,它与RW里的数据不同之处在于这部分数据不能被修正。
在ADS编译前在ARM-Linker里的Ro_Base和Rw_Base两个地址值,便是指两个输出段的开端地址,即程序是依照你设置的这种方法排布在内存中的,各个地址标号依据这两个值确认。可是,用Ultraedit翻开bin文件却发现其实Rw是跟在Ro后边的,也便是说,这两个段并没有依照你设置的地址开端,由此引出映像文件的加载域和运转时域两个概念。
加载域便是用Ultraedit翻开看到的程序最原始的状况,而运转时域则是程序在履行时依照你设定的方法排布的状况,明显,上面设置的两个地址是针对运转时域来设置的,程序要满意上面的设置才干正确衔接。也便是程序开端阶段(加载域状况)是不能正确衔接的,不过开端时不需求用到Rw里的数据,程序是能够运转的,因而有必要在需求用到Rw数据之前把它复制到上面设置的方位上,这便是bootloader里初始化用户程序的履行环境部分的效果,把数据移动到正确的方位!
复制完Rw里的数据之后,一切的符号都能够正确衔接,这时跳转到main函数里去履行程序就能够了。2410的这段发动代码没有进行Ro的复制,所以假设你把程序烧在0x0地址,那么Ro就有必要设置成0x0,假设你设置成0x30000000,那么Ro就有必要设置成0x30000000,假设Rw不设置,它将默许跟在Ro后边,不然就履行上面的搬家代码,挪到正确的方位上。由于本体系是选用NandFlash发动的,开端的发动代码有必要要在0x0处的SRAM里履行,所以,假设要把这段发动代码当作NandFlash的发动代码的话,Ro就有必要设成0x0。

6、中止处理进程
要运用中止,首要需求清掉程序状况寄存器CPSR里的IRQ位,这个很简单被忽略了。再之后才是考虑与中止有关的相应寄存器.
这个几个寄存器比较简单弄混了:
SRCPND/SUBSRCPND:只需中止发生的条件满意,例如外部电平,守时溢出等等,SRCPND/SUBSRCPND的相应位就会被置位,它不论其他当地的设置怎么,所以某一时间可能有几个位一起被置位了(几个中止一起发生)。
INTMSK/INTSUBMSK:这个是中止屏蔽位,清零表明答应中止请求,默许是制止了一切的中止请求。
INTPND:它表明处理器接下来就要去处理的那个中止,某一时间只可能有一个位被置位。这个寄存器置位的必要条件是SRCPND/SUBSRCPND现已是1,并且INTMSK/INTSUBMSK相应位现已清零。
SRCPND/SUBSRCPND和INTPND都不会主动清零,要程序向相应的位写1才干清零。

2410不支持中止嵌套,中止发生后处理器进入到IRQ方法,只要在比及这个中止处理完之后才干呼应下一次中止。
假设一起发生多个中止,就触及到了中止优先级的问题。SRCPND寄存器对应的32个中止源总共被分为6个组,每个组由一个ARBITER(0~5)对其进行办理。中止有必要先由所属组的ARBITER(0~5)进行第一次优先级判别然后再到ARBITER6进行第2次判别。能够更改的仅仅组里的优先级次第。
PRIORITY的各个位被分为两种类型,一种是ARB_MODE,另一种为ARB_SEL,拿ARBITER0来说,这个组总共包含了四种中止源:EINT0~EINT3,别离对应Req0~Req3,很明显ARB_SEL0便是决议了这四种中止的优先次第,假设这个组里的两个中止一起发生,将会把排在前面的先传递给ARBITER06进行第2次判别。ARB_MODE0置1代表敞开优先级次第旋转,当该方位为1之后,ARB_SEL0的值会在每处理完一次中止后依次改动。

中止处理流程
发动代码开端是一个反常向量表,这个向量表是固定的,由处理器决议,有必要要放在0x0地址那个当地,这个跟51单片机的中止向量表相相似。
b ResetHandler
b HandlerUndef ;handler for Undefined mode
b HandlerSWI ;handler for SWI interrupt
b HandlerPabort ;handler for PAbort
b HandlerDabort ;handler for DAbort
b . ;reserved
b HandlerIRQ ;handler for IRQ interrupt
b HandlerFIQ ;handler for FIQ interrupt
当发生IRQ中止时,PC首要无条件地来到0x18这个地址处,这个0x18便是处理器决议的IRQ中止的进口地址,所以要在这个地址处放一条跳转指令b HandlerIRQ,PC接着跳转到HandlerIRQ地址标号处,这儿寄存着一个宏句子:
HandlerIRQ HANDLER HandleIRQ
依照上面说的宏翻开,其实是履行这么一段句子:
sub sp,sp,#4 ;留下仓库的第一个方位
stmfd sp!,{r0} ;维护R0由于后边要用R0传递值
ldrr0,=HandleIRQ ;将HandleIRQ这个地址标号的值传如R0
ldrr0,[r0];取寄存在HandleIRQ里的那个值
strr0,[sp,#4] ;把取到的值压入栈
ldmfdsp!,{r0,pc};康复R0并把PC指向HandleIRQ里寄存的地址值
HandleIRQ里寄存是什么值呢?代码最终有个这样的表,这个表便是在SDRAM里的别的一张反常向量表,这张表能够依据需求修正_ISR_STARTADDRESS的值来随意更改它的方位。
^_ISR_STARTADDRESS
HandleReset#4
HandleUndef#4
HandleSWI#4
HandlePabort #4
HandleDabort #4
HandleReserved #4
HandleIRQ#4
HandleFIQ#4
这儿完结结构化一片地址空间的意图,可见在HandleIRQ这儿预留了4个字节的空间,可是这个空间里现在放的是什么东西呢?
在代码的初始化进程中有这么一段代码:
ldr r0,=HandleIRQ ; Setup IRQ handler
ldr r1,=IsrIRQ
str r1,[r0]
原来是把IsrIRQ地点的地址值放到这个当地,那便是宏完结了把PC指向IsrIRQ的意图。程序来到IsrIRQ:
IsrIRQ
sub sp,sp,#4;预留仓库
stmfd sp!,{r8-r9} ;维护R8,R9

ldr r9,=INTOFFSET ;找出发生哪种中止
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc} ;将PC指向相应的中止处理地址
假设发生了EINT0中止来到了这儿,那么PC将会跳转到HandleEINT0里寄存的地址值,与上面的相同,程序里有这个表:
HandleEINT0#4
HandleEINT1#4
HandleEINT2#4
HandleEINT3#4
HandleEINT4_7 #4
.
.
.
这个表在2410addr.h头文件里也有对应的界说,指向的是相同的一块当地:
.
.
.
#define pISR_EINT0(*(unsigned *)(_ISR_STARTADDRESS+0x20))
#define pISR_EINT1(*(unsigned *)(_ISR_STARTADDRESS+0x24))
#define pISR_EINT2(*(unsigned *)(_ISR_STARTADDRESS+0x28))
.
.
.
问题是HandleEINT0寄存的又是什么值呢?这就需求在初始化EINT0的时分写上这么一句:
pISR_EINT0 = (unsigned )_IsrEINT0Service;
也便是把EINT0的中止处理函数的地址写到HandleEINT0地址处寄存,那么到此PC就能够跳转到_IsrEINT0Service里去了,这儿完结你所需求的中止处理进程。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/ic/276530.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部