SmartARM2200启动文件分析

 

  先看图如下:这是arm的启动过程。

 

 

       SmartARM2200启动文件分析_第1张图片   

    先对启动前的硬件描述一下,这样在分析startup.s的时候就轻松多了。我使用的是smartarm2200开发板,其中CPU芯片使用的LPC2210,没有内部flash(周公太抠门了)。因此说到设置也就是两点:

一,BOOT[1:0]的设置。决定是从内部Memory还是外部Memory启动。面对抠门的周公,咱只能从外部存储器启动了。无奈啊!这也就引发了第二个扩展存储器的设置。

二,bank0bank1的设置。要是用于调试的话就把ram设成bank0,可以在ram启动,这样可以很容易进行存储器重映射。要是烧flash的话就把flash设成bank0

因此,我们在流程图中的路线是始终在最右边走。哦,原来是从0x80000000启动啊!

接下来就开始进入代码了!首先看下图是整体几个文件的关系图。

SmartARM2200启动文件分析_第2张图片

    刚才看到运行首地址是0x80000000,那么怎么安排我们的flash或者ram?记得在单片机中经常实用org 0x800方式就能搞定,我们在ads中也可以设置RO、RW、ZI和入口点地址一额可以办到。但这只能应用一些很简单的情况,现在面临的要复杂一点,因而“分散加载方式”闪亮登场。这里不妨总结一下ARM链接方式:

    (1)simple方式:(三点设置)分别是,Output下:RO(代码基址) RW(数据基址包括ZI)。Layout下:Object/Symble填入startup.o  Section填入start(根据实际情况定)Option下:Image Entry Pointer填入地址。

    (2)scattered方式:(也要三步)分别是,编写.scf文件;在output下填入该文件;Option下填入入口地址。

下面分析.scf文件,以mem_b.scf为例。

/**************  mem_b.scf文件  *************/

ROM_LOAD 0x80000000                          //名      地址      范围限制(本例子缺省)
{
    ROM_EXEC 0x80000000                      //片外存储器   地址  范围大小(本例缺省)
    {
        Startup.o (vectors, +First)               //startup文件中vector段放于开头
        * (+RO)                                         //其他模块的代码与只读数据放于此
    }
    IRAM 0x40000000                              //片内RAM  地址  范围大小(缺省)
    {
        Startup.o (MyStacks)                      //startup文件中MyStacks段放于开头
    }

    STACKS_BOTTOM +0 UNINIT               //栈底 地址 不用初始化 范围大小限制(缺省)
    {
        Startup.o (StackBottom)                //startup文件中MyStackBottom段放于开头
    }

    STACKS 0x40004000 UNINIT
    {
        Startup.o (Stacks)
    }

    ERAM 0x80040000
    {
        * (+RW,+ZI)                              //所有的RW与ZI数据置于此,也就是未初始化和初始化的全局变量
    }

    HEAP +0 UNINIT
    {
        Startup.o (Heap)
    }

    HEAP_BOTTOM 0x80080000 UNINIT
    {
        Startup.o (HeapTop)
    }

}

 可以用文件的方式观察内存的实际格局,在ARM Linker的Listings选项卡下,选中Image Map复选框。这样编译的时候就会显示内存格局了。

