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