uboot学习之命令体系

一、uboot的命令体系基础

1、uboot命令体系的实现在uboot/common/cmd_xxx.c中,有若干个.c文件,还包括common.c和main.c文件,

2、每一个命令对应着一个函数,但是也不是完全对应的:

  • 一个函数对应着一个命令或者多个命令,
  • 找到命令对应的函数,对应着关系;
  • 以argc和argv的方式,进行传参;

二、uboot的命令解析和执行过程分析

1、从main-lopp说起

(1)main_loop函数,在board.c中的start_armboot函数中,是uboot进入命令行的函数。这个函数的主要作用就是获取从命令输入的命令,然后解析命令(命令是否存在,命令参数是否正确),执行命令。

2、run_command函数

(1)函数的功能:用来执行从命令行传递进来的参数

(2)parse_line()把传递的命令进行分割,例如输入的命令为“md 0x30000000 10”,通过这个函数把这个字符串解析成argv[0] = md,argv[1] = 0x30000000,argv[2] = 10。

(3)find_cmd()函数是查找命令,是否在uboot的命令集中,如果找到则返回这个命令所对应的结构体指针,没有找到则返回NULL。

(4)如果找到,find_cmd函数则会返回一个命令结构体,通过命令结构体中的函数指针,执行相应的的命令函数。

 

三、uboot如何处理命令集

1、可能的管理方式

在uboot拥有很多的命令,那么uboot怎么管理这些命令,通过什么方式呢?

(1)数组的方式,通过建立一个命令结构体的数组来管理命令集。

(2)通过链表的方式来管理命令集。

(3)第三种方式?

2、uboot管理命令集的方式,既不是数组也不是链表。

命令结构体,uboot通过一个命令结构体来管理命令,一个命令结构体变量对应着一个命令,类似于高级语言中的类和对象的关系。结构体类型就是类,变量就是对象。

struct cmd_tbl_s {
	char		*name;	//命令的名字
	int		maxargs;	//命令所带的最大参数个数
	int		repeatable;	//是否可重复,也就是enter键,重复上一个指令。
	int		(*cmd)(struct cmd_tbl_s *, int, int, char *[]); //命令函数
	char		*usage;  //命令的短帮助
#ifdef	CFG_LONGHELP
	char		*help;		//命令的长帮助
#endif
#ifdef CONFIG_AUTO_COMPLETE  //自动补全功能
	int		(*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};

typedef struct cmd_tbl_s	cmd_tbl_t;

所以常见一个命令,就需要实例化这么一个对象即可。

 

3、uboot实现命令管理的思路,即uboot的命令集在哪,怎么找?

 给命令结构体的对象添加特定的段属性(用户自定义段),链接的时候将带有该段属性的内容链接在一起排列,所以各个命令之间是连续排列的,类似与数组的在内存中的存储方式,但是顺序不同于数组那么固定,每个位置的命令都是不能够确定的。

uboot重定位的时候,将该段整体加载到DDR中,加载到DDR中的uboot镜像中,带有特定段属性的这一段就是命令结构体集合。

段起始地址和结束地址,在链接脚本中都用指定,这样我们就可以得到命令结合的起始地址和结束地址了。便于我们访问命令集。

 

四、uboot如何实现命令集

1、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}

总的来说,这个宏就是定义了一个cmd_tbl_t 结构体类型的变量,变量的名字,以及给这个结构体变量赋值。

 

这里以version命令为代表解释:

U_BOOT_CMD(
	version,	1,		1,	do_version,
	"version - print monitor version\n",
	NULL
);

这句宏定义的执行结果定义了一个结构体变量:

cmd_tbl_t __u_boot_cmd_version __attribute__ ((unused,section (".u_boot_cmd"))) = 
{
	"version",
	1,
	1,
	do_version,
	"version - print monitor version\n",
	NULL,
};
  • ##name就替换成了version
  • #name这个#的作用,就是将version变成了字符串"version"。
  • Struct_Section是__attribute__ ((unused,section (".u_boot_cmd"))),也就是在这里指定段属性,表示是一个命令,在链接的时候都放在一起。

 

五、如何添加自己的命令,在command.c中添加

1、创建命令对应的宏

U_BOOT_CMD(
	mycmd,	1,	1,	do_mycmd,
	"mycmd    - mycmd usage\n",
	"mycmd help\n"
);

2、创建命令处理函数

int
do_mycmd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	printf("this is mycmd");
	return 0;
}

其实就是按照原有的命令实现方式,进行移植就可以了。

 

总结:可见uboot这种处理命令集的方式,我们添加或者删除一个命令都非常的方面,只需要建立一个结构体对象,和创建一个对应的命令函数即可,其他的完全不用顾虑。不用像使用数组那样担心越界,不用向使用链表那样麻烦,我很欣赏这种方式,感觉很好。第一次见到这样的实现方式。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值