基于STM32简易命令行实现

本文介绍了如何基于STM32实现一个简易的命令行,通过分析u-boot命令行源码,理解参数解析和命令执行过程,然后将关键部分移植到STM32上。文中展示了命令注册方式,并提供了command.h和command.c的代码片段,实现了通过telnet的简单命令行交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于STM32简易命令行实现

Hi,long time no see.停更了很久了,这要也是因为工作上的变动,已经有一段时间没有碰32了。我看了一下原子的usmart以及lwip官方的shell,觉得都有一个共同点,识别了第一个命令后就开始找回调了,并没有去统计argc和argv。也有不少人来问linux应用中的main函数argc和argv是怎么来的,下面我们找份uboot源码看看做了什么事以及我们怎么搬运到32上。

  1. u-boot命令行源码分析
    首先我看一下我的版本号->/u-boot/Makefile/中
VERSION = 2012
PATCHLEVEL = 04
SUBLEVEL = 01
EXTRAVERSION =
ifneq "$(SUBLEVEL)" ""
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)

老样子,把u-boot丢进sourceinsight.打开main.c后我们发现。在进过一些列的init后,出现了

#ifdef CONFIG_PREBOOT
    if ((p = getenv ("preboot")) != NULL){
   
   
# ifdef CONFIG_AUTOBOOT_KEYED
	int prev = disable_ctrlc(1); /* disable Control C checking
# endif
	run_command(p, 0);
# ifdef CONFIG_AUTOBOOT_KEYED
  	disable_ctrlc(prev); /* restore Control C checking */
# endif
    }
#endif

我们发现在run_command之前,并没有进行run_init之类的操作,所以这个就是我们要进去的入口了。

/*
 * Run a command using the selected parser.
 *
 * @param cmd Command to run
 * @param flag Execution flags (CMD_FLAG_...)
 * @return 0 on success, or != 0 on error.
 */
int run_command(const char *cmd, int flag)
{
   
   
#ifndef CONFIG_SYS_HUSH_PARSER
	/*
  	* builtin_run_command can return 0 or 1 for success, so clean up
  	* its result.
  	*/
  	if (builtin_run_command(cmd, flag) == -1)
  	return -1return 0;
 #else
 	return parse_string_outer(cmd,
 		FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
 #endif
}

CONFIG_SYS_HUSH_PARSER 为了灵活配置环境变量,我们看上面的。

/****************************************************************************
 * 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 CONFIG_SYS_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).
 */
static int builtin_run_command(const char *cmd, int flag)
{
   
   
 	char cmdbuf[CONFIG_SYS_CBSIZE]; /* working copy of cmd  */
 	char *token;   /* start of token in cmdbuf */
 	char *sep;   /* end of token (separator) in cmdbuf */
 	char finaltoken[CONFIG_SYS_CBSIZE];
 	char *str = cmdbuf;
 	char *argv[CONFIG_SYS_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 */

	if (!cmd || !*cmd) {
   
   
	  return -1; /* empty command */
	 }
	 
	if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {
   
   
	  puts ("## Command too long!\n");
	  return -1;
	 }
	 strcpy (cmdbuf, cmd);
	/* Process separators and check for invalid
  	* repeatable commands
	*/
	#ifdef DEBUG_PARSER
 	printf ("[PROCESS_SEPARATORS] %s\n", cmd);
	#endif
	while (*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<
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值