用ADS写一个ARM启动代码遇到的问题

来源:互联网 发布:爱思助手mac官方下载 编辑:程序博客网 时间:2024/05/22 06:10

今天一天我一直被一个启动代码所捆饶着:在调用一个堆栈初始化函数以后,堆栈竟然出现错误配置,指向了那些不可用的地址,导致取数据异常。一开始我以为是不是我的分散加载文件写错误了,找遍了所有的资料,都可以确认我的分散加载文件是没有问题。

这个问题是这样的:

在安装完异常向量代码以后,我调用一个Stack_init函数来实现对堆栈进行初始化。如下

start

         LDR  PC,RESET_ADDR

       ....

RESET_ADDR DCD RESET_Handler

     ...

RESET_Handler

        BL Stack_init   ;初始化堆栈,为了更好模块化,Stack_init 在另外一个文件Stack.s中实现

     ....

 

;File    : Stack.S
;Author  : embs
;Date    : 2008/05/08
;Version : 1.0
;------------------------------------------------------------
;This File is the bootloader code for arm7,when power up.use to
; Initalization the stack of all kinds of mode
;   
; you must change the size of mode that maybe use for your project
; the size of stack must align to 32bit. if not,it will data abort
;-------------------------------------------------------------------

UND_STACK_SIZE   EQU  0x00000004
ABT_STACK_SIZE   EQU  0x00000004
FIQ_STACK_SIZE   EQU  0x00000004
IRQ_STACK_SIZE   EQU  0x00000100
SVC_STACK_SIZE   EQU  0x00000020 

MODE_USR         EQU  0x10            ;/* User Mode */
MODE_FIQ         EQU  0x11            ;/* FIQ Mode */
MODE_IRQ         EQU  0x12            ;/* IRQ Mode */
MODE_SVC         EQU  0x13            ;/* Supervisor Mode */
MODE_ABT         EQU  0x17            ;/* Abort Mode */
MODE_UND         EQU  0x1B            ;/* Undefined Mode */
MODE_SYS         EQU  0x1F            ;/* System Mode */
    
FIQ_MASK         EQU  0x40            ;mask of IFQ ,set disable
IRQ_MASK         EQU  0x80            ;mask of IRQ ,set disable
    
     EXPORT  STACK_init
     CODE32
     AREA Start,CODE,READONLY
STACK_init
     MOV R0,LR
     LDR R1,=Stack_TOP
    
     MSR CPSR_c,#MODE_UND|FIQ_MASK|IRQ_MASK
     MOV SP,R1
     SUB R1,R1,#UND_STACK_SIZE
    
     MSR CPSR_c,#MODE_ABT|FIQ_MASK|IRQ_MASK
     MOV SP,R1
     SUB R1,R1,#ABT_STACK_SIZE
    
     MSR CPSR_c,#MODE_FIQ|FIQ_MASK|IRQ_MASK
     MOV SP,R1
     SUB R1,R1,#FIQ_STACK_SIZE
    
     MSR CPSR_c,#MODE_IRQ|FIQ_MASK|IRQ_MASK
     MOV SP,R1
     SUB R1,R1,#IRQ_STACK_SIZE
    
     MSR CPSR_c,#MODE_SVC|FIQ_MASK|IRQ_MASK
     MOV SP,R1
     SUB R1,R1,#SVC_STACK_SIZE
    
     MSR CPSR_c,#MODE_SYS|FIQ_MASK|IRQ_MASK  ;default start mode
     MOV SP,R1
    
     IF :LNOT:(:DEF:START_MODE)
     MSR CPSR_c,#START_MODE|FIQ_MASK|IRQ_MASK
     ENDIF
     MOV PC,R0
    
     AREA StackS,DATA,NOINIT
Stack_TOP


     END

