ecos 浅析eCos系统Redboot单元启动流程

 

http://blog.chinaunix.net/u1/38994/article_56618.html

 

http://sources-redhat.mirrors.airband.net/ecos/releases/ecos-3.0/

 

http://blog.chinaunix.net/u1/38994/showart_1856869.html

浅析eCos系统Redboot单元启动流程

浅析eCos系统Redboot单元启动流程

packages/ hal/ arm/ arch/ v2_0/ src/ vectors. S
install/ lib/ target. ld| 1| STARTUP( vectors. o) //入口文件

install/ lib/ target. ld| 2| ENTRY( reset_vector) //入口段

//packages/redboot/v2_0/src/main.c|178| cyg_start(void)

    . code 32
    . section ".vectors" , "ax"
# ifdef PLATFORM_PREAMBLE
        PLATFORM_PREAMBLE //而ep93xx恰好就定义了该宏packages/hal/arm/arm9/ep93xx/v2_0/include/hal_platform_setup.h

/*
#define PLATFORM_PREAMBLE _platform_preamble
#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
    .macro _platform_preamble
    b start_here
    ......
    // Put the current literal pool here.
    .ltorg
    // Put a "CRUS" at offset 0x1000 so that the boot ROM will boot this image.
    // 在0或0x1000地址写入"CRUS"4个字符,是ep9312启动所必须[luther.gliethttp]
    .org 0x1000
    .long 0x53555243 // Put a CRUS in there so this is bootable.
start_here:
    .endm
*/

# endif
    . global __exception_handlers
__exception_handlers:
        ldr pc, . reset_vector // 0x00

        ldr pc, . undefined_instruction // 0x04

        ldr pc, . software_interrupt // 0x08 start && software int

        ldr pc, . abort_prefetch // 0x0C

        ldr pc, . abort_data // 0x10

        . word 0 // unused

        ldr pc, . IRQ // 0x18

        ldr pc, . FIQ // 0x1C

    . . . . . .
reset_vector:
        PLATFORM_SETUP1 //对于ep93xx来说对应:packages/hal/arm/arm9/ep93xx/v2_0/include/hal_platform_setup.h

/*
#define PLATFORM_SETUP1 _platform_setup1
    .macro _platform_setup1

    b Setup
//and r12, pc, #0xf0000000//获取flash的基地址,因为pc现在运行在flash中,并且flash的基地址含1数一定在最高8bit中[luther.gliethttp]
//bl BuildPagetable //建立虚拟地址映射表

    //
    // Create a read-only mapping of FLASH at virtual address 0x6000_0000.
    //
    add r1, r0, #0x00001800 //0x60000000 >> 18 这样将作为虚拟地址入口
#if defined(HAL_PLATFORM_EP9301) || defined(HAL_PLATFORM_EP9302)
    mov r2, #0x00000040
#else
    mov r2, #0x00000080
#endif
    orr r3, r12, #0x0000001e
//将r12中flash的物理地址存入PTE虚拟地址入口为0x60000000,这样对0x60000000访问将被线性MMU到物理地址[luther.gliethttp]
map_flash_6:
        str r3, [r1], #4
        add r3, r3, #0x00100000
        subs r2, r2, #4
        bne map_flash_6
...
    //
    // Enable the MMU and branch to our equivalent virtual address.
    //
    ldr     r0, =0xc0000079
    ldr     r1, =go_virtual
    ldr     r2, =__rom_vectors_vma
    sub     r1, r1, r2  //之所以进行sub操作,我的EP9312使用的是ROMRAM启动方式,
//BootROM将直接跳转到flash处执行存储在flash中的代码,flash被映射到虚拟地址0x60000000之后,
//为了还能够在0x60000000空间执行flash中的代码,那么就需要首先计算出go_virtual偏移地址,
//然后加上flash的虚拟基地址0x60000000,这样代码才会从flash处继续顺利执行[gliethttp.luther-20090310]
    bic     r1, r1, #0xf0000000
    orr     r1, r1, #0x60000000
    mcr     p15, 0, r0, c1, c0, 0
    mov     pc, r1
go_virtual:
    nop
#ifdef CYG_HAL_STARTUP_ROMRAM
//因为现在代码运行在rom中,所以可以安全的对整个SDRAM进行清0操作
    //
    // Copy our image from FLASH to SDRAM.
    //
    ldr     r0,=__rom_vectors_lma //值为0x60000000,就是flash的虚拟地址
    ldr     r1,=__rom_vectors_vma //值为0x8000
    ldr     r2,=__ram_data_end
copy_loop:
        ldmia   r0!, {r3-r10}       //将flash中的数据取出来
        stmia   r1!, {r3-r10}       //转储到0x8000开始处
        cmp     r1, r2
        blt     copy_loop

    //
    // Zero fill the first portion of SDRAM.
    //
    mov     r0, #0x00000000
    mov     r1, #0x00000000
    mov     r2, #0x00002000
zero:
        str     r0, [r1], #4        //清零0~0x4000空间的数据
        subs    r2, r2, #4          //0x4000~0x8000空间用来存放MMU的PTE虚拟映射表[luther.gliethttp]
        bne     zero

    //
    // Branch to the copy in RAM.
    //
    ldr     r0, =RamLocation        //ok现在取出RamLocation编译地址0x8504
    mov     pc, r0                  //执行完该句之后,程序就到被虚拟映射到0地址的SDRAM中跑了[luther.gliethttp]
RamLocation:
#endif
...
//完成SDRAM初始化,将flash只读地址映射到虚拟地址0x60000000,将flash读写地址映射到虚拟地址0xe0000000,熄灭green led,点亮red led,打开PLL,使能200MHz处理器时钟,使能usb时钟
//packages/hal/arm/arch/v2_0/src/arm.ld|105| __rom_vectors_lma = LOADADDR(.rom_vectors);
//packages/hal/arm/arm9/ep93xx/v2_0/include/pkgconf/mlt_arm_arm9_edb9312_romram.ldi|15| SECTION_rom_vectors (ram, 0x8000, AT (0x60000000))
//所以这样__rom_vectors_lma = 0x60000000; __rom_vectors_vma = 0x8000该地址为ram中地址

//于是将根据下面的内容生成install/lib/target.ld
MEMORY
{
    ram : ORIGIN = 0, LENGTH = 0x10000000
    rom : ORIGIN = 0x60000000, LENGTH = 0x2000000 //这是rom的虚拟地址,flash物理地址将在b Setup中被映射到0x60000000这里
}

SECTIONS
{
    SECTIONS_BEGIN
    SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA)
    SECTION_rom_vectors (ram, 0x8000, AT (0x60000000))//
    SECTION_text (ram, ALIGN (0x4), FOLLOWING (.rom_vectors))
    SECTION_fini (ram, ALIGN (0x4), FOLLOWING (.text))
    SECTION_rodata (ram, ALIGN (0x4), FOLLOWING (.fini))
    SECTION_rodata1 (ram, ALIGN (0x4), FOLLOWING (.rodata))
    SECTION_fixup (ram, ALIGN (0x4), FOLLOWING (.rodata1))
    SECTION_gcc_except_table (ram, ALIGN (0x4), FOLLOWING (.fixup))
    SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table))
    SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA)
    _heap1 = ALIGN (0x8); //堆栈开始
    SECTIONS_END
}


SetupReturn:

   .endm
 */

