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 |