uboot 命令构造宏分析

在uboot源码目录下include/command.h中定义了一系列宏来构造一个UBOOT CMD。下面结构是命令表中一条命令的组成

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 * const []);
	char		*usage;		/* Usage message	(short)	*/
#ifdef	CONFIG_SYS_LONGHELP
	char		*help;		/* Help  message	(long)	*/
#endif
#ifdef CONFIG_AUTO_COMPLETE
	/* do auto completion on the arguments */
	int		(*complete)(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
#endif
};
typedef struct cmd_tbl_s cmd_tbl_t;  //重命名
extern cmd_tbl_t  __u_boot_cmd_start;   //这是两个很重要的符号  后面会解释
extern cmd_tbl_t  __u_boot_cmd_end;
接下来是几个组合的宏定义来构造出一条命令:

#define Struct_Section  __attribute__((unused, section(".u_boot_cmd"), 	aligned(4)))

#ifdef CONFIG_AUTO_COMPLETE
# define _CMD_COMPLETE(x) x,
#else
# define _CMD_COMPLETE(x)
#endif
#ifdef CONFIG_SYS_LONGHELP
# define _CMD_HELP(x) x,
#else
# define _CMD_HELP(x)
#endif

#define U_BOOT_CMD_MKENT_COMPLETE(name,maxargs,rep,cmd,usage,help,comp) \
	{#name, maxargs, rep, cmd, usage, _CMD_HELP(help),_CMD_COMPLETE(comp)}

#define U_BOOT_CMD_MKENT(name,maxargs,rep,cmd,usage,help) \
	U_BOOT_CMD_MKENT_COMPLETE(name,maxargs,rep,cmd,usage,help,NULL)

#define U_BOOT_CMD_COMPLETE(name,maxargs,rep,cmd,usage,help,comp) \
	cmd_tbl_t __u_boot_cmd_##name Struct_Section = \
		U_BOOT_CMD_MKENT_COMPLETE(name,maxargs,rep,cmd,usage,help,comp)

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
	U_BOOT_CMD_COMPLETE(name,maxargs,rep,cmd,usage,help,NULL)
 
这样当我们在定义一条命令时就可以用最后一个用户接口宏 
U_BOOT_CMD来定义自己的命令。以uboot现有的例子来分析: 
#include <common.h>
#include <command.h>

int do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	int i;
	int putnl = 1;
......
	return 0;
}
U_BOOT_CMD(
	echo,
	CONFIG_SYS_MAXARGS,
	1,
	do_echo,
	"echo args to console",
	"[args..]\n",
	"    - echo args to console; \\c suppresses newline"
);
 

上面的宏按照顺序依次展开 最终会得到

cmd_tbl_t  __u_boot_cmd_echo  __attribute__((unused, section(".u_boot_cmd"), aligned(4)))  ={
	echo,
	CONFIG_SYS_MAXARGS,
	1,
	do_echo,
	"echo args to console",
	"[args..]\n",
	"    - echo args to console; \\c suppresses newline"
}

 这样就构造出了一条命令。然而我们发现include/command目录下有很多cmd_xxx.c文件。从文件名来看是对命令进行了分类,实际是也就是如此。那这么多文件是如何组织起来的呢? 

那就是前面提到的两个重要符号的功劳:

extern cmd_tbl_t  __u_boot_cmd_start;  //这是两个很重要的符号  后面会解释
extern cmd_tbl_t  __u_boot_cmd_end;

这两个符号在连接文件中以下面的方式使用。其含义就是将这些左右这个类型的结构化的命令链接在一个连续的段中,以方便重定向时将uboot的命令表一起搬移到内存中指定区域。

	. = ALIGN(4);
	. = .;
	__u_boot_cmd_start = .;
	.u_boot_cmd : { *(.u_boot_cmd) }
	__u_boot_cmd_end = .;

最后来看一眼command目录下的Makefile ,经便了解这些命令的使能除能配置。

include $(TOPDIR)/config.mk

LIB	= $(obj)libcommon.o

# core
COBJS-y += main.o
......
COBJS-$(CONFIG_SYS_HUSH_PARSER) += hush.o
......

# core command
COBJS-y += cmd_boot.o
COBJS-y += cmd_bootm.o
......
COBJS-y += cmd_version.o

# environment
COBJS-y += env_common.o
COBJS-$(CONFIG_ENV_IS_IN_DATAFLASH) += env_dataflash.o
......
COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o

# command
COBJS-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o
COBJS-$(CONFIG_SOURCE) += cmd_source.o
......
ifdef CONFIG_4xx
COBJS-$(CONFIG_CMD_SETGETDCR) += cmd_dcr.o
endif
ifdef CONFIG_POST
COBJS-$(CONFIG_CMD_DIAG) += cmd_diag.o
endif
COBJS-$(CONFIG_CMD_DISPLAY) += cmd_display.o
......
COBJS-$(CONFIG_CMD_FLASH) += cmd_flash.o
ifdef CONFIG_FPGA
COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o
endif
COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o
......
COBJS-$(CONFIG_CMD_OTP) += cmd_otp.o
ifdef CONFIG_PCI
COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o
endif
COBJS-y += cmd_pcmcia.o
COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o
COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o
......
COBJS-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o
ifdef CONFIG_CMD_USB
COBJS-y += cmd_usb.o
COBJS-y += usb.o
COBJS-$(CONFIG_USB_STORAGE) += usb_storage.o
endif
COBJS-$(CONFIG_VFD) += cmd_vfd.o

# others
COBJS-$(CONFIG_DDR_SPD) += ddr_spd.o
COBJS-$(CONFIG_HWCONFIG) += hwconfig.o
......

COBJS	:= $(sort $(COBJS-y))
XCOBJS	:= $(sort $(XCOBJS-y))
SRCS	:= $(COBJS:.o=.c) $(XCOBJS:.o=.c)
OBJS	:= $(addprefix $(obj),$(COBJS))
XOBJS	:= $(addprefix $(obj),$(XCOBJS))

CPPFLAGS += -I..

all:	$(LIB) $(XOBJS)

$(LIB): $(obj).depend $(OBJS)
	$(call cmd_link_o_target, $(OBJS))

$(obj)env_embedded.o: $(src)env_embedded.c $(obj)../tools/envcrc
	$(CC) $(AFLAGS) -Wa,--no-warn \
		-DENV_CRC=$(shell $(obj)../tools/envcrc) \
		-c -o $@ $(src)env_embedded.c

$(obj)../tools/envcrc:
	$(MAKE) -C ../tools

#########################################################################

# defines $(obj).depend target
include $(SRCTREE)/rules.mk

sinclude $(obj).depend

#########################################################################

可以使用 COBJS-y += cmd_usr.o方式或是条件编译方式COBJS-$(CONFIG_CMD_USR) += cmd_usr.o 来使能命令编译。

尾巴:如果要为uboot添加自定义命令,我们最好在command目录下新建一个cmd_usr.c文件,按照上述规则来构建自己的命令。同时要修改Makefile 来使能自定义命令编译就可以了。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值