嵌入式开发——uboot中命令执行函数(main_loop函数)

1、main_loop()函数源码

从uboot中摘抄的部分main_loop函数,为了便于理解,函数只保留了主线部分代码,一些用宏定义控制的代码被删除掉了。

void main_loop (void)
	{
    
    
		static char lastcommand[CFG_CBSIZE] = {
    
     0, };
		int len;
		int rc = 1;
		int flag;

	#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) //是否有bootdelay
		char *s;
		int bootdelay;
	#endif

	#ifdef CONFIG_BOOTCOUNT_LIMIT //启动次数的限制
		unsigned long bootcount = 0;
		unsigned long bootlimit = 0;
		char *bcs;
		char bcs_set[16];
	#endif /* CONFIG_BOOTCOUNT_LIMIT */

	#ifdef CONFIG_BOOTCOUNT_LIMIT
		bootcount = bootcount_load();//读取已经启动的次数
		bootcount++;
		bootcount_store (bootcount);//将启动次数加1再写回去保存起来
		sprintf (bcs_set, "%lu", bootcount);
		setenv ("bootcount", bcs_set); //设置已经启动的次数到环境变量bootcount
		bcs = getenv ("bootlimit");//从环境变量获取启动次数的上限,此时返回的是字符串还需要转换成整数
		bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0;
	#endif /* CONFIG_BOOTCOUNT_LIMIT */

	#ifdef CONFIG_VERSION_VARIABLE	//设置ver环境变量,里面保存的是uboot的版本
		{
    
    
			extern char version_string[];

			setenv ("ver", version_string);  /* set version variable */
		}
	#endif /* CONFIG_VERSION_VARIABLE */

	#ifdef CONFIG_AUTO_COMPLETE //命令的自动补全功能
		install_auto_complete();
	#endif

	#ifdef CONFIG_FASTBOOT//支持fastboot刷机
		if (fastboot_preboot())
			run_command("fastboot", 0);
	#endif

	/* 下面就是实现uboot启动延时机制bootdelay的代码 */
	#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
		s = getenv ("bootdelay"); /* 从环境变量获取启动延时的秒数 */
		bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

		debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);

	/* 检查启动次数是否超过上限*/
	#ifdef CONFIG_BOOTCOUNT_LIMIT
		if (bootlimit && (bootcount > bootlimit)) {
    
    
			printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
					(unsigned)bootlimit);
			s = getenv ("altbootcmd");
		}
		else
	#endif /* CONFIG_BOOTCOUNT_LIMIT */
			s = getenv ("bootcmd"); /* 从环境变量获取启动内核的命令 */

		debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");

		/*abortboot函数是检测在bootdelay时间内是否有人按键:如果有人按键则返回1;
			超过bootdelay的时间没有人按键则返回0,if条件满足则启动内核*/
		if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
    
    
	#ifdef CONFIG_AUTOBOOT_KEYED
			int prev = disable_ctrlc(1);	/* 禁止 ctrl+c 功能 */
	#endif
			run_command (s, 0);	//启动内核

	#ifdef CONFIG_AUTOBOOT_KEYED
			disable_ctrlc(prev);	/* 恢复 ctrl+c 功能 */
	#endif
		}

	#endif	/* CONFIG_BOOTDELAY */

		/*
		 * 下面是一个死循环,不停的从控制台读取命令解析,直到执行bootm命令去启动内核
		 */
		for (;;) {
    
    
			len = readline (CFG_PROMPT); //从控制台读取一行指令,存放在console_buffer

			flag = 0;	/* assume no special flags for now */
			if (len > 0)
				strcpy (lastcommand, console_buffer);
			else if (len == 0)
				flag |= CMD_FLAG_REPEAT;

			if (len == -1)
				puts ("<INTERRUPT>\n");
			else
				rc = run_command (lastcommand, flag); //解析并运行读取到的指令

			if (rc <= 0) {
    
    
				/* invalid command or not repeatable, forget it */
				lastcommand[0] = 0;
			}
		}
	}

2、abortboot函数

该函数的传参是bootdelay,函数内部会不停的去检测当前是否有按键被按下,如果有则返回1,超时则返回0。

3、readline函数

该函数是从控制台读取一行数据,也就是从串口读取,但是有控制台实现了行缓冲。

4、run_command函数

以输入"setenv bootdelay 5"为例。
传参是readline读取到的指令;内部parse_line函数先进行字符处理,解析成argc=3, argv[0]=setenv ,argv[1]=bootdelay, argv[0]=5;cmdtp = find_cmd(argv[0])去查找当前是否有该命令,如果找到会返回该命令的结构体;执行命令:(cmdtp->cmd) (cmdtp, flag, argc, argv)

Guess you like

Origin blog.csdn.net/weixin_42031299/article/details/121239386