2、arm启动代码分析

来源:互联网 发布:cad制图软件 编辑:程序博客网 时间:2024/04/30 14:46
 

理解启动代码(ADS)
  所谓启动代码,就是处理器在启动的时候执行的一段代码,主要任务是初始化处理器模式,设置堆栈,初始化变量等等.由于以上的操作均与处理器体系结构和系统配置密切相关,所以一般由汇编来编写.
  具体到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
               SYSINIT                        ; Reset
               UDFHANDLER            ; UNDEFINED
               SWIHANDLER             ; SWI
               PABTHANDLER          ; PREFETCH ABORT
               DABTHANDLER          ; DATA ABORT
                                                    ; RESERVED
               VECTORED_IRQ_HANDLER
                                                    ; ADD FIQ CODE HERE

UDFHANDLER
               .

SWIHANDLER
               .

PABTHANDLER
               .

DABTHANDLER
               .

请注意,B指令经汇编后会替换为当前PC值加上一个修正值(+/-),所以这条指令是代码位置无关的,也就是不管这条指令是在0地址还是在0x100000执行,都能跳转到指定的位置,而LDR PC,=???将向PC直接装载一个标号的值,请注意,标号在编译过后将被替换为一个与RO相对应的值,也就是说,这样的指令无论在哪里执行,都只会跳转到一个指定的位置.下面举一个具体的例子来说明两者的区别:
      假定有如下程序:
       RESET
                        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             ; size of   USR   stack
SysStkSz     EQU    128         ; size of   SYS   stack
SvcStkSz     EQU             ; size of   SVC   stack
UdfStkSz     EQU             ; size of   UDF   stack
AbtStkSz     EQU             ; 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|
     
         CMP     R1,R2
         LDRLO   R3,[R0],#4
         STRLO   R3,[R1],#4
         BLO     %B1 

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

四,复制异常向量
         由于代码于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 

                         CMP     R0,R1
   LDRLO   R3,[R0],#4
   STRLO   R3,[R2],#4
   BLO     %B0

这段程序将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|

                         CMP     R1,R3
   LDRLO   R4,[R2],#4
   STRLO   R4,[R1],#4
   BLO     %B3
 
   LDR     PC,=COPY_END
 
COPY_END
程序首先取得RESET的连接地址,判断程序是否时是在RAM中运行,方法是与RAM起始地址比较,如果小于,那么就跳过代码复制.
在复制代码的时候需要注意,在这段程序结束之前的代码没有必要复制,因为这些代码都已经执行过了,所以,先取得COPY_END,作为复制起始地址,然后计算其相对RESET的偏移,然后以RO的值加上这个偏移,就是复制目的地的起始地址,然后开始复制.

五,开始主程序
         以上步骤完成,就可以跳转到main运行
         IMPORT Main

         LDR     PC,=Main
              .

 
六,器件初始化
         主程序首先要进行器件的初始化,对S64而言,应该先初始化WDT,因为默认情况下,WDT是打开的,然后是各设备的时钟分配,最后应该remap

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我把exe删除了怎么办 大学图书馆借书超过期限了怎么办 win10更新完鼠标没有了怎么办 打开软件提示运行出错怎么办 电脑中了u盘病毒怎么办 电脑中病毒自动重启怎么办 病毒软件不断发信息买服务怎么办 qq被腾讯屏蔽了怎么办 电脑被u盘中毒怎么办 电脑一分钟重启怎么办 创维电视音量小怎么办 捷豹pin码忘记了怎么办 华为手机版本更新下载不了怎么办? 微信钱包没有钱怎么办 微信钱包里没有钱怎么办 微信没有收到退款怎么办 微信转账退款没有收到怎么办 礼物跟人家送重复怎么办 你已被steam封禁怎么办 武装突袭3被锁定怎么办 绝地求生右下角小地图变大怎么办 ctrl z 误删了怎么办 武装突袭3渴了怎么办 武装突袭3枪卡壳怎么办 玩武装突袭3CPU不好怎么办? 户户通001信号中断怎么办 电脑运行速度特别慢怎么办 win8.1电脑太卡怎么办 电线厂非法战地没拆够怎么办 久笔记本电脑玩彩虹六号卡怎么办 彩虹六号一直建立小队进不去怎么办 小佩喂食器离线怎么办 手机打游戏掉帧怎么办 电脑打游戏掉帧怎么办 武装突袭3太卡怎么办 英语b级考不过怎么办 绝地求生被燃烧瓶烧了怎么办 搜狗输入法打字出现问好怎么办 全民k歌解码失败怎么办 视频声音小怎么办调大 乐视2视频声音小怎么办