您的位置 首页 国产IC

arm发动代码详细分析

arm启动代码详细分析所谓启动代码,就是处理器在启动的时候执行的一段代码,主要任务是初始化处理器模式,设置堆栈,初始化变量等等.由于以上的…

arm发动代码详细剖析

所谓发动代码,便是处理器在发动的时分履行的一段代码,主要任务是初始化处理器形式,设置仓库,初始化变量等等.由于以上的操作均与处理器体系结构和体系装备密切相关,所以一般由汇编来编写.
  详细到S64,发动代码分红两部分,一是与ARM7TDMI内核相关的部分,包含处理器各反常向量的装备,各处理器形式的仓库设置,如有必要,仿制向量到RAM,以便remap之后处理器正确处理反常,初始化数据(包含RW与ZI),最终跳转到Main.二是与处理器外部设备相关的部分,这和厂商的联络比较大.尽管都采用了ARM7TDMI的内核,可是不同的厂家整合了不同的片上外设,需求不同的初始化,其间比较重要的是初始化WDT,初始化各子体系时钟,有必要的话,进行remap.这一部分与一般控制器的初始化相似,因而,本文不作要点描绘.
  在进行剖析之前,请承认如下相关概念:
S64片上FLASH开端于0x100000,共64kB,片上RAM开端于0x200000,共16kB.
S64复位之后,程序会从0开端履行,此刻FLASH被映射到0地址,因而,S64能够获得指令并履行.显着,此刻仍是驻留在0x100000地址.假如运用remap指令,将会把RAM映射到0地址,相同的这时0地址的内容也仅仅RAM的镜像.
S64的FLASH能够确保在最差状况时以30MHz进行单周期拜访,而RAM能够确保在最大速度时的单周期拜访.
OK,以下开端剖析发动代码.

一,处理器反常
S64将反常向量至于0地址开端的几个直接,这些是必需求处理的.由于复位向量坐落0,也需求一条跳转指令.详细代码如下:
RESET
B SYSINIT ; Reset
B UDFHANDLER ; UNDEFINED
B SWIHANDLER ; SWI
B PABTHANDLER ; PREFETCH ABORT
B DABTHANDLER ; DATA ABORT
B . ; RESERVED
B VECTORED_IRQ_HANDLER
B . ; ADD FIQ CODE HERE

UDFHANDLER
B .

SWIHANDLER
B .

PABTHANDLER
B .

DABTHANDLER
B .

请留意,B指令经汇编后会替换为当时PC值加上一个修正值(+/-),所以这条指令是代码方位无关的,也便是不论这条指令是在0地址仍是在 0x100000履行,都能跳转到指定的方位,而LDR PC,=???将向PC直接装载一个标号的值,请留意,标号在编译往后将被替换为一个与RO相对应的值,也便是说,这样的指令不管在哪里履行,都只会跳转到一个指定的方位.下面举一个详细的比如来阐明两者的差异:
假定有如下程序:
RESET
B INIT 或许 LDR PC,=INIT

INIT

其间RESET为开端时的代码,也便是这条代码的偏移为0,设INIT的偏移量为offset.假如将这段程序依照RO=0x1000000编译, 那么B INIT可理解为ADD PC, PC, #offset,而LDR PC,=INIT可被理解为 MOV PC,#(RO+offset) .显着当体系复位时,程序从0开端运转,而0地址有FLASH的副本,履行B INIT将把PC指向坐落0地址处的镜像代码方位,也即INIT;假如履行LDR PC,=INIT将会将PC直接指向坐落FLASH中的原始代码.因而以上两者都能正确运转.下面将RO设置为0x200000,编译后生成代码,仍是得烧写到FLASH中,也便是仍是0x100000,体系复位后从0地址履行,仍是FLASH的副本,此刻履行B INIT,将跳到副本中的INIT方位履行,此处有对应的代码;可是假如履行LDR PC,=INIT,将向PC加载0x200000+offset,这将使得PC跳到RAM中,而此刻由于代码没有仿制,RAM中的指定方位并没有代码,程序无法运转.

二,处理器形式
ARM的处理器可作业于多种形式,不同形式有不同的仓库 ,以下设置各形式及其仓库.
预界说一些参数:
MODUSR EQU 0x10
MODSYS EQU 0x1F
MODSVC EQU 0x13
MODABT EQU 0x17
MODUDF EQU 0x1B
MODIRQ EQU 0x12
MODFIQ EQU 0x11

IRQBIT EQU 0x80
FIQBIT EQU 0x40

RAMEND EQU 0x00204000 ; S64 : 16KB RAM

VECTSIZE EQU 0x100 ;

UsrStkSz EQU 8 ; size of USR stack
SysStkSz EQU 128 ; size of SYS stack
SvcStkSz EQU 8 ; size of SVC stack
UdfStkSz EQU 8 ; size of UDF stack
AbtStkSz EQU 8 ; size of ABT stack
IrqStkSz EQU 128 ; size of IRQ stack
FiqStkSz EQU 16 ; size of FIQ stack

