?
里面会调用一个initcall_run_list(init_sequence_f)函数,而init_sequence_r是个函数指针数组,里面存了大量需要依次初始化执行的函数。
?
里面也会调用一个initcall_run_list(init_sequence_r)函数,而init_sequence_r是个函数指针数组,里面存了大量需要依次初始化执行的函数。
示例代码 32.2.8.2 board_r.c 代码段
1 init_fnc_t init_sequence_r[] = {
2 initr_trace,
3 initr_reloc,
4 initr_caches,
5 initr_reloc_global_data,
6 initr_barrier,
7 initr_malloc,
8 initr_console_record,
9 bootstage_relocate,
10 initr_bootstage,
11 board_init, /* Setup chipselects */
12 stdio_init_tables,
13 initr_serial,
。。。。。。
38 initr_net,
39 INIT_FUNC_WATCHDOG_RESET
40 run_main_loop,? ? ? ? //里面是个无限循环,会不断检测是否有输入命令,以及倒计时
41 };
?
run_main_loop->main_loop,里面会循环调用两函数:
?
命令的定义如下:以dhcp命令为例,
U_BOOT_CMD(
dhcp, 3, 1, do_dhcp,
"boot image via network using DHCP/TFTP protocol",
"[loadAddress] [[hostIPaddr:]bootfilename]"
);
将其展开,对应一个命令结构体,结果如下:
30 struct cmd_tbl_s {
31 char *name; /* Command Name */
32 int maxargs; /* maximum number of arguments */
33 int repeatable; /* autorepeat allowed? */
34 /* Implementation function */
35 int (*cmd)(struct cmd_tbl_s *, int, int, char * const []);
36 char *usage; ?/* Usage message (short) */
37 #ifdef CONFIG_SYS_LONGHELP
38 char *help; /* Help message (long) */
39 #endif
40 #ifdef CONFIG_AUTO_COMPLETE
41 /* do auto completion on the arguments */
42 int (*complete)(int argc, char * const argv[], char
last_char, int maxv, char *cmdv[]);
43 #endif
44 };
?
命令对应赋值后,结果如下:
_u_boot_list_2_cmd_2_dhcp.name = "dhcp"
_u_boot_list_2_cmd_2_dhcp.maxargs = 3
_u_boot_list_2_cmd_2_dhcp.repeatable = 1
_u_boot_list_2_cmd_2_dhcp.cmd = do_dhcp
_u_boot_list_2_cmd_2_dhcp.usage = "boot image via network using DHCP/TFTP protocol"
_u_boot_list_2_cmd_2_dhcp.help = "[loadAddress] [[hostIPaddr:]bootfilename]"
_u_boot_list_2_cmd_2_dhcp.complete = NULL
当我们在 uboot 的命令行中输入“dhcp”这个命令的时候,最终执行的是 do_dhcp 这个函
数(因此,自己想做一个命令行解释器,没必要搞这么复杂这么绕(uboot为了做得通用,所以非常绕,条件编译和各种判断非常多),因为最终就是为了执行do_xx函数嘛,自己直接执行就行了)。总结一下,uboot 中使用 U_BOOT_CMD 来定义一个命令,最终的目的就是为了定义一个
cmd_tbl_t 类型的变量,并初始化这个变量的各个成员。uboot 中的每个命令都存储在.u_boot_list
段中,每个命令都有一个名为 do_xxx(xxx 为具体的命令名)的函数,这个 do_xxx 函数就是具体
的命令处理函数。
?
?
DDR 最高地址为 0X80000000+0X20000000(512MB)=0XA0000000
注:一个程序通过链接地址,能知道自己的起始地址(这是自己设计好的),那怎么知道自己的结束地址呢?
答:就是通过链接脚本里的自己定义标识符,比如__image_copy_end,那gcc编译完后会给这个标识符赋值,我们在程序里访问这个标识符就可以了。
?
原文:https://blog.51cto.com/u_13682052/2962911