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
5argc=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
35static 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_CMD
或SHELL_ARG_CMD
组成的,并由SHELL_SUBCMD_SET_END
结束。
注册命令
1 | SHELL_CMD_REGISTER(syntax, subcmd, help, handler) |
syntax – [in] 命令符号
subcmd – [in] 指向子命令,为空表示没有子命令。
help – [in] 命令帮助信息。
handler – [in] 命令函数,,为空表示没有命令函数。
实例:这里使用上面三个宏注册命令
1 | /* SHELL_CMD 注册两个子命令, board和version,执行时会调用cmd_info_board和cmd_info_version函数 |
执行命令
上面实例中注册了根命令 shell_sample 和其子命令集subinfo,其命令为树机构1
2
3shell_sample
├── board
└── version
在shell中可以执行的命令如下:
执行shell_sample 会调用cmd_shell_help
显示出帮助信息和参数个数
执行shell_sample board 会调用cmd_info_board
显示出开发板的字符串
执行shell_sample version 会调用cmd_info_version
显示zephyr的版本
命令参数
使用SHELL_CMD_REGISTER
和SHELL_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系统都会创建argc
和argv
并交由注册的命令函数处理。但由SHELL_CMD_ARG
定义的命令会指定必选参数数量mandatory
和可选参数数量optional
,实际通过shell命令输入的参数数量(包含命令本身)要满足:
1 | mandatory <= argc <= mandatory + optional |
当不满足时,shell系统会检查参数数量出来并做如下提示
1 | shell_sample_args: wrong parameter count |
当mandatory
和optional
均被设置为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