嵌入式系统之shell

         嵌入式开发包罗万象,但是一些基本组件的设计可以让你的代码更具灵活性和可操作性,比如可以在你的系统中集成一个shell,让你可以向linux一样操作命令控制。

     shell的本质就是通过对命令行的解析实现对应功能函数的调用,一般嵌入式的输入终端大多数采用串口进行交互,下面就是一个简单的接收串口的键盘输入然后解析内置的命令,实现内置功能函数的调用,程序可以采用可配置的方式,实现命令字和功能函数指针映射,实现强大而简洁的shell功能,这种解析技巧也可以用在文本协议功能解析上,逻辑简单易于扩展,功能强大,欢迎大家交流。

核心代码如下

void shelltask(char recChar)
{
 
	  //u8 i=0,num,err;		/*i is the pointer of commandbuf */
	  int ii=0;  
	char ch;
	ii=ii;
    ch=recChar; 
		switch(ch)
		{
		case 0xd:				//enter
 	    #ifdef ShellDebug
 	    Shell_Printf("Run command\r\n");
 	    #endif
			
			if (g_Counter==0)
			{      						//commandbuf is null,begin a new line
				_log(DIRNAME);
				_log(CurDir);
				_log(">");
			}
			else{
				if(CommandBuf[g_Counter-1]==' ') 
					g_Counter--;			//get rid of the end space
				//CommandBuf[i++] = '\r';
				//CommandBuf[i++] = '\n';
				CommandBuf[g_Counter] = '\0';
				#ifdef ShellDebug

				for(ii=0;ii<g_Counter;ii++)
	       UART_Send_Byte(CommandBuf[ii]);
				Shell_Printf("\r\nexcute command i=%d\r\n",g_Counter);
				//UART_Send_Str(CommandBuf);
				Shell_Printf("\r\n%s\r\n",CommandBuf);
				
				#endif
				_log("\r\n");
				//OSSemPost(WaitSem);
			    ShellCommand(CommandBuf);
			    //OSSemPost(WaitSem);
				g_Counter = 0;
				CommandBuf[g_Counter] = '\0';
				_log("\r\n");
				_log(DIRNAME);
				_log(CurDir);
				_log(">");

			}
			break;
			
		case '\b':				//backspace
			if ( g_Counter==0 ){		//has backed to first one
				//do nothing
				
			}
			else{
				g_Counter--;			//pointer back once
				putchar('\b');		//cursor back once
				putchar(' ');	      //earse last char in screen
				putchar('\b');		//cursor back again
			}
			break;
			
		case ' ':               //don't allow continuous or begin space(' ')
			if((CommandBuf[g_Counter-1] == ' ')||(g_Counter==0)||(g_Counter>MaxLenComBuf)){
				//do nothing
			#ifdef ShellDebug
      Shell_Printf("\r\nRec %d-> %c\r\n",g_Counter,CommandBuf[g_Counter-1]);
      #endif
			}
			else
			{
				CommandBuf[g_Counter] = ch;
				g_Counter++;
				putchar(ch);  //display and store ch
			}
			break;
			
		default:				//normal key
			if (g_Counter>MaxLenComBuf){	//the buf reached MAX 
				//do nothing
			#ifdef ShellDebug
      Shell_Printf("\r\nRec %d-> %c\r\n",g_Counter,CommandBuf[g_Counter-1]);
      #endif
			}			
			else{

				CommandBuf[g_Counter] = ch;
				
				g_Counter++;
				putchar(ch);  //display and store ch
			#ifdef ShellDebug
      Shell_Printf("\r\nRec %d-> %c\r\n",g_Counter,CommandBuf[g_Counter-1]);
      #endif
			}
			break;
		}  //switch

}

SHELL_COMMAND shell_cmds[]=
{
{"help",      helpFunc,     "help       - 显示帮助"},
{"gettime",   ShowTime,     "gettime    - 显示系统时间"},
{"settime",   SetTime,      "settime    - 设置系统时间"},
//{"setport",   SetPort,      "setport    - 设置端口开关"},
//{"setimgcyc", SetImgSendCyc,"setimgcyc  - 设置图像定时周期传送参数"},
{"reset",     ResetFunc,    "reset      - 系统复位"},
{"login",     Login,        "login      - 操作用户登录"},
{"logout",    Logout,       "logout     - 操作用户退出"},
{"ver",       Vesion,       "ver        - 程序版本"},

//{"sendjpeg",  SendJpeg,     "sendjpeg   - 通过串口提取图片"},
//{"startjpeg", StartJpeg,    "startjpeg  - 开始图片采集存储"},
//{"stopjpeg",  StopJpeg,     "stopjpeg   - 停止图片采集存储"},
//{"resetsend", ResetSend,    "resetsend  - 复位文件发送任务"}
//{"setenv",    SetEnv,       "setenv     - 设置环境变量"},
//{"setdefenv", SetDefEnv,    "setdefenv  - 恢复出厂环境变量"},
//{"getenv",    GetEnv,       "getenv     - 显示环境变量"},
//{"saveenv",   SaveEnv,      "saveenv    - 保存环境变量"},
//{"resetenv",  ResetEnv,     "resetenv   - 初始化环境变量"},
//{"netstatus", NetStatus,    "netstatus  - 网络状态"},
//{"mktime",    MkTime,       "mktime     - 当前时间转时间戳"},
//{"gmtime",    GmTime,       "gmtime     - 输入时间戳转时间"},
//{"leddsp",    LedDsp,       "leddsp     - 发送文本到LED"},
//{"queryled",  QueryLedDsp,  "queryled   - 查询LED预置信息"},
//{"clrled",    ClrLedDsp,    "clrled     - LED清除预置信息"},


{NULL,NULL,NULL}
};