Memory Map of the image

  Image Entry point : 0x80000000

  Load Region ROM_LOAD (Base: 0x80000000, Size: 0x000005b4, Max: 0xffffffff, ABSOLUTE)

    Execution Region ROM_EXEC (Base: 0x80000000, Size: 0x000005b4, Max: 0xffffffff, ABSOLUTE)

    Base Addr    Size         Type   Attr  Idx  E Section Name        Object

    0x80000000   0x00000110   Code   RO     1   * vectors             Startup.o
    0x80000110   0x000000a8   Code   RO    53   * !!!                 __main.o(c_a__un.l)
    0x800001b8   0x000000dc   Code   RO    10     .text               target.o
    0x80000294   0x00000078   Code   RO    42     .text               main.o
    0x8000030c   0x00000008   Code   RO    55     .text               _no_redirect.o(c_a__un.l)
    0x80000314   0x000000a4   Code   RO    57     .text               stkheap2.o(c_a__un.l)
    0x800003b8   0x00000004   Code   RO    59     .text               use_no_semi.o(c_a__un.l)
    0x800003bc   0x00000028   Code   RO    61     .text               kernel.o(c_a__un.l)
    0x800003e4   0x0000000c   Code   RO    63     .text               libspace.o(c_a__un.l)
    0x800003f0   0x00000018   Code   RO    66     .text               exit.o(c_a__un.l)
    0x80000408   0x000000fc   Code   RO    68     .text               lib_init.o(c_a__un.l)
    0x80000504   0x00000010   Code   RO    72     .text               rt_fp_status_addr.o(c_a__un.l)
    0x80000514   0x00000014   Code   RO    70     x$fpl$fpinit        fpinit.o(f_a_p.l)
    0x80000528   0x00000020   Data   RO    43     .constdata          main.o
    0x80000548   0x00000054   Data   RO    74     Region$$Table       anon$$obj.o
    0x8000059c   0x00000018   Data   RO    75     ZISection$$Table    anon$$obj.o
    Execution Region IRAM (Base: 0x40000000, Size: 0x00000400, Max: 0xffffffff, ABSOLUTE)

    Base Addr    Size         Type   Attr  Idx  E Section Name        Object

    0x40000000   0x00000400   Zero   RW     2     MyStacks            Startup.o
    Execution Region STACKS_BOTTOM (Base: 0x40000400, Size: 0x00000004, Max: 0xffffffff, ABSOLUTE, UNINIT)

    Base Addr    Size         Type   Attr  Idx  E Section Name        Object

    0x40000400   0x00000004   Zero   RW     4     StackBottom         Startup.o
    Execution Region STACKS (Base: 0x40004000, Size: 0x00000000, Max: 0xffffffff, ABSOLUTE, UNINIT)

    Base Addr    Size         Type   Attr  Idx  E Section Name        Object

    0x40004000   0x00000000   Zero   RW     6     Stacks              Startup.o
    Execution Region ERAM (Base: 0x80040000, Size: 0x00000060, Max: 0xffffffff, ABSOLUTE)

    Base Addr    Size         Type   Attr  Idx  E Section Name        Object

    0x80040000   0x00000060   Zero   RW    64     .bss                libspace.o(c_a__un.l)
    Execution Region HEAP (Base: 0x80040060, Size: 0x00000004, Max: 0xffffffff, ABSOLUTE, UNINIT)

    Base Addr    Size         Type   Attr  Idx  E Section Name        Object

    0x80040060   0x00000004   Zero   RW     3     Heap                Startup.o
    Execution Region HEAP_BOTTOM (Base: 0x80080000, Size: 0x00000000, Max: 0xffffffff, ABSOLUTE, UNINIT)

    Base Addr    Size         Type   Attr  Idx  E Section Name        Object

    0x80080000   0x00000000   Zero   RW     5     HeapTop             Startup.o

  Load Region LR$$Debug (Base: 0x00000000, Size: 0x00000000, Max: 0xffffffff, ABSOLUTE)

    Execution Region ER$$Debug (Base: 0x00000000, Size: 0x00000000, Max: 0xffffffff, ABSOLUTE)

    Base Addr    Size         Type   Attr  Idx  E Section Name        Object

    0x00000000   0x00000010   Dbug   RW     9     .debug_abbrev       Startup.o
    0x00000010   0x000003ec   Dbug   RW    19     .debug_abbrev       target.o
    0x00000000   0x0000014c   Dbug   RW    18     .debug_frame        target.o
    0x0000014c   0x00000058   Dbug   RW    52     .debug_frame        main.o
    0x000001a4   0x0000003c   Dbug   RW    54     .debug_frame        __main.o(c_a__un.l)
    0x000001e0   0x0000004c   Dbug   RW    56     .debug_frame        _no_redirect.o(c_a__un.l)
    0x0000022c   0x00000094   Dbug   RW    58     .debug_frame        stkheap2.o(c_a__un.l)
    0x000002c0   0x00000044   Dbug   RW    60     .debug_frame        use_no_semi.o(c_a__un.l)
    0x00000304   0x00000058   Dbug   RW    62     .debug_frame        kernel.o(c_a__un.l)
    0x0000035c   0x00000044   Dbug   RW    65     .debug_frame        libspace.o(c_a__un.l)
    0x000003a0   0x0000004c   Dbug   RW    67     .debug_frame        exit.o(c_a__un.l)
    0x000003ec   0x0000007c   Dbug   RW    69     .debug_frame        lib_init.o(c_a__un.l)
    0x00000468   0x0000004c   Dbug   RW    71     .debug_frame        fpinit.o(f_a_p.l)
    0x000004b4   0x0000004c   Dbug   RW    73     .debug_frame        rt_fp_status_addr.o(c_a__un.l)
    0x00000000   0x00000074   Dbug   RW     7     .debug_info         Startup.o
    0x00000074   0x0000007c   Dbug   RW    12     .debug_info         target.o
    0x000000f0   0x00000108   Dbug   RW    35     .debug_info         target.o
    0x000001f8   0x000000e4   Dbug   RW    31     .debug_info         target.o
    0x000002dc   0x00000540   Dbug   RW    15     .debug_info         target.o
    0x0000081c   0x00000110   Dbug   RW    27     .debug_info         target.o
    0x0000092c   0x00000090   Dbug   RW    45     .debug_info         main.o
    0x000009bc   0x00000134   Dbug   RW    49     .debug_info         main.o
    0x00000000   0x0000009c   Dbug   RW     8     .debug_line         Startup.o
    0x0000009c   0x000000b8   Dbug   RW    11     .debug_line         target.o
    0x00000154   0x000000f8   Dbug   RW    14     .debug_line         target.o
    0x0000024c   0x00000064   Dbug   RW    26     .debug_line         target.o
    0x000002b0   0x00000050   Dbug   RW    30     .debug_line         target.o
    0x00000300   0x00000050   Dbug   RW    34     .debug_line         target.o
    0x00000350   0x00000078   Dbug   RW    44     .debug_line         main.o
    0x000003c8   0x000000a4   Dbug   RW    48     .debug_line         main.o
    0x00000000   0x000002c0   Dbug   RW    17     .debug_loc          target.o
    0x000002c0   0x00000064   Dbug   RW    51     .debug_loc          main.o
    0x00000000   0x00000190   Dbug   RW    13     .debug_macinfo      target.o
    0x00000190   0x00000078   Dbug   RW    29     .debug_macinfo      target.o
    0x00000208   0x0000004c   Dbug   RW    33     .debug_macinfo      target.o
    0x00000254   0x000001f0   Dbug   RW    37     .debug_macinfo      target.o
    0x00000444   0x00000190   Dbug   RW    47     .debug_macinfo      main.o
    0x00000000   0x00000128   Dbug   RW    16     .debug_pubnames     target.o
    0x00000128   0x00000064   Dbug   RW    28     .debug_pubnames     target.o
    0x0000018c   0x00000058   Dbug   RW    32     .debug_pubnames     target.o
    0x000001e4   0x00000084   Dbug   RW    36     .debug_pubnames     target.o
    0x00000268   0x00000020   Dbug   RW    46     .debug_pubnames     main.o
    0x00000288   0x00000028   Dbug   RW    50     .debug_pubnames     main.o
