2.8.uboot源码分析4-uboot的命令体系(2021-5-8)


2.8.1、uboot命令体系基础

2.8.1.1、使用uboot命令

在这里插入图片描述

x210 # help tftp
tftpboot [loadAddress] [[hostIPaddr:]bootfilename]

x210 # help ping
ping pingAddress

2.8.1.2、uboot命令体系实现代码在哪里

在这里插入图片描述

2.8.1.3、每个命令对应一个函数

在这里插入图片描述

2.8.1.4、命令参数以argc&argv传给函数

在这里插入图片描述

//Command.h
/*
 * Monitor Command Table 监控命令表
 * uboot命令表结构体
 */
//定义了一个命令表结构体,里面包含
//命令名字、接收参数个数、是否可重复执行、命令所对应的函数指针、
//短帮助信息、长帮助信息、命令自动补全函数
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
};
//Command.c
/*
 * Use puts() instead of printf() to avoid printf buffer overflow
 * for long help messages
 * 用puts()代替printf(),以避免长帮助消息的printf缓冲区溢出
 */
/*
 * 函数功能:对应命令help背后的函数,实现help功能
 *
 * 参数:
 * cmd_tbl_t * cmdtp:命令结构体指针
 * int flag:标志
 * int argc:输入的参数
 * char *argv[]:输入的字符
 * 
 * 返回值:
 */
int do_help (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	int i;
	int rcode = 0;

	if (argc == 1) {	/*show list of commands 显示命令列表*/  //仅仅只有命令,没有参数
	
		//uboot中命令总个数,当只有一个help命令时,需要打印所有的命令
		int cmd_items = &__u_boot_cmd_end -             
				&__u_boot_cmd_start;	     /* pointer arith! 指针*/
		//定义了一个指针数组,其是一个数组,数组中存放的元素时指针,该指针指向的为命令结构体
		cmd_tbl_t *cmd_array[cmd_items];   
		int i, j, swaps;

		/* Make array of commands from .uboot_cmd section */
		//从创建命令数组。uboot_cmd部分
		cmdtp = &__u_boot_cmd_start;        //cmdtp中记录uboot中命令的起始地址

		//利用for循环,依次将uboot中所有命令表结构体复制到结构体指针数组
		for (i = 0; i < cmd_items; i++) {
			cmd_array[i] = cmdtp++;
		}

		/* Sort command list (trivial bubble sort) 排序命令列表(普通气泡排序)*/
		//按照命令的名字进行冒泡排序
		for (i = cmd_items - 1; i > 0; --i) {
			swaps = 0;
			for (j = 0; j < i; ++j) {
				if (strcmp (cmd_array[j]->name,
					    cmd_array[j + 1]->name) > 0) {
					cmd_tbl_t *tmp;
					tmp = cmd_array[j];
					cmd_array[j] = cmd_array[j + 1];
					cmd_array[j + 1] = tmp;
					++swaps;
				}
			}
			if (!swaps)           //swaps:交换次数为0;跳出死循环
				break;
		}

		/* print short help (usage) 打印简短帮助(用法)*/
		for (i = 0; i < cmd_items; i++) {
			//const char *usage:usage是一个字符指针,usage本身可以改变,但是其指向的字符不可以改变
			const char *usage = cmd_array[i]->usage;

			/* allow user abort 允许用户中止*/
			if (ctrlc ())
				return 1;
			if (usage == NULL)
				continue;          //结束本次循环执行下一循环
			puts (usage);
		}
		return 0;
	}
	/*
	 * command help (long version)
	 * 命令帮助(长版本)
	 * 此时输入的命令参数大于1
	 */
	 //argc大于1,输入了多少个命令。就执行多少次循环
	for (i = 1; i < argc; ++i) {                          
		if ((cmdtp = find_cmd (argv[i])) != NULL) {   //如果查找到命令。将此命令的地址复制给cmdtp
#ifdef	CFG_LONGHELP                                   //CFG_LONGHELP:定义,可以打印长帮主信息
			/* found - print (long) help info */
			//找到-打印(长)帮助信息
			puts (cmdtp->name);          //打印命令
			putc (' ');                  //空格              
			if (cmdtp->help) {
				puts (cmdtp->help);      //打印长帮助信息
			} else {
				puts ("- No help available.\n");
				rcode = 1;
			}
			putc ('\n');                 //换行符
#else	/* no long help available 不再有帮助*/
			if (cmdtp->usage)
				puts (cmdtp->usage);
#endif	/* CFG_LONGHELP */
		} else {
			printf ("Unknown command '%s' - try 'help'"
				" without arguments for list of all"
				" known commands\n\n", argv[i]
					);
			rcode = 1;
		}
	}
	return rcode;
}
/* Sort command list (trivial bubble sort) 排序命令列表(普通气泡排序)*/
		//按照命令的名字进行冒泡排序
		for (i = cmd_items - 1; i > 0; --i) {
			swaps = 0;
			for (j = 0; j < i; ++j) {
				if (strcmp (cmd_array[j]->name,
					    cmd_array[j + 1]->name) > 0) {
					cmd_tbl_t *tmp;
					tmp = cmd_array[j];
					cmd_array[j] = cmd_array[j + 1];
					cmd_array[j + 1] = tmp;
					++swaps;
				}
			}
			if (!swaps)           //swaps:交换次数为0;跳出死循环
				break;
		}

