u-boot的main_loop解析

u-boot-1.1.6   tq2440

u-boot有两个功能: 调试功能,启动内核。

调试功能实现是通过u-boot /common下定义的大量的命令的来实现的。

用户通过u-boot命令行来告诉要输入的命令,命令行交互是通过u-boot的main_loop来实现的。接下来我们就看看main_loop是怎么实现命令行交互的吧!

将tq2440修改过的main_loop代码根据宏定义,掐头去尾后代码如下:

main_loop命令行

/common/main.c     掐头去尾后代码如下
void main_loop (void)
{
#ifndef CFG_HUSH_PARSER
  static char lastcommand[CFG_CBSIZE] = { 0, };
  int len;
  int rc = 1;
  int flag;
#endif

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

#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
  s = getenv ("bootdelay");//获得环境变量的bootdelay的值
  bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;//确定最后的bootdelay的值
  s = getenv ("bootcmd");//获得超时后u-boot自启动的命令
  if (bootdelay >= 0 && s && !abortboot (bootdelay)) //调用abortboot 倒计时计数
  {
        if (bBootFrmNORFlash())//从nor flash启动,执行menu命令,显示调试界面,用户自定义
                run_command("menu", 0);
        else                                      //从nand flash启动,执行boot_zImage命令,启动内核,用户自定义
        {	
                printf("Booting Linux ...\n");
                run_command("boot_zImage", 0);
        }
}
#endif/* CONFIG_BOOTDELAY */
//当abortboot 倒计时不为0时,按下键盘,则nand启动模式就进入命令行模式

//初始化mtd(不是很懂这个)标准的源码没有这个
#ifdef CONFIG_JFFS2_CMDLINE
extern int mtdparts_init(void);
if (!getenv("mtdparts"))
       run_command("mtdparts default", 0);
else
       mtdparts_init();
#endif
for (;;) {
          len = readline (CFG_PROMPT);//获取用户输入的内容
          flag = 0;	
          if (len > 0)
               strcpy (lastcommand, console_buffer);//将用户输入保存在lastcommand数组中
         else if (len == 0)
               flag |= CMD_FLAG_REPEAT;//用户如果只是按了回车,那么重复执行上次那个命令
         if (len == -1)
               puts ("<INTERRUPT>\n");//中断执行
         else
               rc = run_command (lastcommand, flag);//执行用户输入的命令
          if (rc <= 0)
               lastcommand[0] = 0;//无效的命令,清空lastcommand内容
      }/*end for*/
}/*end main_loop*/

abortboot 倒计时显示

/common/main.c     掐头去尾后的代码如下
static __inline__ int abortboot(int bootdelay)
{
       int abort = 0;//默认不终止倒计时
       char c;
       printf("Press any key to stop autoboot: %2d ", bootdelay);//在串口终端显示倒计时

       while ((bootdelay > 0) && (!abort)) 
       {
              int i;
              --bootdelay;//倒计时减1
              for (i=0; !abort && i<100; ++i) 
              {
                if (tstc())       //检查是否有按键输入
	        {
	          abort  = 1;	  //终止倒计时
	          bootdelay = 0;  //倒计时清零
	          (void) getc();  
	          break;          //退出for循环
	        }
	        udelay (10000);   //延时0.01s
              }/*end for*/
             printf ("\b\b\b%2d ", bootdelay);
       }/*end while*/
    }								
      putc ('\n');
      return abort;
}

readline读取用户输入

/common/main.c  掐头去尾结果
int readline (const char *const prompt)
{

        char   *p = console_buffer;   //p指向当前要输入的字符的地址
        int	n = 0;	              //n输入的字符数
        int	plen = 0;	      //使用提示符大小 smdk2410#
        int	col;	              //输入的字符显示时相对开始的偏移量
        char	c;                    //每次读到的字符
        if (prompt)
        {
               plen = strlen (prompt);
               puts (prompt);              //打印出输入提示符
        }
       col = plen;
       for (;;) {
	c = getc();      //获得输入
	switch (c) {     //特殊字符的处理
	       case '\r'://按下enter键,输入结束
	       case '\n':
	                *p = '\0';         
	                puts ("\r\n");
	                return (p - console_buffer);//返回输入的字符数
               case '\0':				
		   continue;
               case 0x03://按下ctrl+c,放弃输入
		   console_buffer[0] = '\0';  
		   return (-1);
               case 0x15://按下ctrl+u,删除输入行
		   while (col > plen){
		          puts (erase_seq);
		          --col;}
		    p = console_buffer;
		    n = 0;
		    continue;
              case 0x17://按下ctrl+w,删除输入行的一个字
		      p=delete_char(console_buffer, p, &col, &n, plen);
		      while ((n > 0) && (*p != ' ')) {
		         p=delete_char(console_buffer, p, &col, &n, plen);}
		      continue;
              case 0x08://按下ctr+h   backspace	
              case 0x7F://按下del     backspace
		      p=delete_char(console_buffer, p, &col, &n, plen);
		      continue;
              default://默认处理
		     if (n < CFG_CBSIZE-2){
                         if (c == '\t') {//按下tab键
		               puts (tab_seq+(col&07));
		               col += 8 - (col&07);} 
                         else {//可见字符处理
                               ++col; 
		               putc (c);}//屏幕回显输入的字符
		         *p++ = c;       //保存输入的字符
		          ++n; }         //字符数加1
                     else                //输入缓冲满
			putc ('\a');                
		}/*end switch*/
	}/*end for*/
}/*end readline*/
run_command执行命令( 点击访问u-boot命令实现)

/common/main.c
int run_command (const char *cmd, int flag)
{
                   cmd_tbl_t *cmdtp;
	char cmdbuf[CFG_CBSIZE];
	char *token;
	char *sep;
	char finaltoken[CFG_CBSIZE];
	char *str = cmdbuf;
	char *argv[CFG_MAXARGS + 1];
	int argc, inquotes;
	int repeatable = 1;
	int rc = 0;

	clear_ctrlc();
	if (!cmd || !*cmd)        return -1;	
	if (strlen(cmd) >= CFG_CBSIZE) {
		puts ("## Command too long!\n");
		return -1;}

	strcpy (cmdbuf, cmd);
	while (*str) {
	        for (inquotes = 0, sep = str; *sep; sep++) {
	           if ((*sep=='\'') && (*(sep-1) != '\\'))
                           inquotes=!inquotes;
                   if (!inquotes &&(*sep == ';') &&(sep != str) &&(*(sep-1) != '\\'))	
		            break;
                             }
	         token = str;
	         if (*sep)   { str = sep + 1;*sep = '\0';}
	         else
		      str = sep;	
	         if ((argc = parse_line (finaltoken, argv)) == 0) {//解析命令缓冲中的参数
		      rc = -1;	
		     continue;}
	         if ((cmdtp = find_cmd(argv[0])) == NULL) {//根据名称查找是否定义了该命令
		     printf ("Unknown command '%s' - try 'help'\n", argv[0]);
		     rc = -1;	
		     continue;}
	         if (argc > cmdtp->maxargs){
		     printf ("Usage:\n%s\n", cmdtp->usage);
		     rc = -1;
		     continue;}
		
	         if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0)//调用命令执行
		     rc = -1;
		 repeatable &= cmdtp->repeatable;
	         if (had_ctrlc ())
	             return 0;	
	}
	return rc ? rc : repeatable;
}

上面就是main_loop的大致过程了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值