UBOOT的命令体系分析

命令体系基本概述:

  1. uboot启动后进入命令行模式,即可输入命令
  2. uboot会进行命令接收,命令解析,命令执行操作
  3. uboot的命令体系实现代码在uboot/common/cmd_xx.c中(command.c 和main.c也和命令相关)
  4. 每个命令都对应一个函数
  5. 有些命令支持传参(和main参数传参差不多),使用argc&argv传递,比如" print ipaddr "会以argc(2),argv(argv[0] = print,argv[1] = ipaddr)传递给命令函数

命令体系解析:

main_loop函数:
在uboot启动第二阶段结束后,会进入main_loop函数进行死循环

		/* main_loop() can return to retry autoboot, if so just run it again. */
		for (;;) {
			main_loop ();
		}

main_loop函数执行一次,就是一个获取,解析,执行命令的过程(main_loop应该是一个阻塞式函数)

run_command函数
在main_loop函数里解析之后用run_command函数执行命令

  • 调用parse_line函数将命令分解,比如" print ipaddr "分成argv[0] = print,argv[1] = ipaddr
  • 然后调用find_cmd(argv[0])函数去uboot的命令集合当中搜索有没有argv[0]这个命令,找到后find_cmd函数返回函数指针
  • 执行命令

命令的可能管理方式:

  1. 数组(结构体数组,每个结构体中存放命令的各种信息),最简单的实现方式,但是增减不便
  2. 链表,链表的每个节点data段放一个结构体存放命令信息,但是占空间大,算法稍麻烦
  3. uboot使用另一种方式,
    (1)使用结构体保存命令的各种信息
    (2)命令结构体全部放在用户自定义段(给命令附加特殊的段属性,就像.bss段,.data段),链接时将带有该段属性的内容链接在一起排列
    (3)uboot重定位时将该段整体加载到DDR中。加载到DDR中的uboot镜像中带有特定段属性的这一段其实就是命令结构体的集合,有点像一个命令结构体数组
    (4)段的起始和结束地址决定了命令集的范围(在链接脚本u-boot.lds里面定义),如下图:
	__u_boot_cmd_start = .;
	.u_boot_cmd : { *(.u_boot_cmd) }
	__u_boot_cmd_end = .;

具体分析:

命令结构体cmd_tbl_t:

struct cmd_tbl_s {
	char		*name;		/* Command Name			*/
	int		maxargs;	/* maximum number of arguments	*/
	int		repeatable;	/* autorepeat allowed?		*/
					/* Implementation function	*/
	int		(*cmd)(struct cmd_tbl_s *, int, int, char *[]);
	char		*usage;		/* Usage message	(short)	*/
#ifdef	CFG_LONGHELP
	char		*help;		/* Help  message	(long)	*/
#endif
#ifdef CONFIG_AUTO_COMPLETE
	/* do auto completion on the arguments */
	int		(*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};

定义了命令的具体信息:

  1. name 名称
  2. maxargs 可接收的最大参数个数
  3. repeatable 是否可重复执行,重复执行是uboot命令行的一种工作机制,就是直接按回车则执行上一条执行的命令
  4. cmd,函数指针,指向这个命令的具体实施函数
  5. usage:命令的短帮助信息。对命令的简单描述
  6. help:命令的长帮助信息。细节的帮助信息
  7. complete:函数指针,指向这个命令的自动补全的函数
    总结:uboot的命令体系在工作时,一个命令对应一个cmd_tbl_t结构体的一个实例,然后uboot支持多少个命令,就需要多少个结构体实例。uboot的命令体系把这些结构体实例管理起来,当用户输入了一个命令时,uboot会去这些结构体实例中查找(查找方法和存储管理的方法有关)。如果找到则执行命令,如果未找到则提示命令未知。

分析一个命令:
version命令,执行结果如下:
在这里插入图片描述
执行后打印uboot版本信息。

下面是命令的执行函数和相关宏:

int
do_version (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	extern char version_string[];
	printf ("\n%s\n", version_string);
	return 0;
}

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

U_BOOT_CMD宏分析:
每个命令函数都带有一个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}

#define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))
  • ##name是指将传进来的name参数替换##name
  • Struct_Section 宏是附加链接属性用的

version命令的U_BOOT_CMD

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"))) = {#name, maxargs, rep, cmd, usage, help}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值