在这里插入图片描述


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

2.8.2.1、从main_loop说起

在这里插入图片描述

//Board.c
	/* main_loop() can return to retry autoboot, if so just run it again. */
	//main_loop()可以返回重试自动启动,如果是这样,就再次运行它
	for (;;) {           //死循环
		main_loop ();    //接收命令、解析命令、执行命令的死循环

2.8.2.2、run_command函数详解

/****************************************************************************
 * returns:
 *	1  - command executed, repeatable
 *	0  - command executed but not repeatable, interrupted commands are
 *	     always considered not repeatable
 *	-1 - not executed (unrecognized, bootd recursion or too many args)
 *           (If cmd is NULL or "" or longer than CFG_CBSIZE-1 it is
 *           considered unrecognized)
 *
 * WARNING:
 *
 * We must create a temporary copy of the command since the command we get
 * may be the result from getenv(), which returns a pointer directly to
 * the environment data, which may change magicly when the command we run
 * creates or modifies environment variables (like "bootp" does).
 */
/****************************************************************************
 * 返回值:
 * 1-执行命令,可重复
 * 0-已执行但不可重复的命令,中断的命令总是被认为不可重复
 * -1-未执行(无法识别、bootd递归或参数太多)(如果cmd为空或""或长于CFG_CBSIZE-1,则视为无法识别)
 *
 * 警告:
 *
 * 我们必须创建该命令的临时副本,因为我们得到的命令可能是getenv()的结果,它直接返回一
 * 个指向环境数据的指针,当我们运行的命令创建或修改环境变量时(就像“bootp”所做的那样),环境数据可能会发生变化。
 */

 //run_command函数就是用来执行命令的函数。
int run_command (const char *cmd, int flag)
{
	cmd_tbl_t *cmdtp;
	char cmdbuf[CFG_CBSIZE];	/* working copy of cmd	(cmd的工作副本)*/
	char *token;			/* start of token in cmdbuf(cmdbuf中令牌的开始)	*/
	char *sep;			/* end of token (separator) in cmdbuf (cmdbuf中的标记结束(分隔符))*/
	char finaltoken[CFG_CBSIZE];
	char *str = cmdbuf;         //命令缓冲区指针
	char *argv[CFG_MAXARGS + 1];	/* NULL terminated	空终止*/
	int argc, inquotes;
	int repeatable = 1;
	int rc = 0;

#ifdef DEBUG_PARSER
	printf ("[RUN_COMMAND] cmd[%p]=\"", cmd);
	puts (cmd ? cmd : "NULL");	/* use puts - string may be loooong */
	puts ("\"\n");
#endif

	clear_ctrlc();		/* forget any previous Control C 忘记任何以前的控制C*/

	if (!cmd || !*cmd) {                     //命令为空
		return -1;	/* empty command 空命令*/
	}

	if (strlen(cmd) >= CFG_CBSIZE) {        //命令太长或者参数过多
		puts ("## Command too long!\n");
		return -1;
	}

	strcpy (cmdbuf, cmd);     //strcpy把含有'\0'结束符的字符串复制到另一个地址空间,返回值的类型为char*

	/* Process separators and check for invalid
	 * repeatable commands
	 * 处理分隔符并检查无效的可重复命令
	 */

#ifdef DEBUG_PARSER
	printf ("[PROCESS_SEPARATORS] %s\n", cmd);
#endif
	while (*str) {        //结束标志:*str为空时

		/*
		 * Find separator, or string end
		 * Allow simple escape of ';' by writing "\;"
		 * 查找分隔符或字符串结尾允许简单转义“;”通过书写“\”;
		 */
		for (inquotes = 0, sep = str; *sep; sep++) {
			if ((*sep=='\'') &&
			    (*(sep-1) != '\\'))
				inquotes=!inquotes;

			if (!inquotes &&
			    (*sep == ';') &&	/* separator		分隔符*/
			    ( sep != str) &&	/* past string start	(过去字符串开始)*/
			    (*(sep-1) != '\\'))	/* and NOT escaped	*/
				break;
		}

		/*
		 * Limit the token to data between separators
		 * 将标记限制为分隔符之间的数据
		 */
		token = str;
		if (*sep) {
					str = sep + 1;	/* start of command for next pass */
			*sep = '\0';
		}
		else
			str = sep;	/* no more commands for next pass */
#ifdef DEBUG_PARSER
		printf ("token: \"%s\"\n", token);
#endif

		/* find macros in this token and replace them */
		process_macros (token, finaltoken);

		/* Extract arguments */
		//parse_line函数把"md 30000000 10"解析成argv[0]=md, argv[1]=30000000 argv[2]=10;
		if ((argc = parse_line (finaltoken, argv)) == 0) {
			rc = -1;	/* no command at all */
			continue;
		}

		/* Look up command in command table */
		//命令集中查找命令。
		//find_cmd(argv[0])函数去uboot的命令集合当中搜索有没有argv[0]这个命令,
		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;
		}
		/* found - check max args */
		if (argc > cmdtp->maxargs) {
			printf ("Usage:\n%s\n", cmdtp->usage);
			rc = -1;
			continue;
		}

在这里插入图片描述

/***************************************************************************
 * find command table entry for a command
 * 查找命令的命令表条目
 */
//命令集中查找命令。
//find_cmd(argv[0])函数去uboot的命令集合当中搜索有没有argv[0]这个命令,
cmd_tbl_t *find_cmd (const char *cmd)
{
	cmd_tbl_t *cmdtp;       //命令结构体指针
	//__u_boot_cmd_start:此在链接脚本定义,其代表命令集的首地址
	//cmdtp_temp:此指针指向了命令集的首地址,类型为cmd_tbl_t
	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.
	 * 有些命令允许长度修饰符(如“CP . b”);仅比较命令名,直到第一个点。
	 */
	 //strchr(cmd, '.')),可以查找字符串s中首次出现字符.的位置
	 //返回首次出现c的位置的指针,返回的地址是字符串在内存中随机分配的地址再加上你所搜索的字符在字符串位置,
	 //如果s中不存在c则返回NULL。
	 //如果p==NULL,则命令中没有.,len为cmd的长度
	 //如果p!=NULL,则命令中有.,len为p - cmd
	len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd); 

	for (cmdtp = &__u_boot_cmd_start;
	     cmdtp != &__u_boot_cmd_end;
	     cmdtp++) {
		 //int strncmp(stringstr1,charstr2,intlen)
		 //功 能:比较字符串的前N个字符
		 // 如果两个字符串相等的话,strcnmp将返回0。
		 //cmd:参数
		if (strncmp (cmd, cmdtp->name, len) == 0) {
			if (len == strlen (cmdtp->name))          //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 */
}

2.8.2.3、关键点分析

在这里插入图片描述

//Main.c
		/* Extract arguments 提取参数*/
		//parse_line函数把"md 30000000 10"解析成argv[0]=md, argv[1]=30000000 argv[2]=10;
		if ((argc = parse_line (finaltoken, argv)) == 0) {
			rc = -1;	/* no command at all */
			continue;
		}

/****************************************************************************/
/* Extract arguments 提取参数*/
//parse_line函数把"md 30000000 10"解析成argv[0]=md, argv[1]=30000000 argv[2]=10;
int parse_line (char *line, char *argv[])
{
	int nargs = 0;

#ifdef DEBUG_PARSER
	printf ("parse_line: \"%s\"\n", line);
#endif
	while (nargs < CFG_MAXARGS) {

		/* skip any white space 跳过任何空白*/ 
		//也就是跳过命令前面的空白
		while ((*line == ' ') || (*line == '\t')) {
			++line;
		}

		if (*line == '\0') {	/* end of line, no more args(行尾,没有参数)	*/
			argv[nargs] = NULL;
#ifdef DEBUG_PARSER
		printf ("parse_line: nargs=%d\n", nargs);
#endif
			return (nargs);
		}

		argv[nargs++] = line;	/* begin of argument string	(参数字符串的开头)*/

		/* find end of string(查找字符串的结尾) */
		while (*line && (*line != ' ') && (*line != '\t')) {
			++line;
		}

		if (*line == '\0') {	/* end of line, no more args	*/
			argv[nargs] = NULL;
#ifdef DEBUG_PARSER
		printf ("parse_line: nargs=%d\n", nargs);
#endif
			return (nargs);
		}

		*line++ = '\0';		/* terminate current arg	 */
	}

	printf ("** Too many args (max. %d) **\n", CFG_MAXARGS);

#ifdef DEBUG_PARSER
	printf ("parse_line: nargs=%d\n", nargs);
#endif
	return (nargs);
}

/****************************************************************************/

在这里插入图片描述

//Main.c
/* Look up command in command table */
		//命令集中查找命令。
		//find_cmd(argv[0])函数去uboot的命令集合当中搜索有没有argv[0]这个命令,
		if ((cmdtp = find_cmd(argv[0])) == NULL) {
			printf ("Unknown command '%s' - try 'help'\n", argv[0]);
			rc = -1;	/* give up after bad command */
			continue;
		}
//Comm

and.c
/***************************************************************************
 * find command table entry for a command
 * 查找命令的命令表条目
 */
//命令集中查找命令。
//find_cmd(argv[0])函数去uboot的命令集合当中搜索有没有argv[0]这个命令,
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.
	 * 有些命令允许长度修饰符(如“CP . b”);仅比较命令名,直到第一个点。
	 */
	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 */
}

在这里插入图片描述

		/* OK - call function to do the command (确定-调用函数执行命令)*/
		if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
			rc = -1;
		}
/*


 * Monitor Command Table
 */

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
};

