环境:ubuntu+(arm-linux-gcc)+minicom+dnw+mini2440

    每换一个架构的处理器,总是会先对LED做些实验.对于启动代码(虽说2440有现成的启动代码,但是是基于ADS下的,在GNU下面用必须得修改伪指 令,而且对于裸奔爱好者来说,只要一小段代码不是自己写的,用起来就浑身不自在),虽然书里有讲它的作用,但是对此我一直存在着几点疑问,,,,

    疑惑1)启动代码可有可无?

    对于使用ADS来写的朋友,启动代码可有可无这点你们可以无需知道,因为编译器已经帮你做好了,而对于linux下的朋友,启动代码这块必须得了解,理由如其名字,,,,对于这个问题,我做了以下实验:

    先写一个简单的led.c的文件,内容如下:

 
  
  1. #define GPBCON (*(volatile unsigned *)0x56000010) 
  2. #define GPBDAT (*(volatile unsigned *)0x56000014) 
  3.  
  4. void main() 
  5.         GPBCON = 0x55<<10;      //01010101<<10 
  6.         GPBDAT = 0x0; 

    start.s启动脚本:

 
  
  1. .text 
  2. .global start 
  3. start: 
  4.         ldr     sp,=1024*4 
  5.         bl      main 
  6. loop: 
  7.         b       loop 

    然后用我之前写的一篇叫ARM9裸奔篇之Makefile 里 的makefile编译链接一下,烧到NANDflash里,灯都亮了,然后把start.s改名为start(这样makefile就不会编译它了)然 后在make一下,烧进板子,灯也是全亮了,对于书中写到裸机程序必须要有启动代码这一说我表示十分疑惑,,,,,为什么可有可无?下面会说到,,,

   

    疑惑2)当我似乎弄懂了上面的疑惑后,我开始led的第二步实验,流水灯,,,(不用启动代码)

    led.c的代码:   

 

 
  
  1. #define GPBCON (*(volatile unsigned *)0x56000010) 
  2. #define GPBDAT (*(volatile unsigned *)0x56000014) 
  3.  
  4. void delay() 
  5.         unsigned int i = 50000;       
            while(1);
  6.  
  7. void main() 
  8.         unsigned char i; 
  9.         GPBCON = 0x55<<10;      //01010101<<10 
  10. //      GPBDAT = 0x0; 
  11.         while(1) 
  12.         { 
  13.                 for(i=0;i<4;i++) 
  14.                 { 
  15.                         GPBDAT = ~(1<<(5+i)); 
  16.                         delay(); 
  17.                 } 
  18.         } 
  19. }                       