void print_help_on_shellcommands(pSHELL_COMMAND commands)
{
  int i = 0;
  Shell_Printf("\r\n");
  while (commands[i].cmdstr != NULL) 
  {
    //if(i%2==0)
    // Shell_Printf("%s",commands[i].cmdstrhelp);
    //else 
     Shell_Printf("    %s\r\n",commands[i].cmdstrhelp);
    
    //OSTimeDly(5);
    i++;
  }
  Shell_Printf("\r\n");
}
enum ParseState {
   PS_WHITESPACE,
   PS_TOKEN,
   PS_STRING,
   PS_SPECCHAR,
   PS_ESCAPE
};
enum ParseState stackedState1;
enum ParseState stackedState2;
enum ParseState stackedState3;
void parseargs(char *argstr,int *argc_p, char **argv)
{
  int argc = 0;
  char c;
  enum ParseState lastState = PS_WHITESPACE;
 
  #ifdef ShellDebug
    Shell_Printf("parseargs\r\n");
  #endif
  // tokenize the argstr 
  while ((c = *argstr) != 0) 
  {
    enum ParseState newState;
      
    if (lastState == PS_ESCAPE) 
    {
      newState = stackedState3;
    } 
    else if (lastState == PS_STRING) 
    {
      if (c == '"') 
      {
        newState = PS_WHITESPACE;
        *argstr = 0;
      } 
      else 
      {
        newState = PS_STRING;
      }
    } 
    else if ((c == ' ') || (c == '\t')) 
    {
      // whitespace character 
      *argstr = 0;
      newState = PS_WHITESPACE;
    } 
    else if (c == '"') 
    {
      newState = PS_STRING;
      *argstr++ = 0;
      argv[argc++] = argstr;
    } 
    else if (c == '\\') 
    {
      stackedState3 = lastState;
      newState = PS_ESCAPE;
    } 
    else 
    {
      // token 
      if (lastState == PS_WHITESPACE) 
      {
        argv[argc++] = argstr;
      }      
      newState = PS_TOKEN;
    }

    lastState = newState;
    argstr++;
  }
#ifdef ShellDebug
  if (1) 
  { 
    int i;
    Shell_Printf("parseargs: argc=%d", argc);
    for (i = 0; i < argc; i++) 
    {
      Shell_Printf("   ");
      Shell_Printf(argv[i]);
      Shell_Printf("\r\n");
    }
  }
#endif
  argv[argc] = NULL;
  if (argc_p != NULL)
    *argc_p = argc;
}



void ShellCommand(char *cmdstr)
{
    int argc;
    char *argv[128];
    argc=0;
    
    memset(argv, 0, sizeof(argv));
    #ifdef ShellDebug
    Shell_Printf("\r\nShellCommand\r\n");
    Shell_Printf(cmdstr);
    //Shell_Printf(cmdstr);
    #endif
    parseargs((char*)cmdstr,&argc, argv);
    if (argc > 0) 
    {
       execshellcmd(shell_cmds, argc, (const char **)argv);
    } 
    else 
    {
       
       print_help_on_shellcommands(shell_cmds);
    }

}
int parseshellcmd(SHELL_COMMAND *cmdlist, int argc, const char **argv)
{
   /* find the command name */
   const char *cmdname = argv[0];
   int cmdnum = 0;
   
   if (argc < 1)
      return -1;
   /* do a string compare for the first offset characters of cmdstr
      against each member of the cmdlist */
   while (cmdlist[cmdnum].cmdstr != NULL) 
   {
     if (strcmp(cmdlist[cmdnum].cmdstr, cmdname) == 0)
        return(cmdnum);
     cmdnum++;
   }
   return(-1);
}

void execshellcmd(pSHELL_COMMAND cmdlist, int argc, const char **argv)
{
   int cmdnum = parseshellcmd(cmdlist, argc, argv);

   if (1) 
   {
   #ifdef ShellDebug
      Shell_Printf("execcmd: argv[0]=%s\r\n",(char*)argv[0]);
      Shell_Printf("  argc=%d", argc);
      Shell_Printf("  cmdnum=%d", cmdnum);
      //OSTimeDlyHMSM(0,0,1,0);
   #endif
   
   }
   if (cmdnum >= 0) 
   {
      (*cmdlist[cmdnum].cmdfunc)(argc, argv);
   } 
   else if (strcmp(argv[1], "help") == 0) 
   {
      print_help_on_shellcommands(cmdlist);
   } 
   else 
   {
#if 0
      print_help_on_shellcommands(cmdlist);
#else
      /* default to the first command and insert it into the head of argv */
      int i;
      for (i = argc; i >= 0; i--) 
      {
         argv[i+1] = argv[i];
      }
      argc++;
      argv[0] = cmdlist[0].cmdstr;
      (*cmdlist[0].cmdfunc)(argc, argv);
#endif
   }
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值