在这里插入图片描述


2.8.3、uboot如何处理命令集1

2.8.3.1、可能的管理方式

在这里插入图片描述

2.8.3.2、命令结构体cmd_tbl_t

在这里插入图片描述
在这里插入图片描述

/*
 * Monitor Command Table 监控命令表
 * uboot命令表结构体
 */
//定义了一个命令表结构体,里面包含
//命令名字、接收参数个数、是否可重复执行、命令所对应的函数指针、
//短帮助信息、长帮助信息、命令自动补全函数
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
};

2.8.3.3、uboot实现命令管理的思路

在这里插入图片描述


2.8.4、uboot如何处理命令集2

2.8.4.1、uboot命令定义具体实现分析

在这里插入图片描述

//Command.h
//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:命令结构体类型
//__u_boot_cmd_##name:结构体变量的名字
//##:在gcc中是一种扩展语法,连字符。这里面的name就是传参的第一个name,其将会被括号里面的#name替换
//#define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))
//__attribute__:属性,给其贴标签,所谓的段
//.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}
//链接脚本
	__u_boot_cmd_start = .;
	.u_boot_cmd : { *(.u_boot_cmd) }  //自定义数据段段
	__u_boot_cmd_end = .;

2.8.4.2、find_cmd函数详解

在这里插入图片描述