warm_reset:
通过反汇编
luther@gliethttp: / vobs/ tmp/ luther$ arm- elf- objdump - DS - b binary - m arm install/ bin/ redboot. bin | more
    1000:     53555243     cmppl    r5, # 805306372    ; 0x30000004
    1004:     ea00000e     b    0x1044
    1008:     e59ff018     ldr    pc, [ pc, # 24]     ; 0x1028
    100c:     e59ff018     ldr    pc, [ pc, # 24]     ; 0x102c //读取pc+24处的handler

    1010:     e59ff018     ldr    pc, [ pc, # 24]     ; 0x1030
    1014:     e59ff018     ldr    pc, [ pc, # 24]     ; 0x1034
    1018:     00000000     andeq    r0, r0, r0
    101c:     e59ff018     ldr    pc, [ pc, # 24]     ; 0x103c
    1020:     e59ff018     ldr    pc, [ pc, # 24]     ; 0x1040
    1024:     00000040     andeq    r0, r0, r0, asr # 32
    1028:     00009178     andeq    r9, r0, r8, ror r1
    102c:     0000919c     muleq    r0, ip, r1
    1030:     000091c8     andeq    r9, r0, r8, asr # 3
    1034:     000091e4     andeq    r9, r0, r4, ror # 3
    1038:     00000000     andeq    r0, r0, r0
    103c:     000092fc     streqd    r9, [ r0] , - ip
    1040:     000092c4     andeq    r9, r0, r4, asr # 5
    1044:     eafffc9f     b    0x2c8 //对应PLATFORM_SETUP1宏展开,执行Setup操作

    1048:     e3a00000     mov    r0, # 0    ; 0x0
    104c:     e59f13d0     ldr    r1, [ pc, # 976]     ; 0x1424
    1050:     e5912008     ldr    r2, [ r1, # 8] //软中断software interrupt

    1054:     e5802008     str    r2, [ r0, # 8] //将verctor存储到0地址处,因为其使用ldr pc绝对跳转,所以都能实现跳转

    1058:     e3a00000     mov    r0, # 0    ; 0x0
    105c:     e59f13a4     ldr    r1, [ pc, # 932]     ; 0x1408
    1060:     e5912028     ldr    r2, [ r1, # 40] //将处理handler地址存储到0x28地址处,将由ldr    pc, [pc, #24]读取

    1064:     e5802028     str    r2, [ r0, # 40]
    1068:     e5912018     ldr    r2, [ r1, # 24]
    106c:     e5802018     str    r2, [ r0, # 24]
    1070:     e5912038     ldr    r2, [ r1, # 56]
    1074:     e5802038     str    r2, [ r0, # 56]
    1078:     e591201c     ldr    r2, [ r1, # 28]
    107c:     e580201c     str    r2, [ r0, # 28]
    1080:     e591203c     ldr    r2, [ r1, # 60]
    1084:     e580203c     str    r2, [ r0, # 60]
    1088:     e591200c     ldr    r2, [ r1, # 12]
    108c:     e580200c     str    r2, [ r0, # 12]
    1090:     e591202c     ldr    r2, [ r1, # 44]
    1094:     e580202c     str    r2, [ r0, # 44]
    1098:     e5912010     ldr    r2, [ r1, # 16]
    109c:     e5802010     str    r2, [ r0, # 16]
    10a0:     e5912030     ldr    r2, [ r1, # 48]
    10a4:     e5802030     str    r2, [ r0, # 48]
    10a8:     e3a00000     mov    r0, # 0    ; 0x0
    10ac:     e59f1354     ldr    r1, [ pc, # 852]     ; 0x1408
    10b0:     e5912000     ldr    r2, [ r1]
    10b4:     e5802000     str    r2, [ r0] //将reset追加到0地址处

    10b8:     e59f2368     ldr    r2, [ pc, # 872]     ; 0x1428
    10bc:     e5802020     str    r2, [ r0, # 32] //将reset的handler改变为warm_reset存储到0x20处,以等待直接跳转方式的reset来调用

    10c0:     e59f3328     ldr    r3, [ pc, # 808]     ; 0x13f0
//packages/hal/arm/arch/v2_0/src/arm.ld|238| __rom_data_start = LOADADDR (.data);

    10c4:     e59f4328     ldr    r4, [ pc, # 808]     ; 0x13f4
    10c8:     e59f5328     ldr    r5, [ pc, # 808]     ; 0x13f8
    10cc:     e1540005     cmp    r4, r5
    10d0:     0a000005     beq    0x10ec
    10d4:     e2433004     sub    r3, r3, # 4    ; 0x4
    10d8:     e2444004     sub    r4, r4, # 4    ; 0x4
    10dc:     e5b30004     ldr    r0, [ r3, # 4] ! //将__rom_data_start中的data数据段加载到__ram_data_start

    10e0:     e5a40004     str    r0, [ r4, # 4] !
    10e4:     e1540005     cmp    r4, r5
    10e8:     1afffffb     bne    0x10dc
    10ec:     e59fd2e4     ldr    sp, [ pc, # 740]     ; 0x13d8
    10f0:     e3a000d2     mov    r0, # 210    ; 0xd2
    10f4:     e129f000     msr    CPSR_fc, r0
    10f8:     e59fd2dc     ldr    sp, [ pc, # 732]     ; 0x13dc
    10fc:     e3a000db     mov    r0, # 219    ; 0xdb
    1100:     e129f000     msr    CPSR_fc, r0
    1104:     e59fd2d0     ldr    sp, [ pc, # 720]     ; 0x13dc
    1108:     e3a000d3     mov    r0, # 211    ; 0xd3
    110c:     e129f000     msr    CPSR_fc, r0
    1110:     e169f000     msr    SPSR_fc, r0
    1114:     e59fd2bc     ldr    sp, [ pc, # 700]     ; 0x13d8
    1118:     e59f12c4     ldr    r1, [ pc, # 708]     ; 0x13e4
    111c:     e59f22c4     ldr    r2, [ pc, # 708]     ; 0x13e8
    1120:     e3a00000     mov    r0, # 0    ; 0x0
    1124:     e1510002     cmp    r1, r2
    1128:     0a000002     beq    0x1138
    112c:     e4810004     str    r0, [ r1] , # 4 //对bbs段进行清0操作

    1130:     e1510002     cmp    r1, r2
    1134:     9afffffc     bls    0x112c
    1138:     eb001eb6     bl    0x8c18 //bl hal_hardware_init 包含打开串口输出功能

/*
hal_virtual_vector_table[]这个表就像是linux下的syscall系统调用,直接调用hal_virtual_vector_table[]中的项就可以执行所要的功能函数
比如:CYGACC_CALL_IF_DELAY_US_SET(delay_us);
static void
delay_us(cyg_int32 usecs)
{
    CYGARC_HAL_SAVE_GP();
    #ifdef CYGPKG_KERNEL
    ...
    #else // CYGPKG_KERNEL
    #ifdef HAL_DELAY_US
    HAL_DELAY_US(usecs);
//packages/hal/arm/arm9/ep93xx/v2_0/include/hal_diag.h ==> #define HAL_DELAY_US(n) hal_delay_us(n);
//packages/hal/arm/arm9/ep93xx/v2_0/src/ep93xx_misc.c ==> void hal_delay_us(cyg_int32 usecs)
    #else
    while (usecs-- > 0) {
        int i;
        for (i = 0; i < 10; i++);
    }
    #endif // HAL_DELAY_US
    #endif // CYGPKG_KERNEL
    CYGARC_HAL_RESTORE_GP();
}
*/

    113c:     eb00258d     bl    0xa778 //bl initialize_stub 会从定义的uart口打印出一个'+'字符

//putDebugChar ('+');

// __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();

// CYGACC_COMM_IF_PUTC(*__debug_procs, c);//执行子函数CYGNUM_COMM_IF_PUTC [luther.gliethttp]

    1140:     e3a00000     mov    r0, # 0    ; 0x0
    1144:     e59f12d8     ldr    r1, [ pc, # 728]     ; 0x1424
    1148:     e5912004     ldr    r2, [ r1, # 4]
    114c:     e5802004     str    r2, [ r0, # 4]
    1150:     e5912024     ldr    r2, [ r1, # 36]
    1154:     e5802024     str    r2, [ r0, # 36]
    1158:     eb002d0b     bl    0xc58c //bl hal_ctrlc_isr_init

    115c:     eb001e9a     bl    0x8bcc //bl cyg_hal_invoke_constructors

/*
//执行c++中对象们各自的构造函数[luther.gliethttp]
packages/hal/arm/arch/v2_0/src/arm.ld|233| __CTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.ctors*))) __CTOR_END__ = ABSOLUTE (.);
void cyg_hal_invoke_constructors (void)
{
    pfunc *p;
    for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--)
        (*p) ();//我打印p为000363a8,*p内容为000158e8,也就是他的跳转地址为000158e8
}
经过反汇编
luther@gliethttp:/vobs/tmp/ep9312$ arm-elf-objdump -DS ./infra/v2_0/src/infra_diag.o |more
...
00000000 <_GLOBAL__I.10100_diag_write_char>:
   0:    e52de004     str    lr, [sp, -#4]!
   4:    e3a01d9d     mov    r1, #10048    ; 0x2740
   8:    e2811034     add    r1, r1, #52    ; 0x34
   c:    e3a00001     mov    r0, #1    ; 0x1
  10:    e49de004     ldr    lr, [sp], #4
  14:    eafffffe     b    0 <_GLOBAL__I.10100_diag_write_char>
Disassembly of section .ctors.55435: //上面就是.ctors*段,所以将被添加到__CTOR_LIST__代表的KEEP (*(SORT (.ctors*)))段空间.

00000000 <.ctors.55435>:
   0:    00000000     andeq    r0, r0, r0
...
luther@gliethttp:/vobs/tmp/ep9312$ arm-elf-objdump -DS install/bin/redboot.elf |more
发现158e8地址处的类构造函数地址:
class Cyg_dummy_diag_init_class {
public:
    Cyg_dummy_diag_init_class() {
        HAL_DIAG_INIT();
    }
};
static Cyg_dummy_diag_init_class cyg_dummy_diag_init_obj
                                      CYGBLD_ATTRIB_INIT_AFTER(CYG_INIT_HAL);//产生静态对象,将自己添加到__CTOR_LIST__构造函数空间区.

000363a8 <__NETDEVTAB_END__>:
   363a8:    000158e8     andeq    r5, r1, r8, ror #17

000158c8 <_Z41__static_initialization_and_destruction_0ii>:
   158c8:    e3a03d9d     mov    r3, #10048    ; 0x2740
   158cc:    e2833034     add    r3, r3, #52    ; 0x34
   158d0:    e1510003     cmp    r1, r3
   158d4:    03500001     cmpeq    r0, #1    ; 0x1
}

   158d8:    e52de004     str    lr, [sp, -#4]!
   158dc:    149df004     ldrne    pc, [sp], #4
   158e0:    e49de004     ldr    lr, [sp], #4
   158e4:    eafffb17     b    14548 <hal_if_diag_init> //跳转到hal_if_diag_init()函数初始化diag,主要是完成gdb的控制函数
//填充,CYGNUM_CALL_IF_SET_COMM_ID_MANGLER对应comm_channels[0],也就是gdb使用的空间
//cyg_hal_diag_mangler_gdb_init()就是完成comm_channels[0]控制函数填充的函数.
//如果想在这里开始就调用diag_printf("hello/n");来打印数据,那还不行,必须调用diag_init_putc(_mon_write_char);设置
//diag_printf的串口数据输出回调函数才行,如果想更早打印数据,那么可以这样修改:
//static void _mon_write_char(char c, void **param)去掉static,然后
//externC void _mon_write_char(char c, void **param);
//void hal_hardware_init(void)
//{
// diag_init_putc(_mon_write_char); 在该函数中追加此行[luther.gliethttp]
// plf_hardware_init();
// hal_if_init();//在执行完该句之后就可以安全使用diag_printf打印数据了.
*/

    1160:     eb003266     bl    0xdb00 //bl cyg_start //进入redboot的c主函数


hal_if_init
= = > CYGACC_CALL_IF_DELAY_US_SET( delay_us) ; //设置时间调用函数体

    CYGACC_CALL_IF_FLASH_CFG_OP_SET( flash_config_op) ; //设置flash配置调用函数体

    set_debug_comm( CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL) ;
    CYGACC_CALL_IF_SET_DEBUG_COMM_SET( set_debug_comm) ;
    CYGACC_CALL_IF_SET_CONSOLE_COMM_SET( set_console_comm) ;
    CYGACC_CALL_IF_VERSION_SET( CYGNUM_CALL_IF_TABLE_VERSION_CALL
            | ( ( CYG_ADDRWORD) CYGNUM_CALL_IF_TABLE_VERSION_COMM< < CYGNUM_CALL_IF_TABLE_VERSION_COMM_shift) ) ;
    CYGACC_CALL_IF_RESET_SET( reset ) ;
    CYGACC_CALL_IF_KILL_VECTOR_SET( kill_by_reset) ;
    CYGACC_CALL_IF_FLUSH_ICACHE_SET( flush_icache) ;
    CYGACC_CALL_IF_FLUSH_DCACHE_SET( flush_dcache) ;

//packages/redboot/v2_0/src/main.c|178| cyg_start(void)

/*
CYG_HAL_TABLE_BEGIN( __RedBoot_INIT_TAB__, RedBoot_inits );//__RedBoot_INIT_TAB__指向.ecos.table.RedBoot_inits.begin首地址
CYG_HAL_TABLE_END( __RedBoot_INIT_TAB_END__, RedBoot_inits );

#define _RedBoot_init(_f_,_p_) /
struct init_tab_entry _init_tab_##_p_##_f_ /
  CYG_HAL_TABLE_QUALIFIED_ENTRY(RedBoot_inits,_p_##_f_) = { _f_ }; //登记到.ecos.table.RedBoot_inits.data节
#define RedBoot_init(_f_,_p_) _RedBoot_init(_f_,_p_) //定义函数RedBoot_init

    for (init_entry = __RedBoot_INIT_TAB__; init_entry != &__RedBoot_INIT_TAB_END__; init_entry++) {
        (*init_entry->fun)();
        //do_flash_init
        //load_flash_config
        //net_init
    }

packages/redboot/v2_0/src/flash.c|1235| RedBoot_init(_do_flash_init, RedBoot_INIT_FIRST);//所以这些都是将会被自动执行的function
packages/redboot/v2_0/src/flash.c|2118| RedBoot_init(load_flash_config, RedBoot_INIT_FIRST);
packages/redboot/v2_0/src/fs/ide.c|489| RedBoot_init(ide_init, RedBoot_INIT_FIRST);
packages/redboot/v2_0/src/decompress.c|104| RedBoot_init(_zlib_init, RedBoot_INIT_FIRST);
packages/redboot/v2_0/src/net/net_io.c|575| RedBoot_init(net_init, RedBoot_INIT_LAST);
packages/redboot/v2_0/include/redboot.h|251| #define RedBoot_init(_f_,_p_) _RedBoot_init(_f_,_p_)

luther@gliethttp:/vobs/tmp/ep9312$ arm-elf-objdump -DS ./redboot/v2_0/src/redboot_flash.o |more
...
Disassembly of section .ecos.table.FIS_cmds.data.fis_init:

00000000 <_cmd_tab_fis_init>:
   0:    00000004     andeq    r0, r0, r4
   4:    0000000c     andeq    r0, r0, ip
   8:    00000030     andeq    r0, r0, r0, lsr r0
...

cyg_start
==>parse
==>return cmd_search(__RedBoot_CMD_TAB__, &__RedBoot_CMD_TAB_END__, argv[0]);//遍历__RedBoot_CMD_TAB__指向section为.ecos.table的存储节中的所有handler处理函数

packages/redboot/v2_0/src/flash.c|173| RedBoot_nested_cmd("fis", //string名为"fis"
//fis命令,其自身添加到命令为RedBoot_commands的__RedBoot_CMD_TAB__所在节
            "Manage FLASH images",
            "{cmds}",
            do_fis,
            __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__
    );
CYG_HAL_TABLE_BEGIN(__FIS_cmds_TAB__, FIS_cmds);//在.ecos.table.节中定义名为FIS_cmds的管理区,即.ecos.table.FIS_cmds节
所有需要被do_fis函数使用的local_cmd_entry命令功能函数都需要将自己添加到名为FIS_cmds管理区,
所以这样看起来就像是一个二维数组或者多维数组[luther.gliethttp]

RedBoot> fis load ramdisk
对应的存储结构二维表为:
__RedBoot_CMD_TAB__["fis"] ==> do_fis
                           ==> cmd_search(__FIS_cmds_TAB__)
__FIS_cmds_TAB__["load"] ==> fis_load

__RedBoot_CMD_TAB__["fis"]["load"]
__RedBoot_CMD_TAB__["fis"]["create"]

#define CYGARC_P2ALIGNMENT 2
#ifndef CYG_HAL_TABLE_BEGIN
#define CYG_HAL_TABLE_BEGIN(_label, _name) /
__asm__(".section /".ecos.table." __xstring(_name) ".begin/",/"aw/"/n" /
    ".globl " __xstring(CYG_LABEL_DEFN(_label)) "/n" /
    ".type " __xstring(CYG_LABEL_DEFN(_label)) ",object/n" /
    ".p2align " __xstring(CYGARC_P2ALIGNMENT) "/n" /
__xstring(CYG_LABEL_DEFN(_label)) ":/n" /
    ".previous/n" /
       )
#endif
展开就是:
.section ".ecos.table.FIS_cmds.begin","aw"
.globl __FIS_cmds_TAB__
.type __FIS_cmds_TAB__,object //表示__FIS_cmds_TAB__这个标量表示的是一个对象,用来索引数据,而不是函数
.p2align 2
__FIS_cmds_TAB__:
.previous
下面是.previous的一行英文解释:
The .PREVIOUS directive instructs the assembler to set the current section in memory to the section described immediately before the current one. The .PREVIOUS directive operates on a stack.

就像
ENTRY(begin)
SECTION
{
.=0x10000000;
.text:{*(.text)}
.data:{*(.data)}
.bss:{*(.bss)}
}

.section ".ecos.table.FIS_cmds.begin","aw"用来说明这里是.ecos.table.FIS_cmds段的begin起始地址处,
.ecos.table.FIS_cmds.data.fis_load 向这里就是表示.ecos.table.FIS_cmds段中的data区的.fis_load域.

#ifndef CYG_HAL_TABLE_ENTRY
#define CYG_HAL_TABLE_ENTRY( _name ) /
        CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".data")
#endif
#ifndef CYG_HAL_TABLE_QUALIFIED_ENTRY
#define CYG_HAL_TABLE_QUALIFIED_ENTRY( _name, _qual ) /
        CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".data." /
                              __xstring(_qual)) //建立名为".ecos.table.RedBoot_commands.data.do_fis"的节
#endif

RedBoot> fis load ramdisk

fis_load
==>fis_lookup

fis_create

packages/redboot/v2_0/src/flash.c|86|
local_cmd_entry("init",
                "Initialize FLASH Image System [FIS]",
                "[-f]",
                fis_init,
                FIS_cmds //由名为FIS_cmds管理区管理
    );
packages/redboot/v2_0/src/flash.c|97|
local_cmd_entry("list",
local_cmd_entry("list",
                "Display contents of FLASH Image System [FIS]",
                FIS_LIST_OPTS,
                fis_list,
                FIS_cmds //由名为.ecos.table.FIS_cmds节管理区管理
packages/redboot/v2_0/src/flash.c|122|
local_cmd_entry("load",
                "Load image from FLASH Image System [FIS] into RAM",
                fis_load_usage,
                fis_load,
                FIS_cmds
packages/redboot/v2_0/src/flash.c|128|
local_cmd_entry("create",
                "Create an image",
                "-b <mem_base> -l <image_length> [-s <data_length>]/n"
                " [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
                fis_create,
                FIS_cmds
packages/redboot/v2_0/src/flash.c|138|
local_cmd_entry("erase",
                "Erase FLASH contents",
                "-f <flash_addr> -l <length>",
                fis_erase,
                FIS_cmds
packages/redboot/v2_0/src/flash.c|158|
local_cmd_entry("write",
                "Write raw data directly to FLASH",
                "-f <flash_addr> -b <mem_base> -l <image_length>",
                fis_write,
                FIS_cmds
packages/redboot/v2_0/include/redboot.h|235| #define local_cmd_entry(_s_,_h_,_u_,_f_,_n_)

local_cmd_entry("load",
                "Load image from FLASH Image System [FIS] into RAM",
                fis_load_usage,
                fis_load,
                FIS_cmds

packages/redboot/v2_0/src/main.c|119| CYG_HAL_TABLE_BEGIN( __RedBoot_CMD_TAB__, RedBoot_commands );
#define CYG_HAL_TABLE_BEGIN( _label, _name ) /
__asm__(".section /".ecos.table." __xstring(_name) ".begin/",/"aw/"/n" /
    ".globl " __xstring(CYG_LABEL_DEFN(_label)) "/n" /
    ".type " __xstring(CYG_LABEL_DEFN(_label)) ",object/n" /
    ".p2align " __xstring(CYGARC_P2ALIGNMENT) "/n" /
__xstring(CYG_LABEL_DEFN(_label)) ":/n" /
    ".previous/n" /
       )
#endif
所以可以看到__RedBoot_CMD_TAB__就是指向section为.ecos.table.RedBoot_commands的存储节.

#ifndef CYG_HAL_TABLE_QUALIFIED_ENTRY
#define CYG_HAL_TABLE_QUALIFIED_ENTRY( _name, _qual ) /
        CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".data." /
                              __xstring(_qual))
#endif
#define RedBoot_cmd(_s_,_h_,_u_,_f_) cmd_entry(_s_,_h_,_u_,_f_,0,0,RedBoot_commands)
#define RedBoot_nested_cmd(_s_,_h_,_u_,_f_,_subs_,_sube_) cmd_entry(_s_,_h_,_u_,_f_,_subs_,_sube_,RedBoot_commands)
#define _cmd_entry(_s_,_h_,_u_,_f_,_subs_,_sube_,_n_) /
cmd_fun _f_; /
struct cmd _cmd_tab_##_f_ CYG_HAL_TABLE_QUALIFIED_ENTRY(_n_,_f_) = {_s_, _h_, _u_, _f_, _subs_, _sube_};
#define cmd_entry(_s_,_h_,_u_,_f_,_subs_,_sube_,_n_) /
extern _cmd_entry(_s_,_h_,_u_,_f_,_subs_,_sube_,_n_)
#define local_cmd_entry(_s_,_h_,_u_,_f_,_n_) /
static _cmd_entry(_s_,_h_,_u_,_f_,0,0,_n_)

packages/redboot/v2_0/src/flash.c|1563| RedBoot_cmd("fconfig",
packages/redboot/v2_0/src/flash.c|1703| RedBoot_cmd("alias",
packages/redboot/v2_0/src/fs/disk.c|68| RedBoot_cmd("disks",
packages/redboot/v2_0/src/net/net_io.c|716| RedBoot_cmd("ip_address",
packages/redboot/v2_0/src/net/ping.c|63| RedBoot_cmd("ping",
packages/redboot/v2_0/src/dump.c|58| RedBoot_cmd("dump",
packages/redboot/v2_0/src/dump.c|63| RedBoot_cmd("x",
packages/redboot/v2_0/src/load.c|80| RedBoot_cmd("load",
packages/redboot/v2_0/src/mcmp.c|58| RedBoot_cmd("mcmp",
packages/redboot/v2_0/src/caches.c|61| RedBoot_cmd("cache",
packages/redboot/v2_0/src/io.c|67| RedBoot_cmd("channel",
packages/redboot/v2_0/src/io.c|73| RedBoot_cmd("channel",
packages/redboot/v2_0/src/main.c|84| RedBoot_cmd("version",
packages/redboot/v2_0/src/main.c|89| RedBoot_cmd("help",
packages/redboot/v2_0/src/main.c|94| RedBoot_cmd("go",
packages/redboot/v2_0/src/main.c|100| RedBoot_cmd("reset",
packages/redboot/v2_0/src/main.c|107| RedBoot_cmd("baudrate",
packages/redboot/v2_0/src/mfill.c|58| RedBoot_cmd("mfill",
packages/redboot/v2_0/src/cksum.c|60| RedBoot_cmd("cksum",
packages/redboot/v2_0/include/redboot.h|228| #define RedBoot_cmd(_s_,_h_,_u_,_f_) cmd_entry(_s_,_h_,_u_,_f_,0,0,RedBoot_commands)


*/

//如果是eCos感觉应该是

//packages/infra/v2_0/src/startup.cxx|92| cyg_start( void )

    1164:     eafffffe     b    0x1164 //bl _start_hang

    . . . . . .
以上进行vectors的向量表搬移和向量表对应的handler搬移

packages/ hal/ arm/ arch/ v2_0/ src/ vectors. S这是执行的0地址文件
= = > hal_hardware_init
= = > hal_if_init
= = > cyg_hal_plf_comms_init
= = > cyg_hal_plf_serial_init
= = > cyg_hal_plf_serial_init_channel
= = > EnableUART

int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM( CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT) ; //执行类似linux系统调用的函数调用

展开之后就是
int cur = __call_vv_CYGNUM_CALL_IF_SET_CONSOLE_COMM( CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT) ;


# define CYGACC_CALL_VV1( t, e, p1) __call_vv_# # e( ( p1) )
# define __call_VV1( _n_, _tt_, _rt_, _t1_) /
static __inline__ _rt_ /
__call_vv_# # _n_( _t1_ _p1_) /
{ /
    _rt_ res; /
    _ENTER_MONITOR( ) ; /
    res = ( ( _tt_ * ) hal_virtual_vector_table[ _n_] ) ( _p1_) ; /
    _EXIT_MONITOR( ) ; /
    return res; /
}

# define CYGACC_CALL_IF_SET_CONSOLE_COMM( _i_) /
 CYGACC_CALL_VV1( __call_if_set_console_comm_t* , CYGNUM_CALL_IF_SET_CONSOLE_COMM, ( _i_) )
__call_VV1( CYGNUM_CALL_IF_SET_CONSOLE_COMM, __call_if_set_console_comm_t, int , int )
# define CYGNUM_CALL_IF_SET_CONSOLE_COMM 13
展开之后为
static __inline__ int
__call_vv_CYGNUM_CALL_IF_SET_CONSOLE_COMM( int _p1_)
{
    int res;
    _ENTER_MONITOR( ) ;
    res = ( ( __call_if_set_console_comm_t * ) hal_virtual_vector_table[ 13] ) ( _p1_) ;
//该函数指针就是CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(set_console_comm);设置的函数set_console_comm

//#define CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(_x_) /

// hal_virtual_vector_table[CYGNUM_CALL_IF_SET_CONSOLE_COMM]=(CYG_ADDRWORD)(_x_)

    _EXIT_MONITOR( ) ;
    return res;
}
# define CYGACC_CALL_IF_SET_CONSOLE_COMM_SET( _x_) /
 hal_virtual_vector_table[ CYGNUM_CALL_IF_SET_CONSOLE_COMM] = ( CYG_ADDRWORD) ( _x_)

# define CYGNUM_COMM_IF_CH_DATA 0
# define CYGNUM_COMM_IF_WRITE 1
# define CYGNUM_COMM_IF_READ 2
# define CYGNUM_COMM_IF_PUTC 3
# define CYGNUM_COMM_IF_GETC 4
# define CYGNUM_COMM_IF_CONTROL 5
# define CYGNUM_COMM_IF_DBG_ISR 6
# define CYGNUM_COMM_IF_GETC_TIMEOUT 7

# define CYGNUM_COMM_IF_TABLE_SIZE 8

typedef volatile CYG_ADDRWORD hal_virtual_comm_table_t[ CYGNUM_COMM_IF_TABLE_SIZE] ; //当前一共定义了8个comm操作函数

static hal_virtual_comm_table_t comm_channels[ CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+ 1] ;
static int
set_console_comm( int __comm_id) //用来设置comm口,每个comm口都对应8个该comm口操作函数[luther.gliethttp]

{
    . . .
    + + __comm_id; //这样保证用户定义的__comm_id=0,实际是对应1索引.

    __selected_id = __comm_id;
    CYGACC_CALL_IF_CONSOLE_PROCS_SET( comm_channels[ __comm_id] ) ; //将comm_channels[__comm_id]对应的hal_virtual_comm_table_t单元

    //作为默认的CONSOLE_PROC回调函数,放入hal_virtual_vector_table[CYGNUM_CALL_IF_CONSOLE_PROCS]=comm_channels[__comm_id];

    //使用CYGACC_CALL_IF_CONSOLE_PROCS()可以返回hal_virtual_comm_table_t* comm;该comm存储空间地址.

    . . .
}
CYGNUM_CALL_IF_SET_COMM_ID_MANGLER对应comm_channels[ 0] ; 也是gdb使用的comm

static void
cyg_hal_plf_serial_init( void )
{
    hal_virtual_comm_table_t* comm;
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM( CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT) ;

    // Init channels

    // TODO shouldn't this be default value, not 0?

    cyg_hal_plf_serial_init_channel( & ep9312_ser_channels[ 0] ) ;

    // Setup procs in the vector table


    // Set channel 0

    CYGACC_CALL_IF_SET_CONSOLE_COMM( 0) ;
    comm = CYGACC_CALL_IF_CONSOLE_PROCS( ) ; //获取comm_channels[0+1]对应的comm存储空间地址

    CYGACC_COMM_IF_CH_DATA_SET( * comm, & ep9312_ser_channels[ 0] ) ; //填充该comm的CYGNUM_COMM_IF_CH_DATA数据

    CYGACC_COMM_IF_WRITE_SET( * comm, cyg_hal_plf_serial_write) ; //填充该comm的CYGNUM_COMM_IF_WRITE写函数地址

    CYGACC_COMM_IF_READ_SET( * comm, cyg_hal_plf_serial_read) ;
    CYGACC_COMM_IF_PUTC_SET( * comm, cyg_hal_plf_serial_putc) ;
    CYGACC_COMM_IF_GETC_SET( * comm, cyg_hal_plf_serial_getc) ;
    CYGACC_COMM_IF_CONTROL_SET( * comm, cyg_hal_plf_serial_control) ;
    CYGACC_COMM_IF_DBG_ISR_SET( * comm, cyg_hal_plf_serial_isr) ;
    CYGACC_COMM_IF_GETC_TIMEOUT_SET( * comm, cyg_hal_plf_serial_getc_timeout) ;

    // Restore original console

    CYGACC_CALL_IF_SET_CONSOLE_COMM( cur) ;
}

cyg_start
= = > packages/ redboot/ v2_0/ src/ main. c| 202| CYGACC_CALL_IF_SET_CONSOLE_COMM( CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL) ;
至于CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL这个默认值是由cdl配置的:
packages/ hal/ arm/ arm9/ ep93xx/ v2_0/ cdl/ hal_arm_arm9_ep93xx. cdl| 273| cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL {
        display "Debug serial port"
        active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE
        flavor data
        legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS- 1
        default_value 0
//默认为0,这就表示CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);

//就是CYGACC_CALL_IF_SET_CONSOLE_COMM(0);

        description "
            The ep93xx board has three serial ports. This option
            chooses which port will be used to connect to a host
            running GDB."

     }

packages/ hal/ arm/ arch/ v2_0/ src/ vectors. S| 430| bl hal_hardware_init
packages/ hal/ arm/ arm9/ var/ v2_0/ src/ arm9_misc. c| 74| hal_if_init( ) ;
packages/ hal/ common/ v2_0/ src/ hal_if. c| 663| externC void cyg_hal_plf_comms_init( void ) ;
packages/ hal/ common/ v2_0/ src/ hal_if. c| 925| cyg_hal_plf_comms_init( ) ;
ackages/ hal/ arm/ arm9/ ep93xx/ v2_0/ src/ hal_diag. c| 374| cyg_hal_plf_comms_init( void )

flash_init
= = > flash_hwr_init
= = > code_len = ( unsigned long ) & flash_query_end - ( unsigned long ) & flash_query;
= = > packages/ devs/ flash/ intel/ strata/ v2_0/ cdl/ flash_strata. cdl| 113| echo " .globl flash_query_end" > > flash_query. s
   packages/ devs/ flash/ intel/ strata/ v2_0/ cdl/ flash_strata. cdl| 114| echo "flash_query_end:" > > flash_query. s
luther@gliethttp: / vobs/ tmp/ ep9312$ vim . / devs/ flash/ intel/ strata/ v2_0/ flash_query. s
    . file     "flash_query.c"
    . text
    . align    2
    . global    flash_query
    . type    flash_query, function //flash_query这个global的类型为function函数

flash_query:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    str    lr, [ sp, # - 4] !
    mov    ip, r0
    mrc p15, 0, r3, c1, c0, 0;
    mov    r3, r3, lsr # 2
    ands    lr, r3, # 1
    beq    . L3
    mov r2, # 0; 1: mov r3, # 0; 2: orr r0, r2, r3; mcr p15, 0, r0, c7, c14, 2; add r3, r3, # 32; cmp r3, # 256; bne 2b; add r2, r2, # 0x04000000; cmp r2, # 0; bne 1b; mcr p15, 0, r0, c7, c10, 4;
    mrc p15, 0, r1, c1, c0, 0; bic r1, r1, # 0x000C; mcr p15, 0, r1, c1, c0, 0; mov r1, # 0; mcr p15, 0, r1, c7, c6, 0
. L3:
    mov    r3, # 9961472
    add    r3, r3, # 152
    mov    r1, # 1610612736
    str    r3, [ r1, # 0]
    mov    r3, # 199680
    mov    r2, # 52
    add    r3, r3, # 320
. L10:
    sub    r3, r3, # 1
    cmp    r3, # 0
    bgt    . L10
    cmp    r2, # 0
    ble    . L21
. L15:
    ldr    r3, [ r1] , # 4
    sub    r2, r2, # 1
    cmp    r2, # 0
    strb    r3, [ ip] , # 1
    bgt    . L15
. L21:
    mov    r3, # 16711680
    add    r3, r3, # 255
    cmp    lr, # 0
    str    r3, [ r1, # 0]
    beq    . L16
    mrc p15, 0, r1, c1, c0, 0; orr r1, r1, # 0x000F; mcr p15, 0, r1, c1, c0, 0
. L16:
    mov    r0, # 0
    ldr    pc, [ sp] , # 4
. Lfe1:
    . size    flash_query, . Lfe1- flash_query
    . ident    "GCC: (GNU) 3.2.1"
 . text
 . globl flash_query_end
flash_query_end:

luther@gliethttp: / vobs/ tmp/ ep9312$ find . - name '*.o'
. / hal/ arm/ arm9/ var/ v2_0/ src/ hal_arm_arm9_var_arm9_misc. o
. / hal/ arm/ arm9/ ep93xx/ v2_0/ src/ hal_arm_arm9_ep93xx_hal_diag. o
. / hal/ arm/ arm9/ ep93xx/ v2_0/ src/ hal_arm_arm9_ep93xx_ep93xx_misc. o
. / hal/ arm/ arch/ v2_0/ src/ hal_arm_arch_hal_syscall. o
. / hal/ arm/ arch/ v2_0/ src/ hal_arm_arch_hal_misc. o
. / hal/ arm/ arch/ v2_0/ src/ hal_arm_arch_arm_stub. o
. / hal/ arm/ arch/ v2_0/ src/ hal_arm_arch_redboot_linux_exec. o
. / hal/ arm/ arch/ v2_0/ src/ hal_arm_arch_context. o
. / hal/ common/ v2_0/ src/ hal_common_drv_api. o
. / hal/ common/ v2_0/ src/ hal_common_hal_if. o
. / hal/ common/ v2_0/ src/ hal_common_dummy. o
. / hal/ common/ v2_0/ src/ hal_common_dbg- threads- syscall. o
. / hal/ common/ v2_0/ src/ hal_common_bplist- dynamic. o
. / hal/ common/ v2_0/ src/ hal_common_hal_stub. o
. / hal/ common/ v2_0/ src/ hal_common_hal_misc. o
. / hal/ common/ v2_0/ src/ hal_common_thread- packets. o
. / hal/ common/ v2_0/ src/ hal_common_generic- stub. o
. / devs/ eth/ arm/ ep93xx/ v2_0/ src/ devs_eth_arm_ep93xx_if_ep93xx. o
. / devs/ flash/ intel/ strata/ v2_0/ flash_query. o //可见flash使用的是intel/strata存储器

. / devs/ flash/ intel/ strata/ v2_0/ src/ devs_flash_intel_strata_strata. o
. / devs/ flash/ intel/ strata/ v2_0/ flash_erase_block. o
. / devs/ flash/ intel/ strata/ v2_0/ flash_program_buf. o
. / services/ crc/ v2_0/ src/ services_crc_crc16. o
. / services/ crc/ v2_0/ src/ services_crc_posix_crc. o
. / services/ crc/ v2_0/ src/ services_crc_crc32. o
. / redboot/ v2_0/ src/ redboot_parse. o
. / redboot/ v2_0/ src/ redboot_xyzModem. o
. / redboot/ v2_0/ src/ redboot_alias. o
. / redboot/ v2_0/ src/ redboot_mfill. o
. / redboot/ v2_0/ src/ redboot_dump. o
. / redboot/ v2_0/ src/ net/ redboot_tcp. o
. / redboot/ v2_0/ src/ net/ redboot_net_io. o
. / redboot/ v2_0/ src/ net/ redboot_arp. o
. / redboot/ v2_0/ src/ net/ redboot_inet_addr. o
. / redboot/ v2_0/ src/ net/ redboot_udp. o
. / redboot/ v2_0/ src/ net/ redboot_dns. o
. / redboot/ v2_0/ src/ net/ redboot_timers. o
. / redboot/ v2_0/ src/ net/ redboot_cksum. o
. / redboot/ v2_0/ src/ net/ redboot_ping. o
. / redboot/ v2_0/ src/ net/ redboot_tftp_client. o
. / redboot/ v2_0/ src/ net/ redboot_pktbuf. o
. / redboot/ v2_0/ src/ net/ redboot_enet. o
. / redboot/ v2_0/ src/ net/ redboot_icmp. o
. / redboot/ v2_0/ src/ net/ redboot_ip. o
. / redboot/ v2_0/ src/ net/ redboot_http_client. o
. / redboot/ v2_0/ src/ net/ redboot_bootp. o
. / redboot/ v2_0/ src/ redboot_cksum. o
. / redboot/ v2_0/ src/ redboot_main. o
. / redboot/ v2_0/ src/ redboot_flash. o
. / redboot/ v2_0/ src/ redboot_io. o
. / redboot/ v2_0/ src/ redboot_caches. o
. / redboot/ v2_0/ src/ redboot_mcmp. o
. / redboot/ v2_0/ src/ redboot_load. o
. / redboot/ v2_0/ src/ redboot_syscall. o
. / redboot/ v2_0/ src/ redboot_ticks. o
. / redboot/ v2_0/ src/ redboot_misc_funs. o
. / infra/ v2_0/ src/ infra_memcpy. o
. / infra/ v2_0/ src/ infra_simple. o
. / infra/ v2_0/ src/ infra_abort. o
. / infra/ v2_0/ src/ infra_fancy. o
. / infra/ v2_0/ src/ infra_userstart. o
. / infra/ v2_0/ src/ infra_dummyxxmain. o
. / infra/ v2_0/ src/ infra_pkgstart. o
. / infra/ v2_0/ src/ infra_tcdiag. o
. / infra/ v2_0/ src/ infra_null. o
. / infra/ v2_0/ src/ infra_diag. o
. / infra/ v2_0/ src/ infra_pure. o
. / infra/ v2_0/ src/ infra_memset. o
. / infra/ v2_0/ src/ infra_startup. o
. / infra/ v2_0/ src/ infra_eprintf. o
. / infra/ v2_0/ src/ infra_delete. o
. / infra/ v2_0/ src/ infra_prestart. o
. / infra/ v2_0/ src/ infra_buffer. o
. / io/ eth/ v2_0/ src/ stand_alone/ io_eth_eth_drv. o
. / io/ flash/ v2_0/ src/ io_flash_flash. o
. / install/ lib/ vectors. o
. / install/ lib/ extras. o
. / install/ lib/ version. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strcoll. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_memchr. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strsuppt. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strlen. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strncat. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strcpy. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strtok. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strspn. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strxfrm. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strcmp. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strcspn. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strncmp. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strrchr. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_memmove. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strcat. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strstr. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strchr. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strpbrk. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_strncpy. o
. / language/ c/ libc/ string / v2_0/ src/ language_c_libc_string_memcmp. o

来看看存储到flash中的script脚本是怎么被读出来执行的:
packages/ redboot/ v2_0/ src/ main. c
= = > cyg_start
= = >
    for ( init_entry = __RedBoot_INIT_TAB__; init_entry ! = & __RedBoot_INIT_TAB_END__; init_entry+ + ) {
        ( * init_entry- > fun) ( ) ;
        //do_flash_init

        //load_flash_config

        //net_init

    }
= = > ( * init_entry- > fun) ( ) 将执行load_flash_config
= = >
    config = ( struct _config * ) ( workspace_end- sizeof ( struct _config) ) ; 从workspace的末尾获得一篇内存
    cfg_base = ( void * ) ( ( CYG_ADDRESS) flash_end + 1 - _rup( _rup( ( - CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK* flash_block_size) , cfg_size) , flash_block_size) ) ; //从flash末尾分配一个CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK个block,

    //packages/redboot/v2_0/cdl/redboot.cdl|611| cdl_option CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK {定义的数值为-2

    //install/include/pkgconf/redboot.h|55| #define CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK -2

    //对于我的intel/strata类型flash

    //flash_start=0x60000000

    //flash_end=0x61ffffff

    //flash_block_size=0x40000

    //所以0x62000000 - 2*0x40000 = 0x61f80000

    //cfg_base=0x61f80000

= = > memcpy ( config, cfg_base, sizeof ( struct _config) ) ; //将flash中的数据拷贝到SDRAM中

= = >
    flash_get_config( "boot_script" , & use_boot_script, CONFIG_BOOL) ;
    if ( use_boot_script) { //使用script启动

        flash_get_config( "boot_script_data" , & script, CONFIG_SCRIPT) ; //获得启动script内容

        flash_get_config( "boot_script_timeout" , & script_timeout, CONFIG_INT) ; //获取超时时间

    }
= = > 最后cyg_start进入下面的while( true ) 循环
        while ( true ) {
            if ( prompt) {
                diag_printf( "RedBoot > " ) ;
                prompt = false ;
            }
            res = _rb_gets( line , sizeof ( line ) , CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) ;
            //如果script存在,那么从script读取一行数据

            //否则从串口读取数据.

            expand_aliases( line , sizeof ( line ) ) ; //如果输入的数据line存在别名之类,那么展开别名,替换成真实的内容.

            command = ( char * ) & line ;
            if ( ( cmd = parse( & command, & argc, & argv[ 0] ) ) ! = ( struct cmd * ) 0) { //解析command,上面有对parse函数的分析

    //parse==>return cmd_search(__RedBoot_CMD_TAB__, &__RedBoot_CMD_TAB_END__, argv[0]);

    //遍历__RedBoot_CMD_TAB__指向section为.ecos.table的存储节中的所有handler处理函数

                ( cmd- > fun) ( argc, argv) ;
            }
        }

//获取一行执行命令[从串口或者script]

= = > _rb_gets
= = > _rb_gets_preloaded
= = >
    char * ip = buf;
    while ( true ) {
# ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
        if ( getc_script( & c) ) //从script读取一个字节数据

            do_idle( false ) ;
/*
void
do_idle(bool is_idle)
{
    struct idle_tab_entry *idle_entry;

    for (idle_entry = __RedBoot_IDLE_TAB__;
         idle_entry != &__RedBoot_IDLE_TAB_END__; idle_entry++) {
        (*idle_entry->fun)(is_idle);//执行定义的idle函数
    }
}
*/

        else
# endif
        从物理串口读取数据
        . . .
        switch ( c) {
            case CTRL( 'P' ) :
                . . .
                break ;
            case CTRL( 'C' ) : // ^C

                . . .
                break ;
            case '/n' :
            case '/r' :
                . . .
                //回显回车、换行

                if ( console_echo) {
                    mon_write_char( '/r' ) ;
                    mon_write_char( '/n' ) ;
     }
                return _GETS_OK;
            default :
                if ( console_echo) {
                    mon_write_char( c) ; //回显从script读取到的一个字节数据

                }
                * ip+ + = c; //将读到一个字节数据存储到buffer输出缓冲区.

                . . .

    }
= = > getc_script
= = >
    while ( script & & * script) {
        . . . .
        * cp = * script+ + ;
     if ( * cp = = '/n' ) {
              newline = true ;
            } else {
              newline = false ;
            }
     return true ;
    }
根据下面的script内容
config_script[ boot_script_data] =
. . fis load ramdisk
. . fis load zImage
. . exec - r 0x800000 - s 0x60000
我们可以看到diag_printf( "RedBoot > " ) ; 将执行3次, 每次都从script中读取一行数据, 所以
我们见到的log将如下:
RedBoot > fis load ramdisk
RedBoot > fis load zImage
RedBoot > exec - r 0x800000 - s 0x60000
Using base address 0x00080000 and length 0x000c938c
Uncompressing Linux. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . done, booting the kernel.

Please press Enter to activate this console.

我的flash中的配置数据:
all configs:
config_bool[ boot_script] = 1
config_script[ boot_script_data] =
. . fis load ramdisk
. . fis load zImage
. . exec - r 0x800000 - s 0x600000
config_int[ boot_script_timeout] = 0x3
config_bool[ bootp] = 0
config_ip[ bootp_my_gateway_ip] = 0x100a8c0
config_ip[ bootp_my_ip] = 0x6400a8c0
config_ip[ bootp_my_ip_mask] = 0xffffff
config_ip[ bootp_server_ip] = 0x200a8c0
config_ip[ dns_ip] = 0x100a8c0
config_int[ gdb_port] = 0x2328
config_bool[ info_console_force] = 0
config_int[ info_console_number] = 0x0
config_bool[ net_debug] = 0

其打印源码如下:
# if 1 & & 1
    {
        unsigned char * dp;
        void * val_ptr;
        int len;
        unsigned long val;
        diag_printf( "all configs:/n" ) ;
        dp = & config- > config_data[ 0] ;
        while ( dp < & config- > config_data[ sizeof ( config- > config_data) ] ) {
            val_ptr = ( void * ) CONFIG_OBJECT_VALUE( dp) ;
            switch ( CONFIG_OBJECT_TYPE( dp) ) {
                // Note: the data may be unaligned in the configuration data

            case CONFIG_BOOL:
                val = 0;
                memcpy ( & val, val_ptr, sizeof ( bool ) ) ;
                diag_printf( "config_bool[%s]=%d/n" , CONFIG_OBJECT_KEY( dp) , val) ;
                break ;
            case CONFIG_INT:
                memcpy ( & val, val_ptr, sizeof ( unsigned long ) ) ;
                diag_printf( "config_int[%s]=0x%x/n" , CONFIG_OBJECT_KEY( dp) , val) ;
                break ;
# ifdef CYGPKG_REDBOOT_NETWORKING
            case CONFIG_IP:
                memcpy ( & val, val_ptr, sizeof ( in_addr_t) ) ;
                diag_printf( "config_ip[%s]=0x%x/n" , CONFIG_OBJECT_KEY( dp) , val) ;
                break ;
            case CONFIG_ESA:
                //memcpy(val, val_ptr, sizeof(enet_addr_t));

                break ;
# endif
            case CONFIG_STRING:
                // Just return a pointer to the script/line

                //*(unsigned char **)val = (unsigned char *)val_ptr;

                diag_printf( "config_string[%s]=%s/n" , CONFIG_OBJECT_KEY( dp) , ( char * ) val_ptr) ;
                break ;
            case CONFIG_SCRIPT:
                {
                    char * sp, * lp;
                    diag_printf( "config_script[%s]=/n" , CONFIG_OBJECT_KEY( dp) ) ;
                    sp = lp = ( unsigned char * ) val_ptr;
                    while ( * sp) {
                        while ( * lp ! = '/n' ) lp+ + ;
                        * lp = '/0' ;
                        diag_printf( ".. %s/n" , sp) ;
                        * lp+ + = '/n' ;
                        sp = lp;
                    }
                }
                break ;
            }
            len = 4 + CONFIG_OBJECT_KEYLEN( dp) + CONFIG_OBJECT_ENABLE_KEYLEN( dp) +
                config_length( CONFIG_OBJECT_TYPE( dp) ) ;
            dp + = len;
        }
    }
    diag_printf( "done!/n" ) ;
# endif

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值