打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
浅析eCos系统Redboot单元启动流程
userphoto

2010.03.02

关注


浅析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

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
ARM Boot 示例
u-boot启动代码start.S详解
AT91初始化代码手册中文翻译版
lowlevel_init过程注释了一遍
转载:arm汇编b,bl指令浅析
C语言在函数调用时,栈是如何变化的?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服