/***************************************************************************
 * find command table entry for a command
 * 查找命令的命令表条目
 */
//命令集中查找命令。
//find_cmd(argv[0])函数去uboot的命令集合当中搜索有没有argv[0]这个命令,
cmd_tbl_t *find_cmd (const char *cmd)
{
	cmd_tbl_t *cmdtp;
	//__u_boot_cmd_start:此在链接脚本定义,其代表命令集的首地址
	//cmdtp_temp:此指针指向了命令集的首地址,类型为cmd_tbl_t
	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.
	 * 有些命令允许长度修饰符(如“CP . b”);仅比较命令名,直到第一个点。
	 */
	 //strchr(cmd, '.')),可以查找字符串s中首次出现字符.的位置
	 //返回首次出现c的位置的指针,返回的地址是字符串在内存中随机分配的地址再加上你所搜索的字符在字符串位置,
	 //如果s中不存在c则返回NULL。
	 //如果p==NULL,则命令中没有.,len为cmd的长度
	 //如果p!=NULL,则命令中有.,len为p - cmd
	len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd); 

	for (cmdtp = &__u_boot_cmd_start;
	     cmdtp != &__u_boot_cmd_end;
	     cmdtp++) {
		 //int strncmp(stringstr1,charstr2,intlen)
		 //功 能:比较字符串的前N个字符
		 // 如果两个字符串相等的话,strcnmp将返回0。
		 //cmd:参数
		if (strncmp (cmd, cmdtp->name, len) == 0) {
			if (len == strlen (cmdtp->name))          //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 */
}

2.8.4.3、U_BOOT_CMD宏详解

在这里插入图片描述

2.8.4.4、命令举例:version命令


2.8.5、uboot中增加自定义命令

2.8.5.1、在已有的c文件中直接添加命令

在这里插入图片描述

//command.c在此目录下
root@xfj-virtual-machine:~/x210v3_bsp/uboot/common# pwd
/root/x210v3_bsp/uboot/common
//xfj添加mycmd
//开始
int
do_mycmd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
        printf ("\n%s\n", "this is a test for add cmd to uboot.");
        return 0;
}

