淺析eCos系統(tǒng)Redboot單元啟動(dòng)流程 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個(gè)字符,是ep9312啟動(dòng)所必須[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 //對(duì)于ep93xx來說對(duì)應(yīng):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的基地址,因?yàn)閜c現(xiàn)在運(yùn)行在flash中,并且flash的基地址含1數(shù)一定在最高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,這樣對(duì)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 //之所以進(jìn)行sub操作,我的EP9312使用的是ROMRAM啟動(dòng)方式, //BootROM將直接跳轉(zhuǎn)到flash處執(zhí)行存儲(chǔ)在flash中的代碼,flash被映射到虛擬地址0x60000000之后, //為了還能夠在0x60000000空間執(zhí)行flash中的代碼,那么就需要首先計(jì)算出go_virtual偏移地址, //然后加上flash的虛擬基地址0x60000000,這樣代碼才會(huì)從flash處繼續(xù)順利執(zhí)行[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 //因?yàn)楝F(xiàn)在代碼運(yùn)行在rom中,所以可以安全的對(duì)整個(gè)SDRAM進(jìn)行清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中的數(shù)據(jù)取出來 stmia r1!, {r3-r10} //轉(zhuǎn)儲(chǔ)到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空間的數(shù)據(jù) subs r2, r2, #4 //0x4000~0x8000空間用來存放MMU的PTE虛擬映射表[luther.gliethttp] bne zero
// // Branch to the copy in RAM. // ldr r0, =RamLocation //ok現(xiàn)在取出RamLocation編譯地址0x8504 mov pc, r0 //執(zhí)行完該句之后,程序就到被虛擬映射到0地址的SDRAM中跑了[luther.gliethttp] RamLocation: #endif ... //完成SDRAM初始化,將flash只讀地址映射到虛擬地址0x60000000,將flash讀寫地址映射到虛擬地址0xe0000000,熄滅green led,點(diǎn)亮red led,打開PLL,使能200MHz處理器時(shí)鐘,使能usb時(shí)鐘 //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中地址 //于是將根據(jù)下面的內(nèi)容生成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 //對(duì)應(yīng)PLATFORM_SETUP1宏展開,執(zhí)行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存儲(chǔ)到0地址處,因?yàn)槠涫褂胠dr pc絕對(duì)跳轉(zhuǎn),所以都能實(shí)現(xiàn)跳轉(zhuǎn) 1058: e3a00000 mov r0, #0 ; 0x0 105c: e59f13a4 ldr r1, [pc, #932] ; 0x1408 1060: e5912028 ldr r2, [r1, #40] //將處理handler地址存儲(chǔ)到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改變?yōu)閣arm_reset存儲(chǔ)到0x20處,以等待直接跳轉(zhuǎn)方式的reset來調(diào)用 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數(shù)據(jù)段加載到__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 //對(duì)bbs段進(jìn)行清0操作 1130: e1510002 cmp r1, r2 1134: 9afffffc bls 0x112c 1138: eb001eb6 bl 0x8c18 //bl hal_hardware_init 包含打開串口輸出功能 /* hal_virtual_vector_table[]這個(gè)表就像是linux下的syscall系統(tǒng)調(diào)用,直接調(diào)用hal_virtual_vector_table[]中的項(xiàng)就可以執(zhí)行所要的功能函數(shù) 比如: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 會(huì)從定義的uart口打印出一個(gè)'+'字符 //putDebugChar ('+'); // __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); // CYGACC_COMM_IF_PUTC(*__debug_procs, c);//執(zhí)行子函數(shù)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 /* //執(zhí)行c++中對(duì)象們各自的構(gòu)造函數(shù)[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內(nèi)容為000158e8,也就是他的跳轉(zhuǎn)地址為000158e8 } 經(jīng)過反匯編 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 發(fā)現(xiàn)158e8地址處的類構(gòu)造函數(shù)地址: 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);//產(chǎn)生靜態(tài)對(duì)象,將自己添加到__CTOR_LIST__構(gòu)造函數(shù)空間區(qū). 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> //跳轉(zhuǎn)到hal_if_diag_init()函數(shù)初始化diag,主要是完成gdb的控制函數(shù) //填充,CYGNUM_CALL_IF_SET_COMM_ID_MANGLER對(duì)應(yīng)comm_channels[0],也就是gdb使用的空間 //cyg_hal_diag_mangler_gdb_init()就是完成comm_channels[0]控制函數(shù)填充的函數(shù). //如果想在這里開始就調(diào)用diag_printf("hello\n");來打印數(shù)據(jù),那還不行,必須調(diào)用diag_init_putc(_mon_write_char);設(shè)置 //diag_printf的串口數(shù)據(jù)輸出回調(diào)函數(shù)才行,如果想更早打印數(shù)據(jù),那么可以這樣修改: //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); 在該函數(shù)中追加此行[luther.gliethttp] // plf_hardware_init(); // hal_if_init();//在執(zhí)行完該句之后就可以安全使用diag_printf打印數(shù)據(jù)了. */ 1160: eb003266 bl 0xdb00 //bl cyg_start //進(jìn)入redboot的c主函數(shù) hal_if_init ==> CYGACC_CALL_IF_DELAY_US_SET(delay_us);//設(shè)置時(shí)間調(diào)用函數(shù)體 CYGACC_CALL_IF_FLASH_CFG_OP_SET(flash_config_op);//設(shè)置flash配置調(diào)用函數(shù)體 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節(jié) #define RedBoot_init(_f_,_p_) _RedBoot_init(_f_,_p_) //定義函數(shù)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);//所以這些都是將會(huì)被自動(dòng)執(zhí)行的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的存儲(chǔ)節(jié)中的所有handler處理函數(shù) packages/redboot/v2_0/src/flash.c|173| RedBoot_nested_cmd("fis", //string名為"fis" //fis命令,其自身添加到命令為RedBoot_commands的__RedBoot_CMD_TAB__所在節(jié) "Manage FLASH images", "{cmds}", do_fis, __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__ ); CYG_HAL_TABLE_BEGIN(__FIS_cmds_TAB__, FIS_cmds);//在.ecos.table.節(jié)中定義名為FIS_cmds的管理區(qū),即.ecos.table.FIS_cmds節(jié) 所有需要被do_fis函數(shù)使用的local_cmd_entry命令功能函數(shù)都需要將自己添加到名為FIS_cmds管理區(qū), 所以這樣看起來就像是一個(gè)二維數(shù)組或者多維數(shù)組[luther.gliethttp] RedBoot> fis load ramdisk 對(duì)應(yīng)的存儲(chǔ)結(jié)構(gòu)二維表為: __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__這個(gè)標(biāo)量表示的是一個(gè)對(duì)象,用來索引數(shù)據(jù),而不是函數(shù) .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區(qū)的.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"的節(jié) #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管理區(qū)管理 ); 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節(jié)管理區(qū)管理 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的存儲(chǔ)節(jié). #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感覺應(yīng)該是 //packages/infra/v2_0/src/startup.cxx|92| cyg_start( void ) 1164: eafffffe b 0x1164 //bl _start_hang ...... 以上進(jìn)行vectors的向量表搬移和向量表對(duì)應(yīng)的handler搬移 packages/hal/arm/arch/v2_0/src/vectors.S這是執(zhí)行的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);//執(zhí)行類似linux系統(tǒng)調(diào)用的函數(shù)調(diào)用 展開之后就是 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_); //該函數(shù)指針就是CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(set_console_comm);設(shè)置的函數(shù)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];//當(dāng)前一共定義了8個(gè)comm操作函數(shù) static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1]; static int set_console_comm(int __comm_id) //用來設(shè)置comm口,每個(gè)comm口都對(duì)應(yīng)8個(gè)該comm口操作函數(shù)[luther.gliethttp] { ... ++__comm_id;//這樣保證用戶定義的__comm_id=0,實(shí)際是對(duì)應(yīng)1索引. __selected_id = __comm_id; CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]);//將comm_channels[__comm_id]對(duì)應(yīng)的hal_virtual_comm_table_t單元 //作為默認(rèn)的CONSOLE_PROC回調(diào)函數(shù),放入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存儲(chǔ)空間地址. ... } CYGNUM_CALL_IF_SET_COMM_ID_MANGLER對(duì)應(yīng)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]對(duì)應(yīng)的comm存儲(chǔ)空間地址 CYGACC_COMM_IF_CH_DATA_SET(*comm, &ep9312_ser_channels[0]);//填充該comm的CYGNUM_COMM_IF_CH_DATA數(shù)據(jù) CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);//填充該comm的CYGNUM_COMM_IF_WRITE寫函數(shù)地址 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這個(gè)默認(rèn)值是由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 //默認(rèn)為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這個(gè)global的類型為function函數(shù) 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存儲(chǔ)器 ./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 來看看存儲(chǔ)到flash中的script腳本是怎么被讀出來執(zhí)行的: 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)()將執(zhí)行l(wèi)oad_flash_config ==> config = (struct _config *)(workspace_end-sizeof(struct _config));從workspace的末尾獲得一篇內(nèi)存 cfg_base = (void *)((CYG_ADDRESS)flash_end + 1 - _rup(_rup((-CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));//從flash末尾分配一個(gè)CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK個(gè)block, //packages/redboot/v2_0/cdl/redboot.cdl|611| cdl_option CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK {定義的數(shù)值為-2 //install/include/pkgconf/redboot.h|55| #define CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK -2 //對(duì)于我的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中的數(shù)據(jù)拷貝到SDRAM中 ==> flash_get_config("boot_script", &use_boot_script, CONFIG_BOOL); if (use_boot_script) {//使用script啟動(dòng) flash_get_config("boot_script_data", &script, CONFIG_SCRIPT);//獲得啟動(dòng)script內(nèi)容 flash_get_config("boot_script_timeout", &script_timeout, CONFIG_INT);//獲取超時(shí)時(shí)間 } ==>最后cyg_start進(jìn)入下面的while(true)循環(huán) while (true) { if (prompt) { diag_printf("RedBoot > "); prompt = false; } res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT); //如果script存在,那么從script讀取一行數(shù)據(jù) //否則從串口讀取數(shù)據(jù). expand_aliases(line, sizeof(line));//如果輸入的數(shù)據(jù)line存在別名之類,那么展開別名,替換成真實(shí)的內(nèi)容. command = (char *)&line; if ((cmd = parse(&command, &argc, &argv[0])) != (struct cmd *)0) {//解析command,上面有對(duì)parse函數(shù)的分析 //parse==>return cmd_search(__RedBoot_CMD_TAB__, &__RedBoot_CMD_TAB_END__, argv[0]); //遍歷__RedBoot_CMD_TAB__指向section為.ecos.table的存儲(chǔ)節(jié)中的所有handler處理函數(shù) (cmd->fun)(argc, argv); } } //獲取一行執(zhí)行命令[從串口或者script] ==>_rb_gets ==>_rb_gets_preloaded ==> char *ip = buf; while (true) { #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT if (getc_script(&c))//從script讀取一個(gè)字節(jié)數(shù)據(jù) 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);//執(zhí)行定義的idle函數(shù) } } */ else #endif 從物理串口讀取數(shù)據(jù) ... 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讀取到的一個(gè)字節(jié)數(shù)據(jù) } *ip++ = c;//將讀到一個(gè)字節(jié)數(shù)據(jù)存儲(chǔ)到buffer輸出緩沖區(qū). ... } ==>getc_script ==> while (script && *script) { .... *cp = *script++; if (*cp == '\n') { newline = true; } else { newline = false; } return true; } 根據(jù)下面的script內(nèi)容 config_script[boot_script_data]= .. fis load ramdisk .. fis load zImage .. exec -r 0x800000 -s 0x60000 我們可以看到diag_printf("RedBoot > ");將執(zhí)行3次,每次都從script中讀取一行數(shù)據(jù),所以 我們見到的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中的配置數(shù)據(jù): 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 |