Chinaunix首页 | 论坛 | 博客

OS

  • 博客访问: 2226359
  • 博文数量: 691
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2660
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-05 12:49
个人简介

不浮躁

文章分类

全部博文(691)

文章存档

2019年(1)

2017年(12)

2016年(99)

2015年(207)

2014年(372)

分类: 嵌入式

2015-12-09 22:14:13

u-boot 中的命令实现
我们知道,u-boot的运行过程是首先进行一些初始化化工作,然后在一个死
循环中不断接收串口的命令并进行解释执行,下面我们就看看执行部分代码的实
现,见common/main.c中的run_command:

int run_command (const char *cmd, int flag)
{

while (*str) {

/* find macros in this token and replace them */
process_macros (token, finaltoken);
/* Extract arguments */
if ((argc = parse_line (finaltoken, argv)) == 0) {
rc = -1; /* no command at all */
continue;
}
/* Look up command in command table */
if ((cmdtp = find_cmd(argv[0])) == NULL) {
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
rc = -1; /* give up after bad command */
continue;
}
/* found - check max args */
if (argc > cmdtp->maxargs) {
printf ("Usage:\n%s\n", cmdtp->usage);
rc = -1;
continue;
}

/* OK - call function to do the command */
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
rc = -1;
}
repeatable &= cmdtp->repeatable;
/* Did the user stop this? */
if (had_ctrlc ())
return 0; /* if stopped then not repeatable */
}
return rc ? rc : repeatable;
}
很简单的一个过程,扩展宏定义 -> 分析命令及其参数 -> 查找命令 -> 执
行命令,有意思的地方在查找命令上(common/command.c):
cmd_tbl_t *find_cmd (const char *cmd)
{
cmd_tbl_t *cmdtp;
cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
const char *p;
int len;
int n_found = 0;
/*
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
*/
len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
for (cmdtp = &__u_boot_cmd_start;
cmdtp != &__u_boot_cmd_end;
cmdtp++) {
if (strncmp (cmd, cmdtp->name, len) == 0) {
if (len == strlen (cmdtp->name))
return cmdtp; /* full match */
cmdtp_temp = cmdtp; /* abbreviated command ? */
n_found++;
}
}
if (n_found == 1) { /* exactly one match */
return cmdtp_temp;
}
return NULL; /* not found or ambiguous command */
}

看起来还是很简单的一个过程,在一个命令数组中查找是否有指定名称的命
令。问题是,在这里使用的两个符号__u_boot_cmd_start和__u_boot_cmd_end,
在所有的C文件中都找不到它们的定义,那么它们的空间从哪里来呢?这些分散
在不同文件中的结构体又是如何能够放在同一个数组中呢?
答案就在board/bf561-ezkit/u-boot.lds.s中,这个文件其实就是一个链
接文件,类似于VDSP中的LDF文件,see see:
___u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
___u_boot_cmd_end = .;
这几句话的意思其实就是指示链接器将所有.u_boot_cmd数据段中的内容全
部放在一起,而且___u_boot_cmd_start和___u_boot_cmd_end是不会占用任何
存储空间的,它们只是用来指示地址的两个符号而已。那么数据段的定义在哪里
呢?看看U_BOOT_CMD的宏定义吧(include/command.h):
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
__attribute__ ((unused,section (".u_boot_cmd")))就指示编译器将这些用U_BOOT_CMD定
义的结构体放在.u_boot_cmd这个数据段中。
如果要在VDSP中编译u-boot,那么就需要在LDF文件中也定义这样一个数
据段:
.u_boot_cmd
{
___u_boot_cmd_start = .;
INPUT_SECTIONS(common.dlb(.u_boot_cmd) common.dlb(__u_boot_cmd))
___u_boot_cmd_end = .;
} > MEM_SDRAM_U_BOOT
不过让人郁闷的是:如果在一个定义命令的C文件中没有一个函数被其它文
件引用,VDSP在链接时将认为这是一个多余的文件,从而不会将这个文件中的
函数链接进来,当然就无法使用其中定义的这些命令,如cmd_load.c。
解决的办法可以是在这些文件中添加一个空函数,并在主函数中调用它们,
这样VDSP就会把这个文件链接进来了。

http://blog.csdn.net/lhf_tiger/article/details/8825213
阅读(1186) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~