uboot执行顺序main_loop

前言
uboot 如果最后走到了用户交互模式,则会循环在 main_loop 函数(位于common/main.c,main.c中的出口函数) 中

main_loop 被 start_armboot 函数调用

main_loop 流程
  • 全部流程

会解析bootdelay变量,并延时
	在延时中如果被中断,则会执行一个循环,循环中readline并执行 run_command
  	如果没被中断,会解析变量boot_cmd里面的变量,并执行

run_command
  	1/判断了长度
  	2/依据;截取字符串,得到一个一个的命令
    3/去掉宏,得到一个解析过的命令
    4/分析一个命令得到 命令名 和 参数
    5/依次将 命令名 和	结构体数组 中的结构体成员的第一个参数 name 进行比较,判断是否相等.相等说明是合法命令
    6/判断合法命令的 参数个数 是否合法
    7/调用命令
在上述序列中, 步骤 5 最难理解
命令及命令集的遍历解析
  • 结构体类型

typedef struct cmd_tbl_s	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	CONFIG_SYS_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
};

  • 结构体数组

其实步骤5中的结构体数组并没有在程序中定义.
而是依靠段的用法将这些结构体存到了指定的段中,然后在链接的时候将各个文件的这个段 连接到一个输出文件的 段中,也就是将这些结构体放到了一起,所以就像我之前说的结构体数组.


下面分为两个部分说

1/输入文件中的段
    它是用宏函数 U_BOOT_CMD(name,maxargs,rep,cmd,usage,help),宏函数的定义在include/command.h中
    
    #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}
  
    
    bootm 解析
    
    假设这个命令是bootm ,U_BOOT_CMD(bootm, 16, 1, do_bootm, “bootm--usage”, “help”)
  
    最后展开会成为这个样子
    cmd_tbl_t  __u_boot_cmd_ bootm  __attribute__ ((unused,section (".u_boot_cmd"))) = {“bootm”, 16, 1, do_bootm, “bootm--usage”}

    表示 
        定义一个结构体 变量 
        类型为  cmd_tbl_t 
        初始化为{“bootm”, 16, 1, do_bootm, “bootm--usage”}
        变量地址 在 段名 ".u_boot_cmd",而到底在段中的什么位置,依赖于链接顺序
  
  
2/输出文件中的段
 
    链接的时候会读取链接文件include/u-boot/u-boot.lds
    按照链接顺序 依次 将输入文件中的 ".u_boot_cmd" 段 放入 输出文件中的  ".u_boot_cmd" 段 
    __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
  • 结构体数组的遍历

main_loop
    readline
        run_command  // 如果 command 是 "bootm 0x30008000"
            判断了长度,截取字符串,将宏去掉,得到 "bootm"
            cmtp = find_cmd(); // 根据字符串"bootm" 对比 命令中的name成员 找到命令
            cmdtp->cmd //找到命令


cmd_tbl_t *find_cmd (const char *cmd)
{
	int len = &__u_boot_cmd_end - &__u_boot_cmd_start;
	return find_cmd_tbl(cmd, &__u_boot_cmd_start, len);
}

cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len)
{
	cmd_tbl_t *cmdtp;
	cmd_tbl_t *cmdtp_temp = table;	/*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 = table;
	     cmdtp != table + table_len;
	     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 */
}
  

----
并执行

if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
    rc = -1;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值