Zephyr shell系统使用指南-添加命令

Creative Commons
本作品采用知识共享署名

本文说明如何向shell系统添加自定义命令。

Zephyr的shell系统提供一个类Unix shell界面,用户可以自定义shell命令和处理函数,通过shell界面调用这些处理函数。本文说明如何向shell系统添加自定义命令。

步骤

1. 实现命令处理函数

shell命令处理函数的参数形式是固定的

1
static int cmd_handler(const struct shell *shell, size_t argc, char **argv)

  • shell[in] shell的实例后端。

  • argc[in] 参数的个数,命令会被计入参数个数中。

  • argv[in] 参数字符串指针,所有参数都会以字符串的形式送到命令函数.

例如执行shell命令shell_sample 1 2 3,命令函数得到的参数如下:

1
2
3
4
5
argc=4
argv[0]="sample"
argv[1]="1"
argv[2]="2"
argv[3]="3"

实例:这里实现三个命令函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
static int cmd_info_board(const struct shell *sh, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);

shell_print(sh, CONFIG_BOARD);

return 0;
}

static int cmd_info_version(const struct shell *sh, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);

shell_print(sh, "Zephyr version %s", KERNEL_VERSION_STRING);

return 0;
}


static int cmd_shell_help(const struct shell *sh, size_t argc, char **argv)
{
shell_print(sh, "show help: %d", argc);
if(argc == 1){
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}

for(size_t i=0; i< argc; i++){
shell_print(sh, "check arg %d: %s", i, argv[i]);
}

return 0;
}

2.注册命令

使用下面三个宏注册静态的shell命令,一旦注册后无法在运行时修改注册的shell命令
创建命令

1
SHELL_CMD(_syntax, _subcmd, _help, _handler)

  • _syntax[in] 命令符号。

  • _subcmd[in] 指向子命令,为空表示没有子命令。子命令可以再嵌入子命令。

  • _help[in] 命令帮助信息。

  • _handler[in] 命令函数,,为空表示没有命令函数。

创建子命令集

1
SHELL_STATIC_SUBCMD_SET_CREATE(name, ...)
  • name[in] 子命令集名.

  • [in] 由多个SHELL_CMDSHELL_ARG_CMD组成的,并由SHELL_SUBCMD_SET_END结束。

注册命令

1
SHELL_CMD_REGISTER(syntax, subcmd, help, handler)
  • syntax[in] 命令符号

  • subcmd[in] 指向子命令,为空表示没有子命令。

  • help[in] 命令帮助信息。

  • handler[in] 命令函数,,为空表示没有命令函数。

实例:这里使用上面三个宏注册命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* SHELL_CMD 注册两个子命令, board和version,执行时会调用cmd_info_board和cmd_info_version函数
SHELL_STATIC_SUBCMD_SET_CREATE 将子命令组装成子命令集subinfo
SHELL_SUBCMD_SET_END表示子命令集的结束
*/
SHELL_STATIC_SUBCMD_SET_CREATE(subinfo,
SHELL_CMD(board, NULL, "Show board command.", cmd_info_board),
SHELL_CMD(version, NULL, "Show info command.", cmd_info_version),
SHELL_SUBCMD_SET_END /* Array terminated. */
);

/* 注册一个根命令shell_sample,执行根命令shell_sample时会调用cmd_shell_help
shell_sample的子命令集为
*/
SHELL_CMD_REGISTER(shell_sample, &subinfo, "Sample commands", cmd_shell_help);

执行命令

上面实例中注册了根命令 shell_sample 和其子命令集subinfo,其命令为树机构

1
2
3
shell_sample
├── board
└── version

在shell中可以执行的命令如下:
执行shell_sample 会调用cmd_shell_help显示出帮助信息和参数个数
执行shell_sample board 会调用cmd_info_board显示出开发板的字符串
执行shell_sample version 会调用cmd_info_version显示zephyr的版本

命令参数

使用SHELL_CMD_REGISTERSHELL_CMD注册的命令,shell系统并不会为其检查参数个数。zephyr提供了另外两个宏注册命令,在注册时可以指定参数个数。在执行shell命令时shell系统会根据指定的参数个数进行检查,如果不匹配将不执行命令函数,并进行错误提示。
创建带参数命令

1
SHELL_CMD_ARG(syntax, subcmd, help, handler, mand, opt)
  • syntax[in] 命令符号。

  • subcmd[in] 指向子命令,为空表示没有子命令。子命令可以再嵌入子命令。

  • help[in] Pointer to a command help string.

  • handler[in] 命令帮助信息。

  • mand[in] 必选参数个数,参数个数包含命令本身。

  • opt[in] 可选参数个数。

1
SHELL_CMD_ARG_REGISTER(syntax, subcmd, help, handler, mandatory, optional)
  • syntax[in] 命令符号

  • subcmd[in] 指向子命令,为空表示没有子命令。

  • help[in] 命令帮助信息。

  • handler[in] 命令函数,,为空表示没有命令函数。

  • mandatory[in] 必选参数个数,参数个数包含命令本身。

  • optional[in] 可选参数个数。

注意无论由那种方式定义的shell命令,shell系统都会创建argcargv并交由注册的命令函数处理。但由SHELL_CMD_ARG定义的命令会指定必选参数数量mandatory和可选参数数量optional,实际通过shell命令输入的参数数量(包含命令本身)要满足:

1
mandatory <= argc <= mandatory + optional

当不满足时,shell系统会检查参数数量出来并做如下提示

1
shell_sample_args: wrong parameter count

mandatoryoptional均被设置为0时,Shell系统不会对参数数量进行检查。
以下实例

1
SHELL_CMD_ARG_REGISTER(shell_sample_args, NULL, "Sample arg commands with handle", cmd_shell_help, 3, 4);

表示shell_sample_args必须有3个参数(包含shell_sample_args),但总计不能超过7个,例如
shell_sample_args 0 非法
shell_sample_args 0 1 合法
shell_sample_args 0 1 2 3 合法
shell_sample_args 0 1 2 3 4 5 6 非法

参考

https://docs.zephyrproject.org/latest/services/shell/index.html