================================================================================

Image component sizes
      Code    RO Data    RW Data    ZI Data      Debug  

       612        140          0       1032       8356   Object Totals
       708          0          0         96        860   Library Totals

================================================================================
      Code    RO Data    RW Data    ZI Data      Debug  

      1320        140          0       1128       9216   Grand Totals

================================================================================

    Total RO  Size(Code + RO Data)                 1460 (   1.43kB)
    Total RW  Size(RW Data + ZI Data)              1128 (   1.10kB)
    Total ROM Size(Code + RO Data + RW Data)       1460 (   1.43kB)

================================================================================

 

 

 ****************************************************************************

 

 一般的可执行程序都包括代码段、数据段。也可以简单的看作由两部分组成:RO段和RW段。RO段一般包括代码段和一些常量,在运行的时候是只读的。而RW段包括一些全局变量和静态变量,在运行的时候是可以改变的(读写)。如果有部分全局变量被初始化为零,则RW段里还包括了ZI段。
RO: Read Only  代码段
RW: Read Write 已初始化的全局变量
ZI: Zero Init   未初始化的全局变量

     因为RO段是只读的,在运行的时候不可以改变,所以,在运行的时候,RO段可以驻留在Flash里(当然也可以在SDRAM或者SRAM里了)。而RW段是可以读写的,所以,在运行的时候必须被装载到SDRAM或者SRAM里。
     在用ADS编译的时候,是需要设置RO BASE 和RW BASE的,用过ADS的应该都清楚这点。通过RO BASE 和RW BASE的设置,告诉链接器(linker)该程序的起始运行地址(RO BASE)和 RW段的地址 (RW BASE)。如果一个程序只有RO段,没有RW段,那么这个程序可以完全在Flash里运行,不需要用到SDRAM 或者 SRAM。如果包括RW段和RO段,那么该程序的RW段必须在被访问以前被拷贝到SDRAM 或者SRAM里去,以保证程序可以正确运行。下面这个图说明了一个程序执行前(load view)和执行时(execute view)的状态。从图中可以看到,整个程序在执行前始放在ROM里的,在执行的时候,RW段被拷贝到了RAM里的合适位置去。

    程序一开始总是存储在ROM/Flash里面的,其RO部分既可以在ROM/Flash里面执行,也可以转移到速度更快的RAM中去;而RW和ZI这两部分是必须转移到可写的RAM里去。所谓应用程序执行环境的初始化,就是完成必要的从ROM到RAM的数据传输和内容清零。

  不同的工具链会提供一些不同的机制和方法帮助用户完成这一步操作,主要是跟链接器(Linker)相关。下面是在ARM开发工具环境ADS下,一种常用存储器模型的直接实现:

  SmartARM2200启动文件分析_第3张图片

    LDR r0, = |Image$$RO$$Limit| ;得到RO段末的下一字节的地址 ,ROM中的RW的开始地址
  LDR r1, = |Image$$RW$$Base| ;得到RAM中的RW段的初始地址
  LDR r3, = |Image$$ZI$$Base| ;全局变量的初始地址  
  CMP r0, r1 ; 
  BEQ LOOP1 