该代码反汇编以后的代码如下:

 STACK_init
    $a
    Start
        0x00000000:    e1a0000e    ....    MOV      r0,r14
        0x00000004:    e59f1048    H...    LDR      r1,0x54    <<==问题就出在这里,按理它应该加载0x00000050地址的值才对,可现在加载的0x54地址处的值。这个可以很容易与源代码比较知道                                                                                     
        0x00000008:    e321f0db    ..!.    MSR      CPSR_c,#0xdb
        0x0000000c:    e1a0d001    ....    MOV      r13,r1
        0x00000010:    e2411004    ..A.    SUB      r1,r1,#4
        0x00000014:    e321f0d7    ..!.    MSR      CPSR_c,#0xd7
        0x00000018:    e1a0d001    ....    MOV      r13,r1
        0x0000001c:    e2411004    ..A.    SUB      r1,r1,#4
        0x00000020:    e321f0d1    ..!.    MSR      CPSR_c,#0xd1
        0x00000024:    e1a0d001    ....    MOV      r13,r1
        0x00000028:    e2411004    ..A.    SUB      r1,r1,#4
        0x0000002c:    e321f0d2    ..!.    MSR      CPSR_c,#0xd2
        0x00000030:    e1a0d001    ....    MOV      r13,r1
        0x00000034:    e2411f40    @.A.    SUB      r1,r1,#0x100
        0x00000038:    e321f0d3    ..!.    MSR      CPSR_c,#0xd3
        0x0000003c:    e1a0d001    ....    MOV      r13,r1
        0x00000040:    e2411020     .A.    SUB      r1,r1,#0x20
        0x00000044:    e321f0df    ..!.    MSR      CPSR_c,#0xdf
        0x00000048:    e1a0d001    ....    MOV      r13,r1
        0x0000004c:    e1a0f000    ....    MOV      pc,r0
    $d
        0x00000050:    00000000    ....    DCD    0     <<应该加载的地方                                                                            

找了一天,花费了很多时间,终于找到了罪魁祸首:

     IF :LNOT:(:DEF:START_MODE)
     MSR CPSR_c,#START_MODE|FIQ_MASK|IRQ_MASK
     ENDIF

非常粗心把IF逻辑判断写错了
应该修改为:
IF :DEF:START_MODE
     MSR CPSR_c,#START_MODE|FIQ_MASK|IRQ_MASK
     ENDIF
现在这是修改后的反汇编代码,修改好以后,也就再也不出现取数据异常了。

STACK_init
    $a
    Start
        0x00000000:    e1a0000e    ....    MOV      r0,r14
        0x00000004:    e59f1044    D...    LDR      r1,0x50   << 0x50
        0x00000008:    e321f0db    ..!.    MSR      CPSR_c,#0xdb
        0x0000000c:    e1a0d001    ....    MOV      r13,r1
        0x00000010:    e2411004    ..A.    SUB      r1,r1,#4
        0x00000014:    e321f0d7    ..!.    MSR      CPSR_c,#0xd7
        0x00000018:    e1a0d001    ....    MOV      r13,r1
        0x0000001c:    e2411004    ..A.    SUB      r1,r1,#4
        0x00000020:    e321f0d1    ..!.    MSR      CPSR_c,#0xd1
        0x00000024:    e1a0d001    ....    MOV      r13,r1
        0x00000028:    e2411004    ..A.    SUB      r1,r1,#4
        0x0000002c:    e321f0d2    ..!.    MSR      CPSR_c,#0xd2
        0x00000030:    e1a0d001    ....    MOV      r13,r1
        0x00000034:    e2411f40    @.A.    SUB      r1,r1,#0x100
        0x00000038:    e321f0d3    ..!.    MSR      CPSR_c,#0xd3
        0x0000003c:    e1a0d001    ....    MOV      r13,r1
        0x00000040:    e2411020     .A.    SUB      r1,r1,#0x20
        0x00000044:    e321f0df    ..!.    MSR      CPSR_c,#0xdf
        0x00000048:    e1a0d001    ....    MOV      r13,r1
        0x0000004c:    e1a0f000    ....    MOV      pc,r0
    $d
        0x00000050:    00000000    ....    DCD    0   <<Stack_TOP就存储在这里

 

所以工作必须要细心,微小的东西往往可以给人致命的打击。以后要加强修炼才行。

原创粉丝点击