make一下后烧录进板子,发现居然不亮了,然后检查了半天代码,没发现有问题,此刻,我就想起了不久前被我抛弃了的启动代码,加进去后,仍然不亮,,,WHY?然后我又想起了看反汇编的程序(make后生成的.dis文件)内容如下:

 

 
  
  1. example.bin_elf:     file format elf32-littlearm 
  2.  
  3.  
  4. Disassembly of section .text: 
  5.  
  6. 00000000 <delay>: 
  7.    0:   e52db004    push    {fp}        ; (str fp, [sp, #-4]!) 
  8.    4:   e28db000    add fp, sp, #0 
  9.    8:   e24dd00c    sub sp, sp, #12 
  10.    c:   e59f3034    ldr r3, [pc, #52]   ; 48 <delay+0x48> 
  11.   10:   e50b3008    str r3, [fp, #-8] 
  12.   14:   e51b3008    ldr r3, [fp, #-8] 
  13.   18:   e3530000    cmp r3, #0 
  14.   1c:   03a03000    moveq   r3, #0 
  15.   20:   13a03001    movne   r3, #1 
  16.   24:   e20330ff    and r3, r3, #255    ; 0xff 
  17.   28:   e51b2008    ldr r2, [fp, #-8] 
  18.   2c:   e2422001    sub r2, r2, #1 
  19.   30:   e50b2008    str r2, [fp, #-8] 
  20.   34:   e3530000    cmp r3, #0 
  21.   38:   1afffff5    bne 14 <delay+0x14> 
  22.   3c:   e28bd000    add sp, fp, #0 
  23.   40:   e8bd0800    pop {fp} 
  24.   44:   e12fff1e    bx  lr 
  25.   48:   0000c350    andeq   ip, r0, r0, asr r3 
  26.  
  27. 0000004c <main>: 
  28.   4c:   e92d4800    push    {fp, lr} 
  29.   50:   e28db004    add fp, sp, #4 
  30.   54:   e24dd008    sub sp, sp, #8 
  31.   58:   e59f304c    ldr r3, [pc, #76]   ; ac <main+0x60> 
  32.   5c:   e3a02b55    mov r2, #87040  ; 0x15400 
  33.   60:   e5832000    str r2, [r3] 
  34.   64:   e3a03000    mov r3, #0 
  35.   68:   e54b3005    strb    r3, [fp, #-5] 
  36.   6c:   ea00000a    b   9c <main+0x50> 
  37.   70:   e59f3038    ldr r3, [pc, #56]   ; b0 <main+0x64> 
  38.   74:   e55b2005    ldrb    r2, [fp, #-5] 
  39.   78:   e2822005    add r2, r2, #5 
  40.   7c:   e3a01001    mov r1, #1 
  41.   80:   e1a02211    lsl r2, r1, r2 
  42.   84:   e1e02002    mvn r2, r2 
  43.   88:   e5832000    str r2, [r3] 
  44.   8c:   ebffffdb    bl  0 <delay> 
  45.   90:   e55b3005    ldrb    r3, [fp, #-5] 
  46.   94:   e2833001    add r3, r3, #1 
  47.   98:   e54b3005    strb    r3, [fp, #-5] 
  48.   9c:   e55b3005    ldrb    r3, [fp, #-5] 
  49.   a0:   e3530003    cmp r3, #3 
  50.   a4:   9afffff1    bls 70 <main+0x24> 
  51.   a8:   eaffffed    b   64 <main+0x18> 
  52.   ac:   56000010    undefined instruction 0x56000010 
  53.   b0:   56000014    undefined instruction 0x56000014 
  54.  
  55. 000000b4 <start>: 
  56.   b4:   e3a0da01    mov sp, #4096   ; 0x1000 
  57.   b8:   ebffffe3    bl  4c <main> 
  58.  
  59. 000000bc <loop>: 
  60.   bc:   eafffffe    b   bc <loop> 
  61.  
  62. Disassembly of section .ARM.attributes: 
  63.  
  64. 00000000 <.ARM.attributes>: 
  65.    0:   00002741    andeq   r2, r0, r1, asr #14 
  66.    4:   61656100    cmnvs   r5, r0, lsl #2 
  67.    8:   01006962    tsteq   r0, r2, ror #18 
  68.    c:   0000001d    andeq   r0, r0, sp, lsl r0 
  69.   10:   00543405    subseq  r3, r4, r5, lsl #8 
  70.   14:   01080206    tsteq   r8, r6, lsl #4 
  71.   18:   04120109    ldreq   r0, [r2], #-265 ; 0x109 
  72.   1c:   01150114    tsteq   r5, r4, lsl r1 
  73.   20:   01180317    tsteq   r8, r7, lsl r3 
  74.   24:   061e021a    undefined instruction 0x061e021a 
  75.  
  76. Disassembly of section .comment: 
  77.  
  78. 00000000 <.comment>: 
  79.    0:   3a434347    bcc 10d0d24 <__bss_end__+0x10c8c64> 
  80.    4:   74632820    strbtvc r2, [r3], #-2080    ; 0x820 
  81.    8:   312d676e    teqcc   sp, lr, ror #14 
  82.    c:   312e362e    teqcc   lr, lr, lsr #12 
  83.   10:   2e342029    cdpcs   0, 3, cr2, cr4, cr9, {1} 
  84.   14:   00332e34    eorseq  r2, r3, r4, lsr lr 

看完后恍然一悟!!!!第一个执行的居然是delay()函数,而启动代码居然是在000000b4位置!!!就等于执行完delay()函数后跳到lr所指向的位置了,,,知道了这事情后,让我明白了,为什么裸机程序需要启动代码(用汇编写快些,当然也能用C写,反正也会编译成汇编,就是产生的汇编代码多了),然后我修改了makefile里的编译顺序后,,,led华丽地动起来啦~~~~~~~~~~