U_BOOT_CMD(
        mycmd,        1,              1,      do_mycmd,
        "mycmd - usage of my cmd\n",
        "long help of mycmd\n"
);

//结束
//烧录
//1.插上SD卡
//2.可移动设备--链接
//3.
root@xfj-virtual-machine:~/x210v3_bsp/uboot# ls /dev/sdb
//4.
root@xfj-virtual-machine:~/x210v3_bsp/uboot# cd sd_fusing/
root@xfj-virtual-machine:~/x210v3_bsp/uboot/sd_fusing# ls
C110-EVT1-mkbl1.c  c110.signedBL1_bin  Makefile  mkbl1  sd_fdisk  sd_fdisk.c  sd_fusing2.sh  sd_fusing.sh
root@xfj-virtual-machine:~/x210v3_bsp/uboot/sd_fusing# ./sd_fusing.sh /dev/sdb


//徐富军添加mycmd
//开始
int
do_mycmd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
        int i = 0;

        printf ("\n%s\n", "this is a test for add cmd to uboot.");

        printf( "argc = %d\n", argc );
        for( i=0; i < argc; i++ )
        {
                printf( "argv[%d] = %s\n", i, argv[i] );
        
        }
        return 0;
}

U_BOOT_CMD(
        mycmd,        3,              1,      do_mycmd,
        "mycmd - usage of my cmd\n",
        "long help of mycmd\n"
);
//结束

