浅析eCos系统Redboot单元启动流程
packages/
hal/
arm/
arch/
v2_0/
src/
vectors.
S
install/
lib/
target.
ld|
1|
STARTUP(
vectors.
o)
//入口文件
install/
lib/
target.
ld|
2|
ENTRY(
reset_vector)
//入口段
//packages/redboot/v2_0/src/main.c|178| cyg_start(void)
.
code 32
.
section ".vectors"
,
"ax"
#
ifdef
PLATFORM_PREAMBLE
PLATFORM_PREAMBLE //而ep93xx恰好就定义了该宏packages/hal/arm/arm9/ep93xx/v2_0/include/hal_platform_setup.h
/*
#define PLATFORM_PREAMBLE _platform_preamble
#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
.macro _platform_preamble
b start_here
......
// Put the current literal pool here.
.ltorg
// Put a "CRUS" at offset 0x1000 so that the boot ROM will boot this image.
// 在0或0x1000地址写入"CRUS"4个字符,是ep9312启动所必须[luther.gliethttp]
.org 0x1000
.long 0x53555243 // Put a CRUS in there so this is bootable.
start_here:
.endm
*/
#
endif
.
global __exception_handlers
__exception_handlers:
ldr pc,
.
reset_vector // 0x00
ldr pc,
.
undefined_instruction // 0x04
ldr pc,
.
software_interrupt // 0x08 start && software int
ldr pc,
.
abort_prefetch // 0x0C
ldr pc,
.
abort_data // 0x10
.
word 0 // unused
ldr pc,
.
IRQ // 0x18
ldr pc,
.
FIQ // 0x1C
.
.
.
.
.
.
reset_vector:
PLATFORM_SETUP1 //对于ep93xx来说对应:packages/hal/arm/arm9/ep93xx/v2_0/include/hal_platform_setup.h
/*
#define PLATFORM_SETUP1 _platform_setup1
.macro _platform_setup1
b Setup
//and r12, pc, #0xf0000000//获取flash的基地址,因为pc现在运行在flash中,并且flash的基地址含1数一定在最高8bit中[luther.gliethttp]
//bl BuildPagetable //建立虚拟地址映射表
//
// Create a read-only mapping of FLASH at virtual address 0x6000_0000.
//
add r1, r0, #0x00001800 //0x60000000 >> 18 这样将作为虚拟地址入口
#if defined(HAL_PLATFORM_EP9301) || defined(HAL_PLATFORM_EP9302)
mov r2, #0x00000040
#else
mov r2, #0x00000080
#endif
orr r3, r12, #0x0000001e
//将r12中flash的物理地址存入PTE虚拟地址入口为0x60000000,这样对0x60000000访问将被线性MMU到物理地址[luther.gliethttp]
map_flash_6:
str r3, [r1], #4
add r3, r3, #0x00100000
subs r2, r2, #4
bne map_flash_6
...
//
// Enable the MMU and branch to our equivalent virtual address.
//
ldr r0, =0xc0000079
ldr r1, =go_virtual
ldr r2, =__rom_vectors_vma
sub r1, r1, r2 //之所以进行sub操作,我的EP9312使用的是ROMRAM启动方式,
//BootROM将直接跳转到flash处执行存储在flash中的代码,flash被映射到虚拟地址0x60000000之后,
//为了还能够在0x60000000空间执行flash中的代码,那么就需要首先计算出go_virtual偏移地址,
//然后加上flash的虚拟基地址0x60000000,这样代码才会从flash处继续顺利执行[gliethttp.luther-20090310]
bic r1, r1, #0xf0000000
orr r1, r1, #0x60000000
mcr p15, 0, r0, c1, c0, 0
mov pc, r1
go_virtual:
nop
#ifdef CYG_HAL_STARTUP_ROMRAM
//因为现在代码运行在rom中,所以可以安全的对整个SDRAM进行清0操作
//
// Copy our image from FLASH to SDRAM.
//
ldr r0,=__rom_vectors_lma //值为0x60000000,就是flash的虚拟地址
ldr r1,=__rom_vectors_vma //值为0x8000
ldr r2,=__ram_data_end
copy_loop:
ldmia r0!, {r3-r10} //将flash中的数据取出来
stmia r1!, {r3-r10} //转储到0x8000开始处
cmp r1, r2
blt copy_loop
//
// Zero fill the first portion of SDRAM.
//
mov r0, #0x00000000
mov r1, #0x00000000
mov r2, #0x00002000
zero:
str r0, [r1], #4 //清零0~0x4000空间的数据
subs r2, r2, #4 //0x4000~0x8000空间用来存放MMU的PTE虚拟映射表[luther.gliethttp]
bne zero
//
// Branch to the copy in RAM.
//
ldr r0, =RamLocation //ok现在取出RamLocation编译地址0x8504
mov pc, r0 //执行完该句之后,程序就到被虚拟映射到0地址的SDRAM中跑了[luther.gliethttp]
RamLocation:
#endif
...
//完成SDRAM初始化,将flash只读地址映射到虚拟地址0x60000000,将flash读写地址映射到虚拟地址0xe0000000,熄灭green led,点亮red led,打开PLL,使能200MHz处理器时钟,使能usb时钟
//packages/hal/arm/arch/v2_0/src/arm.ld|105| __rom_vectors_lma = LOADADDR(.rom_vectors);
//packages/hal/arm/arm9/ep93xx/v2_0/include/pkgconf/mlt_arm_arm9_edb9312_romram.ldi|15|
SECTION_rom_vectors (ram, 0x8000, AT (0x60000000))
//所以这样__rom_vectors_lma = 0x60000000; __rom_vectors_vma = 0x8000该地址为ram中地址
//于是将根据下面的内容生成install/lib/target.ld
MEMORY
{
ram : ORIGIN = 0, LENGTH = 0x10000000
rom : ORIGIN = 0x60000000, LENGTH = 0x2000000 //这是rom的虚拟地址,flash物理地址将在b Setup中被映射到0x60000000这里
}
SECTIONS
{
SECTIONS_BEGIN
SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA)
SECTION_rom_vectors (ram, 0x8000, AT (0x60000000))//
SECTION_text (ram, ALIGN (0x4), FOLLOWING (.rom_vectors))
SECTION_fini (ram, ALIGN (0x4), FOLLOWING (.text))
SECTION_rodata (ram, ALIGN (0x4), FOLLOWING (.fini))
SECTION_rodata1 (ram, ALIGN (0x4), FOLLOWING (.rodata))
SECTION_fixup (ram, ALIGN (0x4), FOLLOWING (.rodata1))
SECTION_gcc_except_table (ram, ALIGN (0x4), FOLLOWING (.fixup))
SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table))
SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA)
_heap1 = ALIGN (0x8); //堆栈开始
SECTIONS_END
}
SetupReturn:
.endm
*/
warm_reset:
通过反汇编
luther@gliethttp:
/
vobs/
tmp/
luther$ arm-
elf-
objdump -
DS -
b binary -
m arm install/
bin/
redboot.
bin |
more
1000:
53555243 cmppl r5,
#
805306372 ;
0x30000004
1004:
ea00000e b 0x1044
1008:
e59ff018 ldr pc,
[
pc,
#
24]
;
0x1028
100c:
e59ff018 ldr pc,
[
pc,
#
24]
;
0x102c //读取pc+24处的handler
1010:
e59ff018 ldr pc,
[
pc,
#
24]
;
0x1030
1014:
e59ff018 ldr pc,
[
pc,
#
24]
;
0x1034
1018:
00000000 andeq r0,
r0,
r0
101c:
e59ff018 ldr pc,
[
pc,
#
24]
;
0x103c
1020:
e59ff018 ldr pc,
[
pc,
#
24]
;
0x1040
1024:
00000040 andeq r0,
r0,
r0,
asr #
32
1028:
00009178 andeq r9,
r0,
r8,
ror r1
102c:
0000919c muleq r0,
ip,
r1
1030:
000091c8 andeq r9,
r0,
r8,
asr #
3
1034:
000091e4 andeq r9,
r0,
r4,
ror #
3
1038:
00000000 andeq r0,
r0,
r0
103c:
000092fc streqd r9,
[
r0]
,
-
ip
1040:
000092c4 andeq r9,
r0,
r4,
asr #
5
1044:
eafffc9f b 0x2c8 //对应PLATFORM_SETUP1宏展开,执行Setup操作
1048:
e3a00000 mov r0,
#
0 ;
0x0
104c:
e59f13d0 ldr r1,
[
pc,
#
976]
;
0x1424
1050:
e5912008 ldr r2,
[
r1,
#
8]
//软中断software interrupt
1054:
e5802008 str r2,
[
r0,
#
8]
//将verctor存储到0地址处,因为其使用ldr pc绝对跳转,所以都能实现跳转
1058:
e3a00000 mov r0,
#
0 ;
0x0
105c:
e59f13a4 ldr r1,
[
pc,
#
932]
;
0x1408
1060:
e5912028 ldr r2,
[
r1,
#
40]
//将处理handler地址存储到0x28地址处,将由ldr pc, [pc, #24]读取
1064:
e5802028 str r2,
[
r0,
#
40]
1068:
e5912018 ldr r2,
[
r1,
#
24]
106c:
e5802018 str r2,
[
r0,
#
24]
1070:
e5912038 ldr r2,
[
r1,
#
56]
1074:
e5802038 str r2,
[
r0,
#
56]
1078:
e591201c ldr r2,
[
r1,
#
28]
107c:
e580201c str r2,
[
r0,
#
28]
1080:
e591203c ldr r2,
[
r1,
#
60]
1084:
e580203c str r2,
[
r0,
#
60]
1088:
e591200c ldr r2,
[
r1,
#
12]
108c:
e580200c str r2,
[
r0,
#
12]
1090:
e591202c ldr r2,
[
r1,
#
44]
1094:
e580202c str r2,
[
r0,
#
44]
1098:
e5912010 ldr r2,
[
r1,
#
16]
109c:
e5802010 str r2,
[
r0,
#
16]
10a0:
e5912030 ldr r2,
[
r1,
#
48]
10a4:
e5802030 str r2,
[
r0,
#
48]
10a8:
e3a00000 mov r0,
#
0 ;
0x0
10ac:
e59f1354 ldr r1,
[
pc,
#
852]
;
0x1408
10b0:
e5912000 ldr r2,
[
r1]
10b4:
e5802000 str r2,
[
r0]
//将reset追加到0地址处
10b8:
e59f2368 ldr r2,
[
pc,
#
872]
;
0x1428
10bc:
e5802020 str r2,
[
r0,
#
32]
//将reset的handler改变为warm_reset存储到0x20处,以等待直接跳转方式的reset来调用
10c0:
e59f3328 ldr r3,
[
pc,
#
808]
;
0x13f0
//packages/hal/arm/arch/v2_0/src/arm.ld|238| __rom_data_start = LOADADDR (.data);
10c4:
e59f4328 ldr r4,
[
pc,
#
808]
;
0x13f4
10c8:
e59f5328 ldr r5,
[
pc,
#
808]
;
0x13f8
10cc:
e1540005 cmp r4,
r5
10d0:
0a000005 beq 0x10ec
10d4:
e2433004 sub r3,
r3,
#
4 ;
0x4
10d8:
e2444004 sub r4,
r4,
#
4 ;
0x4
10dc:
e5b30004 ldr r0,
[
r3,
#
4]
!
//将__rom_data_start中的data数据段加载到__ram_data_start
10e0:
e5a40004 str r0,
[
r4,
#
4]
!
10e4:
e1540005 cmp r4,
r5
10e8:
1afffffb bne 0x10dc
10ec:
e59fd2e4 ldr sp,
[
pc,
#
740]
;
0x13d8
10f0:
e3a000d2 mov r0,
#
210 ;
0xd2
10f4:
e129f000 msr CPSR_fc,
r0
10f8:
e59fd2dc ldr sp,
[
pc,
#
732]
;
0x13dc
10fc:
e3a000db mov r0,
#
219 ;
0xdb
1100:
e129f000 msr CPSR_fc,
r0
1104:
e59fd2d0 ldr sp,
[
pc,
#
720]
;
0x13dc
1108:
e3a000d3 mov r0,
#
211 ;
0xd3
110c:
e129f000 msr CPSR_fc,
r0
1110:
e169f000 msr SPSR_fc,
r0
1114:
e59fd2bc ldr sp,
[
pc,
#
700]
;
0x13d8
1118:
e59f12c4 ldr r1,
[
pc,
#
708]
;
0x13e4
111c:
e59f22c4 ldr r2,
[
pc,
#
708]
;
0x13e8
1120:
e3a00000 mov r0,
#
0 ;
0x0
1124:
e1510002 cmp r1,
r2
1128:
0a000002 beq 0x1138
112c:
e4810004 str r0,
[
r1]
,
#
4 //对bbs段进行清0操作
1130:
e1510002 cmp r1,
r2
1134:
9afffffc bls 0x112c
1138:
eb001eb6 bl 0x8c18 //bl hal_hardware_init 包含打开串口输出功能
/*
hal_virtual_vector_table[]这个表就像是linux下的syscall系统调用,直接调用hal_virtual_vector_table[]中的项就可以执行所要的功能函数
比如:CYGACC_CALL_IF_DELAY_US_SET(delay_us);
static void
delay_us(cyg_int32 usecs)
{
CYGARC_HAL_SAVE_GP();
#ifdef CYGPKG_KERNEL
...
#else // CYGPKG_KERNEL
#ifdef HAL_DELAY_US
HAL_DELAY_US(usecs);
//packages/hal/arm/arm9/ep93xx/v2_0/include/hal_diag.h ==> #define HAL_DELAY_US(n) hal_delay_us(n);
//packages/hal/arm/arm9/ep93xx/v2_0/src/ep93xx_misc.c ==> void hal_delay_us(cyg_int32 usecs)
#else
while (usecs-- > 0) {
int i;
for (i = 0; i < 10; i++);
}
#endif // HAL_DELAY_US
#endif // CYGPKG_KERNEL
CYGARC_HAL_RESTORE_GP();
}
*/
113c:
eb00258d bl 0xa778 //bl initialize_stub 会从定义的uart口打印出一个'+'字符
//putDebugChar ('+');
// __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();
// CYGACC_COMM_IF_PUTC(*__debug_procs, c);//执行子函数CYGNUM_COMM_IF_PUTC [luther.gliethttp]
1140:
e3a00000 mov r0,
#
0 ;
0x0
1144:
e59f12d8 ldr r1,
[
pc,
#
728]
;
0x1424
1148:
e5912004 ldr r2,
[
r1,
#
4]
114c:
e5802004 str r2,
[
r0,
#
4]
1150:
e5912024 ldr r2,
[
r1,
#
36]
1154:
e5802024 str r2,
[
r0,
#
36]
1158:
eb002d0b bl 0xc58c //bl hal_ctrlc_isr_init
115c:
eb001e9a bl 0x8bcc //bl cyg_hal_invoke_constructors
/*
//执行c++中对象们各自的构造函数[luther.gliethttp]
packages/hal/arm/arch/v2_0/src/arm.ld|233| __CTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.ctors*))) __CTOR_END__ = ABSOLUTE (.);
void cyg_hal_invoke_constructors (void)
{
pfunc *p;
for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--)
(*p) ();//我打印p为000363a8,*p内容为000158e8,也就是他的跳转地址为000158e8
}
经过反汇编
luther@gliethttp:/vobs/tmp/ep9312$ arm-elf-objdump -DS ./infra/v2_0/src/infra_diag.o |more
...
00000000 <_GLOBAL__I.10100_diag_write_char>:
0: e52de004 str lr, [sp, -#4]!
4: e3a01d9d mov r1, #10048 ; 0x2740
8: e2811034 add r1, r1, #52 ; 0x34
c: e3a00001 mov r0, #1 ; 0x1
10: e49de004 ldr lr, [sp], #4
14: eafffffe b 0 <_GLOBAL__I.10100_diag_write_char>
Disassembly of section .ctors.55435: //上面就是.ctors*段,所以将被添加到__CTOR_LIST__代表的KEEP (*(SORT (.ctors*)))段空间.
00000000 <.ctors.55435>:
0: 00000000 andeq r0, r0, r0
...
luther@gliethttp:/vobs/tmp/ep9312$ arm-elf-objdump -DS install/bin/redboot.elf |more
发现158e8地址处的类构造函数地址:
class Cyg_dummy_diag_init_class {
public:
Cyg_dummy_diag_init_class() {
HAL_DIAG_INIT();
}
};
static Cyg_dummy_diag_init_class cyg_dummy_diag_init_obj
CYGBLD_ATTRIB_INIT_AFTER(CYG_INIT_HAL);//产生静态对象,将自己添加到__CTOR_LIST__构造函数空间区.
000363a8 <__NETDEVTAB_END__>:
363a8: 000158e8 andeq r5, r1, r8, ror #17
000158c8 <_Z41__static_initialization_and_destruction_0ii>:
158c8: e3a03d9d mov r3, #10048 ; 0x2740
158cc: e2833034 add r3, r3, #52 ; 0x34
158d0: e1510003 cmp r1, r3
158d4: 03500001 cmpeq r0, #1 ; 0x1
}
158d8: e52de004 str lr, [sp, -#4]!
158dc: 149df004 ldrne pc, [sp], #4
158e0: e49de004 ldr lr, [sp], #4
158e4: eafffb17 b 14548 <hal_if_diag_init> //跳转到hal_if_diag_init()函数初始化diag,主要是完成gdb的控制函数
//填充,CYGNUM_CALL_IF_SET_COMM_ID_MANGLER对应comm_channels[0],也就是gdb使用的空间
//cyg_hal_diag_mangler_gdb_init()就是完成comm_channels[0]控制函数填充的函数.
//如果想在这里开始就调用diag_printf("hello/n");来打印数据,那还不行,必须调用diag_init_putc(_mon_write_char);设置
//diag_printf的串口数据输出回调函数才行,如果想更早打印数据,那么可以这样修改:
//static void _mon_write_char(char c, void **param)去掉static,然后
//externC void _mon_write_char(char c, void **param);
//void hal_hardware_init(void)
//{
// diag_init_putc(_mon_write_char); 在该函数中追加此行[luther.gliethttp]
// plf_hardware_init();
// hal_if_init();//在执行完该句之后就可以安全使用diag_printf打印数据了.
*/
1160:
eb003266 bl 0xdb00 //bl cyg_start //进入redboot的c主函数
hal_if_init
=
=
>
CYGACC_CALL_IF_DELAY_US_SET(
delay_us)
;
//设置时间调用函数体
CYGACC_CALL_IF_FLASH_CFG_OP_SET(
flash_config_op)
;
//设置flash配置调用函数体
set_debug_comm(
CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL)
;
CYGACC_CALL_IF_SET_DEBUG_COMM_SET(
set_debug_comm)
;
CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(
set_console_comm)
;
CYGACC_CALL_IF_VERSION_SET(
CYGNUM_CALL_IF_TABLE_VERSION_CALL
|
(
(
CYG_ADDRWORD)
CYGNUM_CALL_IF_TABLE_VERSION_COMM<
<
CYGNUM_CALL_IF_TABLE_VERSION_COMM_shift)
)
;
CYGACC_CALL_IF_RESET_SET(
reset
)
;
CYGACC_CALL_IF_KILL_VECTOR_SET(
kill_by_reset)
;
CYGACC_CALL_IF_FLUSH_ICACHE_SET(
flush_icache)
;
CYGACC_CALL_IF_FLUSH_DCACHE_SET(
flush_dcache)
;
//packages/redboot/v2_0/src/main.c|178| cyg_start(void)
/*
CYG_HAL_TABLE_BEGIN( __RedBoot_INIT_TAB__, RedBoot_inits );//__RedBoot_INIT_TAB__指向.ecos.table.RedBoot_inits.begin首地址
CYG_HAL_TABLE_END( __RedBoot_INIT_TAB_END__, RedBoot_inits );
#define _RedBoot_init(_f_,_p_) /
struct init_tab_entry _init_tab_##_p_##_f_ /
CYG_HAL_TABLE_QUALIFIED_ENTRY(RedBoot_inits,_p_##_f_) = { _f_ }; //登记到.ecos.table.RedBoot_inits.data节
#define RedBoot_init(_f_,_p_) _RedBoot_init(_f_,_p_) //定义函数RedBoot_init
for (init_entry = __RedBoot_INIT_TAB__; init_entry != &__RedBoot_INIT_TAB_END__; init_entry++) {
(*init_entry->fun)();
//do_flash_init
//load_flash_config
//net_init
}
packages/redboot/v2_0/src/flash.c|1235| RedBoot_init(_do_flash_init, RedBoot_INIT_FIRST);//所以这些都是将会被自动执行的function
packages/redboot/v2_0/src/flash.c|2118| RedBoot_init(load_flash_config, RedBoot_INIT_FIRST);
packages/redboot/v2_0/src/fs/ide.c|489| RedBoot_init(ide_init, RedBoot_INIT_FIRST);
packages/redboot/v2_0/src/decompress.c|104| RedBoot_init(_zlib_init, RedBoot_INIT_FIRST);
packages/redboot/v2_0/src/net/net_io.c|575| RedBoot_init(net_init, RedBoot_INIT_LAST);
packages/redboot/v2_0/include/redboot.h|251| #define RedBoot_init(_f_,_p_) _RedBoot_init(_f_,_p_)
luther@gliethttp:/vobs/tmp/ep9312$ arm-elf-objdump -DS ./redboot/v2_0/src/redboot_flash.o |more
...
Disassembly of section .ecos.table.FIS_cmds.data.fis_init:
00000000 <_cmd_tab_fis_init>:
0: 00000004 andeq r0, r0, r4
4: 0000000c andeq r0, r0, ip
8: 00000030 andeq r0, r0, r0, lsr r0
...
cyg_start
==>parse
==>return cmd_search(__RedBoot_CMD_TAB__,
&__RedBoot_CMD_TAB_END__,
argv[0]);//遍历__RedBoot_CMD_TAB__指向section为.ecos.table的存储节中的所有handler处理函数
packages/redboot/v2_0/src/flash.c|173| RedBoot_nested_cmd("fis", //string名为"fis"
//fis命令,其自身添加到命令为RedBoot_commands的__RedBoot_CMD_TAB__所在节
"Manage FLASH images",
"{cmds}",
do_fis,
__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__
);
CYG_HAL_TABLE_BEGIN(__FIS_cmds_TAB__, FIS_cmds);//在.ecos.table.节中定义名为FIS_cmds的管理区,即.ecos.table.FIS_cmds节
所有需要被do_fis函数使用的local_cmd_entry命令功能函数都需要将自己添加到名为FIS_cmds管理区,
所以这样看起来就像是一个二维数组或者多维数组[luther.gliethttp]
RedBoot> fis load ramdisk
对应的存储结构二维表为:
__RedBoot_CMD_TAB__["fis"] ==> do_fis
==> cmd_search(__FIS_cmds_TAB__)
__FIS_cmds_TAB__["load"] ==> fis_load
__RedBoot_CMD_TAB__["fis"]["load"]
__RedBoot_CMD_TAB__["fis"]["create"]
#define CYGARC_P2ALIGNMENT 2
#ifndef CYG_HAL_TABLE_BEGIN
#define CYG_HAL_TABLE_BEGIN(_label, _name) /
__asm__(".section /".ecos.table." __xstring(_name) ".begin/",/"aw/"/n" /
".globl " __xstring(CYG_LABEL_DEFN(_label)) "/n" /
".type " __xstring(CYG_LABEL_DEFN(_label)) ",object/n" /
".p2align " __xstring(CYGARC_P2ALIGNMENT) "/n" /
__xstring(CYG_LABEL_DEFN(_label)) ":/n" /
".previous/n" /
)
#endif
展开就是:
.section ".ecos.table.FIS_cmds.begin","aw"
.globl __FIS_cmds_TAB__
.type __FIS_cmds_TAB__,object //表示__FIS_cmds_TAB__这个标量表示的是一个对象,用来索引数据,而不是函数
.p2align 2
__FIS_cmds_TAB__:
.previous
下面是.previous的一行英文解释:
The .PREVIOUS directive instructs the assembler to set the current
section in memory to the section described immediately before the
current one. The .PREVIOUS directive operates on a stack.
就像
ENTRY(begin)
SECTION
{
.=0x10000000;
.text:{*(.text)}
.data:{*(.data)}
.bss:{*(.bss)}
}
.section ".ecos.table.FIS_cmds.begin","aw"用来说明这里是.ecos.table.FIS_cmds段的begin起始地址处,
.ecos.table.FIS_cmds.data.fis_load 向这里就是表示.ecos.table.FIS_cmds段中的data区的.fis_load域.
#ifndef CYG_HAL_TABLE_ENTRY
#define CYG_HAL_TABLE_ENTRY( _name ) /
CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".data")
#endif
#ifndef CYG_HAL_TABLE_QUALIFIED_ENTRY
#define CYG_HAL_TABLE_QUALIFIED_ENTRY( _name, _qual ) /
CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".data." /
__xstring(_qual)) //建立名为".ecos.table.RedBoot_commands.data.do_fis"的节
#endif
RedBoot> fis load ramdisk
fis_load
==>fis_lookup
fis_create
packages/redboot/v2_0/src/flash.c|86|
local_cmd_entry("init",
"Initialize FLASH Image System [FIS]",
"[-f]",
fis_init,
FIS_cmds //由名为FIS_cmds管理区管理
);
packages/redboot/v2_0/src/flash.c|97|
local_cmd_entry("list",
local_cmd_entry("list",
"Display contents of FLASH Image System [FIS]",
FIS_LIST_OPTS,
fis_list,
FIS_cmds //由名为.ecos.table.FIS_cmds节管理区管理
packages/redboot/v2_0/src/flash.c|122|
local_cmd_entry("load",
"Load image from FLASH Image System [FIS] into RAM",
fis_load_usage,
fis_load,
FIS_cmds
packages/redboot/v2_0/src/flash.c|128|
local_cmd_entry("create",
"Create an image",
"-b <mem_base> -l <image_length> [-s <data_length>]/n"
" [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
fis_create,
FIS_cmds
packages/redboot/v2_0/src/flash.c|138|
local_cmd_entry("erase",
"Erase FLASH contents",
"-f <flash_addr> -l <length>",
fis_erase,
FIS_cmds
packages/redboot/v2_0/src/flash.c|158|
local_cmd_entry("write",
"Write raw data directly to FLASH",
"-f <flash_addr> -b <mem_base> -l <image_length>",
fis_write,
FIS_cmds
packages/redboot/v2_0/include/redboot.h|235| #define local_cmd_entry(_s_,_h_,_u_,_f_,_n_)
local_cmd_entry("load",
"Load image from FLASH Image System [FIS] into RAM",
fis_load_usage,
fis_load,
FIS_cmds
packages/redboot/v2_0/src/main.c|119| CYG_HAL_TABLE_BEGIN( __RedBoot_CMD_TAB__, RedBoot_commands );
#define CYG_HAL_TABLE_BEGIN( _label, _name ) /
__asm__(".section /".ecos.table." __xstring(_name) ".begin/",/"aw/"/n" /
".globl " __xstring(CYG_LABEL_DEFN(_label)) "/n" /
".type " __xstring(CYG_LABEL_DEFN(_label)) ",object/n" /
".p2align " __xstring(CYGARC_P2ALIGNMENT) "/n" /
__xstring(CYG_LABEL_DEFN(_label)) ":/n" /
".previous/n" /
)
#endif
所以可以看到__RedBoot_CMD_TAB__就是指向section为.ecos.table.RedBoot_commands的存储节.
#ifndef CYG_HAL_TABLE_QUALIFIED_ENTRY
#define CYG_HAL_TABLE_QUALIFIED_ENTRY( _name, _qual ) /
CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".data." /
__xstring(_qual))
#endif
#define RedBoot_cmd(_s_,_h_,_u_,_f_) cmd_entry(_s_,_h_,_u_,_f_,0,0,RedBoot_commands)
#define RedBoot_nested_cmd(_s_,_h_,_u_,_f_,_subs_,_sube_) cmd_entry(_s_,_h_,_u_,_f_,_subs_,_sube_,RedBoot_commands)
#define _cmd_entry(_s_,_h_,_u_,_f_,_subs_,_sube_,_n_) /
cmd_fun _f_; /
struct cmd _cmd_tab_##_f_ CYG_HAL_TABLE_QUALIFIED_ENTRY(_n_,_f_) = {_s_, _h_, _u_, _f_, _subs_, _sube_};
#define cmd_entry(_s_,_h_,_u_,_f_,_subs_,_sube_,_n_) /
extern _cmd_entry(_s_,_h_,_u_,_f_,_subs_,_sube_,_n_)
#define local_cmd_entry(_s_,_h_,_u_,_f_,_n_) /
static _cmd_entry(_s_,_h_,_u_,_f_,0,0,_n_)
packages/redboot/v2_0/src/flash.c|1563| RedBoot_cmd("fconfig",
packages/redboot/v2_0/src/flash.c|1703| RedBoot_cmd("alias",
packages/redboot/v2_0/src/fs/disk.c|68| RedBoot_cmd("disks",
packages/redboot/v2_0/src/net/net_io.c|716| RedBoot_cmd("ip_address",
packages/redboot/v2_0/src/net/ping.c|63| RedBoot_cmd("ping",
packages/redboot/v2_0/src/dump.c|58| RedBoot_cmd("dump",
packages/redboot/v2_0/src/dump.c|63| RedBoot_cmd("x",
packages/redboot/v2_0/src/load.c|80| RedBoot_cmd("load",
packages/redboot/v2_0/src/mcmp.c|58| RedBoot_cmd("mcmp",
packages/redboot/v2_0/src/caches.c|61| RedBoot_cmd("cache",
packages/redboot/v2_0/src/io.c|67| RedBoot_cmd("channel",
packages/redboot/v2_0/src/io.c|73| RedBoot_cmd("channel",
packages/redboot/v2_0/src/main.c|84| RedBoot_cmd("version",
packages/redboot/v2_0/src/main.c|89| RedBoot_cmd("help",
packages/redboot/v2_0/src/main.c|94| RedBoot_cmd("go",
packages/redboot/v2_0/src/main.c|100| RedBoot_cmd("reset",
packages/redboot/v2_0/src/main.c|107| RedBoot_cmd("baudrate",
packages/redboot/v2_0/src/mfill.c|58| RedBoot_cmd("mfill",
packages/redboot/v2_0/src/cksum.c|60| RedBoot_cmd("cksum",
packages/redboot/v2_0/include/redboot.h|228| #define
RedBoot_cmd(_s_,_h_,_u_,_f_)
cmd_entry(_s_,_h_,_u_,_f_,0,0,RedBoot_commands)
*/
//如果是eCos感觉应该是
//packages/infra/v2_0/src/startup.cxx|92| cyg_start( void )
1164:
eafffffe b 0x1164 //bl _start_hang
.
.
.
.
.
.
以上进行vectors的向量表搬移和向量表对应的handler搬移
packages/
hal/
arm/
arch/
v2_0/
src/
vectors.
S这是执行的0地址文件
=
=
>
hal_hardware_init
=
=
>
hal_if_init
=
=
>
cyg_hal_plf_comms_init
=
=
>
cyg_hal_plf_serial_init
=
=
>
cyg_hal_plf_serial_init_channel
=
=
>
EnableUART
int
cur =
CYGACC_CALL_IF_SET_CONSOLE_COMM(
CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT)
;
//执行类似linux系统调用的函数调用
展开之后就是
int
cur =
__call_vv_CYGNUM_CALL_IF_SET_CONSOLE_COMM(
CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT)
;
#
define
CYGACC_CALL_VV1(
t,
e,
p1)
__call_vv_#
#
e(
(
p1)
)
#
define
__call_VV1(
_n_,
_tt_,
_rt_,
_t1_)
/
static
__inline__
_rt_ /
__call_vv_#
#
_n_(
_t1_ _p1_)
/
{
/
_rt_ res;
/
_ENTER_MONITOR(
)
;
/
res =
(
(
_tt_ *
)
hal_virtual_vector_table[
_n_]
)
(
_p1_)
;
/
_EXIT_MONITOR(
)
;
/
return
res;
/
}
#
define
CYGACC_CALL_IF_SET_CONSOLE_COMM(
_i_)
/
CYGACC_CALL_VV1(
__call_if_set_console_comm_t*
,
CYGNUM_CALL_IF_SET_CONSOLE_COMM,
(
_i_)
)
__call_VV1(
CYGNUM_CALL_IF_SET_CONSOLE_COMM,
__call_if_set_console_comm_t,
int
,
int
)
#
define
CYGNUM_CALL_IF_SET_CONSOLE_COMM 13
展开之后为
static
__inline__
int
__call_vv_CYGNUM_CALL_IF_SET_CONSOLE_COMM(
int
_p1_)
{
int
res;
_ENTER_MONITOR(
)
;
res =
(
(
__call_if_set_console_comm_t *
)
hal_virtual_vector_table[
13]
)
(
_p1_)
;
//该函数指针就是CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(set_console_comm);设置的函数set_console_comm
//#define CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(_x_) /
// hal_virtual_vector_table[CYGNUM_CALL_IF_SET_CONSOLE_COMM]=(CYG_ADDRWORD)(_x_)
_EXIT_MONITOR(
)
;
return
res;
}
#
define
CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(
_x_)
/
hal_virtual_vector_table[
CYGNUM_CALL_IF_SET_CONSOLE_COMM]
=
(
CYG_ADDRWORD)
(
_x_)
#
define
CYGNUM_COMM_IF_CH_DATA 0
#
define
CYGNUM_COMM_IF_WRITE 1
#
define
CYGNUM_COMM_IF_READ 2
#
define
CYGNUM_COMM_IF_PUTC 3
#
define
CYGNUM_COMM_IF_GETC 4
#
define
CYGNUM_COMM_IF_CONTROL 5
#
define
CYGNUM_COMM_IF_DBG_ISR 6
#
define
CYGNUM_COMM_IF_GETC_TIMEOUT 7
#
define
CYGNUM_COMM_IF_TABLE_SIZE 8
typedef
volatile
CYG_ADDRWORD hal_virtual_comm_table_t[
CYGNUM_COMM_IF_TABLE_SIZE]
;
//当前一共定义了8个comm操作函数
static
hal_virtual_comm_table_t comm_channels[
CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+
1]
;
static
int
set_console_comm(
int
__comm_id)
//用来设置comm口,每个comm口都对应8个该comm口操作函数[luther.gliethttp]
{
.
.
.
+
+
__comm_id;
//这样保证用户定义的__comm_id=0,实际是对应1索引.
__selected_id =
__comm_id;
CYGACC_CALL_IF_CONSOLE_PROCS_SET(
comm_channels[
__comm_id]
)
;
//将comm_channels[__comm_id]对应的hal_virtual_comm_table_t单元
//作为默认的CONSOLE_PROC回调函数,放入hal_virtual_vector_table[CYGNUM_CALL_IF_CONSOLE_PROCS]=comm_channels[__comm_id];
//使用CYGACC_CALL_IF_CONSOLE_PROCS()可以返回hal_virtual_comm_table_t* comm;该comm存储空间地址.
.
.
.
}
CYGNUM_CALL_IF_SET_COMM_ID_MANGLER对应comm_channels[
0]
;
也是gdb使用的comm
static
void
cyg_hal_plf_serial_init(
void
)
{
hal_virtual_comm_table_t*
comm;
int
cur =
CYGACC_CALL_IF_SET_CONSOLE_COMM(
CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT)
;
// Init channels
// TODO shouldn't this be default value, not 0?
cyg_hal_plf_serial_init_channel(
&
ep9312_ser_channels[
0]
)
;
// Setup procs in the vector table
// Set channel 0
CYGACC_CALL_IF_SET_CONSOLE_COMM(
0)
;
comm =
CYGACC_CALL_IF_CONSOLE_PROCS(
)
;
//获取comm_channels[0+1]对应的comm存储空间地址
CYGACC_COMM_IF_CH_DATA_SET(
*
comm,
&
ep9312_ser_channels[
0]
)
;
//填充该comm的CYGNUM_COMM_IF_CH_DATA数据
CYGACC_COMM_IF_WRITE_SET(
*
comm,
cyg_hal_plf_serial_write)
;
//填充该comm的CYGNUM_COMM_IF_WRITE写函数地址
CYGACC_COMM_IF_READ_SET(
*
comm,
cyg_hal_plf_serial_read)
;
CYGACC_COMM_IF_PUTC_SET(
*
comm,
cyg_hal_plf_serial_putc)
;
CYGACC_COMM_IF_GETC_SET(
*
comm,
cyg_hal_plf_serial_getc)
;
CYGACC_COMM_IF_CONTROL_SET(
*
comm,
cyg_hal_plf_serial_control)
;
CYGACC_COMM_IF_DBG_ISR_SET(
*
comm,
cyg_hal_plf_serial_isr)
;
CYGACC_COMM_IF_GETC_TIMEOUT_SET(
*
comm,
cyg_hal_plf_serial_getc_timeout)
;
// Restore original console
CYGACC_CALL_IF_SET_CONSOLE_COMM(
cur)
;
}
cyg_start
=
=
>
packages/
redboot/
v2_0/
src/
main.
c|
202|
CYGACC_CALL_IF_SET_CONSOLE_COMM(
CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL)
;
至于CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL这个默认值是由cdl配置的:
packages/
hal/
arm/
arm9/
ep93xx/
v2_0/
cdl/
hal_arm_arm9_ep93xx.
cdl|
273|
cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL {
display "Debug serial port"
active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE
flavor data
legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-
1
default_value 0
//默认为0,这就表示CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);
//就是CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
description "
The ep93xx board has three serial ports. This option
chooses which port will be used to connect to a host
running GDB."
}
packages/
hal/
arm/
arch/
v2_0/
src/
vectors.
S|
430|
bl hal_hardware_init
packages/
hal/
arm/
arm9/
var/
v2_0/
src/
arm9_misc.
c|
74|
hal_if_init(
)
;
packages/
hal/
common/
v2_0/
src/
hal_if.
c|
663|
externC void
cyg_hal_plf_comms_init(
void
)
;
packages/
hal/
common/
v2_0/
src/
hal_if.
c|
925|
cyg_hal_plf_comms_init(
)
;
ackages/
hal/
arm/
arm9/
ep93xx/
v2_0/
src/
hal_diag.
c|
374|
cyg_hal_plf_comms_init(
void
)
flash_init
=
=
>
flash_hwr_init
=
=
>
code_len =
(
unsigned
long
)
&
flash_query_end -
(
unsigned
long
)
&
flash_query;
=
=
>
packages/
devs/
flash/
intel/
strata/
v2_0/
cdl/
flash_strata.
cdl|
113|
echo " .globl flash_query_end"
>
>
flash_query.
s
packages/
devs/
flash/
intel/
strata/
v2_0/
cdl/
flash_strata.
cdl|
114|
echo "flash_query_end:"
>
>
flash_query.
s
luther@gliethttp:
/
vobs/
tmp/
ep9312$ vim .
/
devs/
flash/
intel/
strata/
v2_0/
flash_query.
s
.
file
"flash_query.c"
.
text
.
align 2
.
global flash_query
.
type flash_query,
function //flash_query这个global的类型为function函数
flash_query:
@ args =
0,
pretend =
0,
frame =
0
@ frame_needed =
0,
uses_anonymous_args =
0
str lr,
[
sp,
#
-
4]
!
mov ip,
r0
mrc p15,
0,
r3,
c1,
c0,
0;
mov r3,
r3,
lsr #
2
ands lr,
r3,
#
1
beq .
L3
mov r2,
#
0;
1:
mov r3,
#
0;
2:
orr r0,
r2,
r3;
mcr p15,
0,
r0,
c7,
c14,
2;
add r3,
r3,
#
32;
cmp r3,
#
256;
bne 2b;
add r2,
r2,
#
0x04000000;
cmp r2,
#
0;
bne 1b;
mcr p15,
0,
r0,
c7,
c10,
4;
mrc p15,
0,
r1,
c1,
c0,
0;
bic r1,
r1,
#
0x000C;
mcr p15,
0,
r1,
c1,
c0,
0;
mov r1,
#
0;
mcr p15,
0,
r1,
c7,
c6,
0
.
L3:
mov r3,
#
9961472
add r3,
r3,
#
152
mov r1,
#
1610612736
str r3,
[
r1,
#
0]
mov r3,
#
199680
mov r2,
#
52
add r3,
r3,
#
320
.
L10:
sub r3,
r3,
#
1
cmp r3,
#
0
bgt .
L10
cmp r2,
#
0
ble .
L21
.
L15:
ldr r3,
[
r1]
,
#
4
sub r2,
r2,
#
1
cmp r2,
#
0
strb r3,
[
ip]
,
#
1
bgt .
L15
.
L21:
mov r3,
#
16711680
add r3,
r3,
#
255
cmp lr,
#
0
str r3,
[
r1,
#
0]
beq .
L16
mrc p15,
0,
r1,
c1,
c0,
0;
orr r1,
r1,
#
0x000F;
mcr p15,
0,
r1,
c1,
c0,
0
.
L16:
mov r0,
#
0
ldr pc,
[
sp]
,
#
4
.
Lfe1:
.
size flash_query,
.
Lfe1-
flash_query
.
ident "GCC: (GNU) 3.2.1"
.
text
.
globl flash_query_end
flash_query_end:
luther@gliethttp:
/
vobs/
tmp/
ep9312$ find
.
-
name '*.o'
.
/
hal/
arm/
arm9/
var/
v2_0/
src/
hal_arm_arm9_var_arm9_misc.
o
.
/
hal/
arm/
arm9/
ep93xx/
v2_0/
src/
hal_arm_arm9_ep93xx_hal_diag.
o
.
/
hal/
arm/
arm9/
ep93xx/
v2_0/
src/
hal_arm_arm9_ep93xx_ep93xx_misc.
o
.
/
hal/
arm/
arch/
v2_0/
src/
hal_arm_arch_hal_syscall.
o
.
/
hal/
arm/
arch/
v2_0/
src/
hal_arm_arch_hal_misc.
o
.
/
hal/
arm/
arch/
v2_0/
src/
hal_arm_arch_arm_stub.
o
.
/
hal/
arm/
arch/
v2_0/
src/
hal_arm_arch_redboot_linux_exec.
o
.
/
hal/
arm/
arch/
v2_0/
src/
hal_arm_arch_context.
o
.
/
hal/
common/
v2_0/
src/
hal_common_drv_api.
o
.
/
hal/
common/
v2_0/
src/
hal_common_hal_if.
o
.
/
hal/
common/
v2_0/
src/
hal_common_dummy.
o
.
/
hal/
common/
v2_0/
src/
hal_common_dbg-
threads-
syscall.
o
.
/
hal/
common/
v2_0/
src/
hal_common_bplist-
dynamic.
o
.
/
hal/
common/
v2_0/
src/
hal_common_hal_stub.
o
.
/
hal/
common/
v2_0/
src/
hal_common_hal_misc.
o
.
/
hal/
common/
v2_0/
src/
hal_common_thread-
packets.
o
.
/
hal/
common/
v2_0/
src/
hal_common_generic-
stub.
o
.
/
devs/
eth/
arm/
ep93xx/
v2_0/
src/
devs_eth_arm_ep93xx_if_ep93xx.
o
.
/
devs/
flash/
intel/
strata/
v2_0/
flash_query.
o //可见flash使用的是intel/strata存储器
.
/
devs/
flash/
intel/
strata/
v2_0/
src/
devs_flash_intel_strata_strata.
o
.
/
devs/
flash/
intel/
strata/
v2_0/
flash_erase_block.
o
.
/
devs/
flash/
intel/
strata/
v2_0/
flash_program_buf.
o
.
/
services/
crc/
v2_0/
src/
services_crc_crc16.
o
.
/
services/
crc/
v2_0/
src/
services_crc_posix_crc.
o
.
/
services/
crc/
v2_0/
src/
services_crc_crc32.
o
.
/
redboot/
v2_0/
src/
redboot_parse.
o
.
/
redboot/
v2_0/
src/
redboot_xyzModem.
o
.
/
redboot/
v2_0/
src/
redboot_alias.
o
.
/
redboot/
v2_0/
src/
redboot_mfill.
o
.
/
redboot/
v2_0/
src/
redboot_dump.
o
.
/
redboot/
v2_0/
src/
net/
redboot_tcp.
o
.
/
redboot/
v2_0/
src/
net/
redboot_net_io.
o
.
/
redboot/
v2_0/
src/
net/
redboot_arp.
o
.
/
redboot/
v2_0/
src/
net/
redboot_inet_addr.
o
.
/
redboot/
v2_0/
src/
net/
redboot_udp.
o
.
/
redboot/
v2_0/
src/
net/
redboot_dns.
o
.
/
redboot/
v2_0/
src/
net/
redboot_timers.
o
.
/
redboot/
v2_0/
src/
net/
redboot_cksum.
o
.
/
redboot/
v2_0/
src/
net/
redboot_ping.
o
.
/
redboot/
v2_0/
src/
net/
redboot_tftp_client.
o
.
/
redboot/
v2_0/
src/
net/
redboot_pktbuf.
o
.
/
redboot/
v2_0/
src/
net/
redboot_enet.
o
.
/
redboot/
v2_0/
src/
net/
redboot_icmp.
o
.
/
redboot/
v2_0/
src/
net/
redboot_ip.
o
.
/
redboot/
v2_0/
src/
net/
redboot_http_client.
o
.
/
redboot/
v2_0/
src/
net/
redboot_bootp.
o
.
/
redboot/
v2_0/
src/
redboot_cksum.
o
.
/
redboot/
v2_0/
src/
redboot_main.
o
.
/
redboot/
v2_0/
src/
redboot_flash.
o
.
/
redboot/
v2_0/
src/
redboot_io.
o
.
/
redboot/
v2_0/
src/
redboot_caches.
o
.
/
redboot/
v2_0/
src/
redboot_mcmp.
o
.
/
redboot/
v2_0/
src/
redboot_load.
o
.
/
redboot/
v2_0/
src/
redboot_syscall.
o
.
/
redboot/
v2_0/
src/
redboot_ticks.
o
.
/
redboot/
v2_0/
src/
redboot_misc_funs.
o
.
/
infra/
v2_0/
src/
infra_memcpy.
o
.
/
infra/
v2_0/
src/
infra_simple.
o
.
/
infra/
v2_0/
src/
infra_abort.
o
.
/
infra/
v2_0/
src/
infra_fancy.
o
.
/
infra/
v2_0/
src/
infra_userstart.
o
.
/
infra/
v2_0/
src/
infra_dummyxxmain.
o
.
/
infra/
v2_0/
src/
infra_pkgstart.
o
.
/
infra/
v2_0/
src/
infra_tcdiag.
o
.
/
infra/
v2_0/
src/
infra_null.
o
.
/
infra/
v2_0/
src/
infra_diag.
o
.
/
infra/
v2_0/
src/
infra_pure.
o
.
/
infra/
v2_0/
src/
infra_memset.
o
.
/
infra/
v2_0/
src/
infra_startup.
o
.
/
infra/
v2_0/
src/
infra_eprintf.
o
.
/
infra/
v2_0/
src/
infra_delete.
o
.
/
infra/
v2_0/
src/
infra_prestart.
o
.
/
infra/
v2_0/
src/
infra_buffer.
o
.
/
io/
eth/
v2_0/
src/
stand_alone/
io_eth_eth_drv.
o
.
/
io/
flash/
v2_0/
src/
io_flash_flash.
o
.
/
install/
lib/
vectors.
o
.
/
install/
lib/
extras.
o
.
/
install/
lib/
version.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strcoll.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_memchr.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strsuppt.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strlen.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strncat.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strcpy.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strtok.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strspn.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strxfrm.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strcmp.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strcspn.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strncmp.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strrchr.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_memmove.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strcat.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strstr.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strchr.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strpbrk.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_strncpy.
o
.
/
language/
c/
libc/
string
/
v2_0/
src/
language_c_libc_string_memcmp.
o
来看看存储到flash中的script脚本是怎么被读出来执行的:
packages/
redboot/
v2_0/
src/
main.
c
=
=
>
cyg_start
=
=
>
for
(
init_entry =
__RedBoot_INIT_TAB__;
init_entry !
=
&
__RedBoot_INIT_TAB_END__;
init_entry+
+
)
{
(
*
init_entry-
>
fun)
(
)
;
//do_flash_init
//load_flash_config
//net_init
}
=
=
>
(
*
init_entry-
>
fun)
(
)
将执行load_flash_config
=
=
>
config =
(
struct
_config *
)
(
workspace_end-
sizeof
(
struct
_config)
)
;
从workspace的末尾获得一篇内存
cfg_base =
(
void
*
)
(
(
CYG_ADDRESS)
flash_end +
1 -
_rup(
_rup(
(
-
CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*
flash_block_size)
,
cfg_size)
,
flash_block_size)
)
;
//从flash末尾分配一个CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK个block,
//packages/redboot/v2_0/cdl/redboot.cdl|611| cdl_option CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK {定义的数值为-2
//install/include/pkgconf/redboot.h|55| #define CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK -2
//对于我的intel/strata类型flash
//flash_start=0x60000000
//flash_end=0x61ffffff
//flash_block_size=0x40000
//所以0x62000000 - 2*0x40000 = 0x61f80000
//cfg_base=0x61f80000
=
=
>
memcpy
(
config,
cfg_base,
sizeof
(
struct
_config)
)
;
//将flash中的数据拷贝到SDRAM中
=
=
>
flash_get_config(
"boot_script"
,
&
use_boot_script,
CONFIG_BOOL)
;
if
(
use_boot_script)
{
//使用script启动
flash_get_config(
"boot_script_data"
,
&
script,
CONFIG_SCRIPT)
;
//获得启动script内容
flash_get_config(
"boot_script_timeout"
,
&
script_timeout,
CONFIG_INT)
;
//获取超时时间
}
=
=
>
最后cyg_start进入下面的while(
true
)
循环
while
(
true
)
{
if
(
prompt)
{
diag_printf(
"RedBoot > "
)
;
prompt =
false
;
}
res =
_rb_gets(
line
,
sizeof
(
line
)
,
CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT)
;
//如果script存在,那么从script读取一行数据
//否则从串口读取数据.
expand_aliases(
line
,
sizeof
(
line
)
)
;
//如果输入的数据line存在别名之类,那么展开别名,替换成真实的内容.
command =
(
char
*
)
&
line
;
if
(
(
cmd =
parse(
&
command,
&
argc,
&
argv[
0]
)
)
!
=
(
struct
cmd *
)
0)
{
//解析command,上面有对parse函数的分析
//parse==>return cmd_search(__RedBoot_CMD_TAB__, &__RedBoot_CMD_TAB_END__, argv[0]);
//遍历__RedBoot_CMD_TAB__指向section为.ecos.table的存储节中的所有handler处理函数
(
cmd-
>
fun)
(
argc,
argv)
;
}
}
//获取一行执行命令[从串口或者script]
=
=
>
_rb_gets
=
=
>
_rb_gets_preloaded
=
=
>
char
*
ip =
buf;
while
(
true
)
{
#
ifdef
CYGFUN_REDBOOT_BOOT_SCRIPT
if
(
getc_script(
&
c)
)
//从script读取一个字节数据
do_idle(
false
)
;
/*
void
do_idle(bool is_idle)
{
struct idle_tab_entry *idle_entry;
for (idle_entry = __RedBoot_IDLE_TAB__;
idle_entry != &__RedBoot_IDLE_TAB_END__; idle_entry++) {
(*idle_entry->fun)(is_idle);//执行定义的idle函数
}
}
*/
else
#
endif
从物理串口读取数据
.
.
.
switch
(
c)
{
case
CTRL(
'P'
)
:
.
.
.
break
;
case
CTRL(
'C'
)
:
// ^C
.
.
.
break
;
case
'/n'
:
case
'/r'
:
.
.
.
//回显回车、换行
if
(
console_echo)
{
mon_write_char(
'/r'
)
;
mon_write_char(
'/n'
)
;
}
return
_GETS_OK;
default
:
if
(
console_echo)
{
mon_write_char(
c)
;
//回显从script读取到的一个字节数据
}
*
ip+
+
=
c;
//将读到一个字节数据存储到buffer输出缓冲区.
.
.
.
}
=
=
>
getc_script
=
=
>
while
(
script &
&
*
script)
{
.
.
.
.
*
cp =
*
script+
+
;
if
(
*
cp =
=
'/n'
)
{
newline =
true
;
}
else
{
newline =
false
;
}
return
true
;
}
根据下面的script内容
config_script[
boot_script_data]
=
.
.
fis load ramdisk
.
.
fis load zImage
.
.
exec -
r 0x800000 -
s 0x60000
我们可以看到diag_printf(
"RedBoot > "
)
;
将执行3次,
每次都从script中读取一行数据,
所以
我们见到的log将如下:
RedBoot >
fis load ramdisk
RedBoot >
fis load zImage
RedBoot >
exec -
r 0x800000 -
s 0x60000
Using
base address 0x00080000 and
length 0x000c938c
Uncompressing Linux.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
done,
booting the kernel.
Please press Enter to activate this
console.
我的flash中的配置数据:
all configs:
config_bool[
boot_script]
=
1
config_script[
boot_script_data]
=
.
.
fis load ramdisk
.
.
fis load zImage
.
.
exec -
r 0x800000 -
s 0x600000
config_int[
boot_script_timeout]
=
0x3
config_bool[
bootp]
=
0
config_ip[
bootp_my_gateway_ip]
=
0x100a8c0
config_ip[
bootp_my_ip]
=
0x6400a8c0
config_ip[
bootp_my_ip_mask]
=
0xffffff
config_ip[
bootp_server_ip]
=
0x200a8c0
config_ip[
dns_ip]
=
0x100a8c0
config_int[
gdb_port]
=
0x2328
config_bool[
info_console_force]
=
0
config_int[
info_console_number]
=
0x0
config_bool[
net_debug]
=
0
其打印源码如下:
#
if
1 &
&
1
{
unsigned
char
*
dp;
void
*
val_ptr;
int
len;
unsigned
long
val;
diag_printf(
"all configs:/n"
)
;
dp =
&
config-
>
config_data[
0]
;
while
(
dp <
&
config-
>
config_data[
sizeof
(
config-
>
config_data)
]
)
{
val_ptr =
(
void
*
)
CONFIG_OBJECT_VALUE(
dp)
;
switch
(
CONFIG_OBJECT_TYPE(
dp)
)
{
// Note: the data may be unaligned in the configuration data
case
CONFIG_BOOL:
val =
0;
memcpy
(
&
val,
val_ptr,
sizeof
(
bool
)
)
;
diag_printf(
"config_bool[%s]=%d/n"
,
CONFIG_OBJECT_KEY(
dp)
,
val)
;
break
;
case
CONFIG_INT:
memcpy
(
&
val,
val_ptr,
sizeof
(
unsigned
long
)
)
;
diag_printf(
"config_int[%s]=0x%x/n"
,
CONFIG_OBJECT_KEY(
dp)
,
val)
;
break
;
#
ifdef
CYGPKG_REDBOOT_NETWORKING
case
CONFIG_IP:
memcpy
(
&
val,
val_ptr,
sizeof
(
in_addr_t)
)
;
diag_printf(
"config_ip[%s]=0x%x/n"
,
CONFIG_OBJECT_KEY(
dp)
,
val)
;
break
;
case
CONFIG_ESA:
//memcpy(val, val_ptr, sizeof(enet_addr_t));
break
;
#
endif
case
CONFIG_STRING:
// Just return a pointer to the script/line
//*(unsigned char **)val = (unsigned char *)val_ptr;
diag_printf(
"config_string[%s]=%s/n"
,
CONFIG_OBJECT_KEY(
dp)
,
(
char
*
)
val_ptr)
;
break
;
case
CONFIG_SCRIPT:
{
char
*
sp,
*
lp;
diag_printf(
"config_script[%s]=/n"
,
CONFIG_OBJECT_KEY(
dp)
)
;
sp =
lp =
(
unsigned
char
*
)
val_ptr;
while
(
*
sp)
{
while
(
*
lp !
=
'/n'
)
lp+
+
;
*
lp =
'/0'
;
diag_printf(
".. %s/n"
,
sp)
;
*
lp+
+
=
'/n'
;
sp =
lp;
}
}
break
;
}
len =
4 +
CONFIG_OBJECT_KEYLEN(
dp)
+
CONFIG_OBJECT_ENABLE_KEYLEN(
dp)
+
config_length(
CONFIG_OBJECT_TYPE(
dp)
)
;
dp +
=
len;
}
}
diag_printf(
"done!/n"
)
;
#
endif
|