LOOP0 
  CMP r1, r3 ; 是否到RAM中的RW段的末地址,如果没到,则一直将ROM(FLASH变    量与数据段拷贝到RAM中
  LDRCC r2, [r0], #4 ;[R0]=[R1] 
  STRCC r2, [r1], #4 ;  
  BCC LOOP0 
LOOP1 
  LDR r1, = |Image$$ZI$$Limit| ; LOOP1与LOOP2执行将ZI初始化为0
  MOV r2, #0 
LOOP2 
  CMP r3, r1 
  STRCC r2, [r3], #4 ; 
  BCC LOOP2

    在ADS里,有一些预先定义了的变量可以用(linker defined symbol)。在下面的实现里,用到了几个预定义的变量:
Image$$RO$$Base 该变量指定了RO段的 BASE
Image$$RO$$Limit 该变量指定了RO段的 Limit
Image$$RW$$Base 该变量指定了RW段的 BASE
Image$$RW$$Limit 该变量指定了RW段的 Limit
Image$$ZI$$Base 该变量指定了ZI段的 BASE
Image$$ZI$$Limit 该变量指定了ZI段的 Limit
注:具体可以参考ADS Linker Guide
Image$$RO$$Limit 减 Image$$RO$$Base 等于RO段的大小
Image$$RW$$Limit 减 Image$$RW$$Base 等于RW段的大小
Image$$ZI$$Limit 减 Image$$ZI$$Base 等于ZI段的大小
(Image$$RO$$Limit 减 Image$$RO$$Base)
+ (Image$$RW$$Limit 减 Image$$RW$$Base)
= 等于整个程序的大小
注:ZI段始包括在RW段里面的。

 

你可能感兴趣的:(SmartARM2200启动文件分析)