2.8.5.2、自建一个c文件并添加命令

在这里插入图片描述

//1.
root@xfj-virtual-machine:~/x210v3_bsp/uboot/common# pwd
/root/x210v3_bsp/uboot/common
//2.
root@xfj-virtual-machine:~/x210v3_bsp/uboot/common# touch cmd_aston.c


#include <common.h>           //头文件一定要包含
#include <command.h>



//徐富军添加aston
//开始
int
do_aston (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
        int i = 0;

        printf ("\n%s\n", "this is a test for add cmd to uboot.");

        printf( "argc = %d\n", argc );
        for( i=0; i < argc; i++ )
        {
                printf( "argv[%d] = %s\n", i, argv[i] );

        }
        return 0;
}

U_BOOT_CMD(
        aston,        3,              1,      do_aston,
        "aston - usage of my aston\n",
        "long help of aston\n"
);
//结束

在这里插入图片描述

root@xfj-virtual-machine:~/x210v3_bsp/uboot/common# pwd
/root/x210v3_bsp/uboot/common
root@xfj-virtual-machine:~/x210v3_bsp/uboot/common# vim Makefile 

COBJS-y += aston.o
//CONFIG_CMD_AMBAPP:若被定义了,则添加;否则不添加
COBJS-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o

在这里插入图片描述

2.8.5.3、体会:uboot命令体系的优点

在这里插入图片描述


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
所有资料来网上,与朋友分享 u-boot-1.1.6之cpu/arm920t/start.s分析 2 u-boot中.lds连接脚本文件的分析 12 分享一篇我总结的uboot学习笔记(转) 15 U-BOOT内存布局及启动过程浅析 22 u-boot中的命令实现 25 U-BOOT环境变量实现 28 1.相关文件 28 2.数据结构 28 3.ENV 的初始化 30 3.1env_init 30 3.2 env_relocate 30 3.3*env_relocate_spec 31 4. ENV 的保存 31 U-Boot环境变量 32 u-boot代码链接的问题 35 ldr和adr在使用标号表达式作为操作数的区别 40 start_armboot浅析 42 1.全局数据结构的初始化 42 2.调用通用初始化函数 43 3.初始化具体设备 44 4.初始化环境变量 44 5.进入主循环 44 u-boot编译过程 44 mkconfig文件的分析 47 从NAND闪存中启动U-BOOT的设计 50 引言 50 NAND闪存工作原理 51 从NAND闪存启动U-BOOT的设计思路 51 具体设计 51 支持NAND闪存的启动程序设计 51 支持U-BOOT命令设计 52 结语 53 参考文献 53 U-boot给kernel传参数和kernel读取参数—struct tag (以及补充) 53 1 、u-boot 给kernel 传RAM 参数 54 2 、Kernel 读取U-boot 传递的相关参数 56 3 、关于U-boot 中的bd 和gd 59 U-BOOT分析及移植 60 一、u-boot工程的总体结构: 61 1、代码组织 61 2.makefile简要分析 61 3、u-boot的通用目录是怎么做到与平台无关的? 63 4、smkd2410其余重要的文件 : 63 二、u-boot的流程、主要的数据结构、内存分配 64 1、u-boot的启动流程: 64 2、u-boot主要的数据结构 66 3、u-boot重定位后的内存分布: 68 三、u-boot的重要细节 。 68 关于U-boot中命令相关的编程 : 73 四、U-boot在ST2410的移植,基于NOR FLASH和NAND FLASH启动。 76 1、从smdk2410到ST2410: 76 2、移植过程: 76 3、移植要考虑的问题: 77 4、SST39VF1601: 77 5、我实现的flash.c主要部分: 78 6、增加从Nand 启动的代码 : 82 7、添加网络命令。 87

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值