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= = > EnableUARTint 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 8typedef 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使用的commstatic 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 0x60000Using 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