修正这些值即可修正相应形式仓库的尺度.
以下为各形式代码:
SYSINIT
;
MRS R0,CPSR
BIC R0,R0,#0x1F

MOV R2,#RAMEND
ORR R1,R0,#(MODSVC :OR: IRQBIT :OR: FIQBIT)
MSR cpsr_cxsf,R1 ; ENTER SVC MODE
MOV sp,R2
SUB R2,R2,#SvcStkSz

ORR R1,R0,#(MODFIQ :OR: IRQBIT :OR: FIQBIT)
MSR CPSR_cxsf,R1 ; ENTER FIQ MODE
MOV sp,R2
SUB R2,R2,#FiqStkSz

ORR R1,R0,#(MODIRQ :OR: IRQBIT :OR: FIQBIT)
MSR CPSR_cxsf,R1 ; ENTER IRQ MODE
MOV sp,R2
SUB R2,R2,#IrqStkSz

ORR R1,R0,#(MODUDF :OR: IRQBIT :OR: FIQBIT)
MSR CPSR_cxsf,R1 ; ENTER UDF MODE
MOV sp,R2
SUB R2,R2,#UdfStkSz

ORR R1,R0,#(MODABT :OR: IRQBIT :OR: FIQBIT)
MSR CPSR_cxsf,R1 ; ENTER ABT MODE
MOV sp,R2
SUB R2,R2,#AbtStkSz

;ORR R1,R0,#(MODUSR :OR: IRQBIT :OR: FIQBIT)
;MSR CPSR_cxsf,R1 ; ENTER USR MODE
;MOV sp,R2
;SUB R2,R2,#UsrStkSz

ORR R1,R0,#(MODSYS :OR: IRQBIT :OR: FIQBIT)
MSR CPSR_cxsf,R1 ; ENTER SYS MODE
MOV sp,R2 ;

三,初始化变量
编译完结之后,衔接器会生成三个根本的段,分别是RO,RW,ZI,并会在image中次序摆放.显着,RW,ZI在运转开端时并不坐落指定的RW方位,因而有必要初始化
LDR R0,=|Image$$RO$$Limit|
LDR R1,=|Image$$RW$$Base|
LDR R2,=|Image$$ZI$$Base|
1
CMP R1,R2
LDRLO R3,[R0],#4
STRLO R3,[R1],#4
BLO �

MOV R3,#0
LDR R1,=|Image$$ZI$$Limit|
2
CMP R2,R1
STRLO R3,[R2],#4
BLO �

四,仿制反常向量
由于代码于RAM运转时,有显着的速度优势,并且变量能够动态装备,因而能够经过remap将RAM映射到0,使得出现反常时ARM从RAM中获得向量.
IMPORT |Image$$RO$$Base|
IMPORT |Image$$RO$$Limit|
IMPORT |Image$$RW$$Base|
IMPORT |Image$$RW$$Limit|
IMPORT |Image$$ZI$$Base|
IMPORT |Image$$ZI$$Limit|

COPY_VECT_TO_RAM
LDR R0,=|Image$$RO$$Base|
LDR R1,=SYSINIT
LDR R2,=0x200000 ; RAM START
0
CMP R0,R1
LDRLO R3,[R0],#4
STRLO R3,[R2],#4
BLO �

这段程序将SYSINIT之前的代码,也便是反常处理函数,悉数仿制到RAM中, 这就意味着不能将RW设置为0x200000,这样会使得向量被冲掉.

四,在RAM中运转
假如有必要,且代码满足小,能够将代码置于RAM中运转,由于RAM中自身没有代码,就需求将代码仿制到RAM中:
COPY_BEGIN
LDR R0,=0x200000
LDR R1,=RESET ; =|Image$$RO$$Base|
CMP R1,R0 ;
BLO COPY_END ;

ADR R0,RESET
ADR R2,COPY_END
SUB R0,R2,R0
ADD R1,R1,R0

LDR R3,=|Image$$RO$$Limit|
3
CMP R1,R3
LDRLO R4,[R2],#4
STRLO R4,[R1],#4
BLO �

LDR PC,=COPY_END

COPY_END
程序首要获得RESET的衔接地址,判别程序是否时是在RAM中运转,办法是与RAM开端地址比较,假如小于,那么就越过代码仿制.
在仿制代码的时分需求留意,在这段程序完毕之前的代码没有必要仿制,由于这些代码都现已履行过了,所以,先获得COPY_END,作为仿制开端地址,然后核算其相对RESET的偏移,然后以RO的值加上这个偏移,便是仿制目的地的开端地址,然后开端仿制.

五,开端主程序
以上过程完结,就能够跳转到main运转
IMPORT Main

LDR PC,=Main
B .
六,器材初始化
主程序首要要进行器材的初始化,对S64而言,应该先初始化WDT,由于默许状况下,WDT是翻开的,然后是各设备的时钟分配,最终应该remap

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

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

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

微信扫一扫关注我们

返回顶部