提交全部资料

This commit is contained in:
2026-03-31 15:40:09 +08:00
parent 46f0e8d6c2
commit 4d2204bf84
235 changed files with 101676 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,557 @@
/**
* @file shell.h
* @author Letter (NevermindZZT@gmail.com)
* @brief letter shell
* @version 3.0.0
* @date 2019-12-30
*
* @copyright (c) 2020 Letter
*
*/
#ifndef __SHELL_H__
#define __SHELL_H__
#include "shell_cfg.h"
#define SHELL_VERSION "3.2.4" /**< 版本号 */
/**
* @brief shell 断言
*
* @param expr 表达式
* @param action 断言失败操作
*/
#define SHELL_ASSERT(expr, action) \
if (!(expr)) { \
action; \
}
#if SHELL_USING_LOCK == 1
#define SHELL_LOCK(shell) shell->lock(shell)
#define SHELL_UNLOCK(shell) shell->unlock(shell)
#else
#define SHELL_LOCK(shell)
#define SHELL_UNLOCK(shell)
#endif /** SHELL_USING_LOCK == 1 */
/**
* @brief shell 命令权限
*
* @param permission 权限级别
*/
#define SHELL_CMD_PERMISSION(permission) \
(permission & 0x000000FF)
/**
* @brief shell 命令类型
*
* @param type 类型
*/
#define SHELL_CMD_TYPE(type) \
((type & 0x0000000F) << 8)
/**
* @brief 使能命令在未校验密码的情况下使用
*/
#define SHELL_CMD_ENABLE_UNCHECKED \
(1 << 12)
/**
* @brief 禁用返回值打印
*/
#define SHELL_CMD_DISABLE_RETURN \
(1 << 13)
/**
* @brief 只读属性(仅对变量生效)
*/
#define SHELL_CMD_READ_ONLY \
(1 << 14)
/**
* @brief 命令参数数量
*/
#define SHELL_CMD_PARAM_NUM(num) \
((num & 0x0000000F)) << 16
#ifndef SHELL_SECTION
#if defined(__CC_ARM) || defined(__CLANG_ARM)
#define SHELL_SECTION(x) __attribute__((section(x), aligned(1)))
#elif defined (__IAR_SYSTEMS_ICC__)
#define SHELL_SECTION(x) @ x
#elif defined(__GNUC__)
#define SHELL_SECTION(x) __attribute__((section(x), aligned(1)))
#else
#define SHELL_SECTION(x)
#endif
#endif
#ifndef SHELL_USED
#if defined(__CC_ARM) || defined(__CLANG_ARM)
#define SHELL_USED __attribute__((used))
#elif defined (__IAR_SYSTEMS_ICC__)
#define SHELL_USED __root
#elif defined(__GNUC__)
#define SHELL_USED __attribute__((used))
#else
#define SHELL_USED
#endif
#endif
/**
* @brief shell float型参数转换
*/
#define SHELL_PARAM_FLOAT(x) (*(float *)(&x))
/**
* @brief shell 代理函数名
*/
#define SHELL_AGENCY_FUNC_NAME(_func) agency##_func
/**
* @brief shell代理函数定义
*
* @param _func 被代理的函数
* @param ... 代理参数
*/
#define SHELL_AGENCY_FUNC(_func, ...) \
void SHELL_AGENCY_FUNC_NAME(_func)(int p1, int p2, int p3, int p4, int p5, int p6, int p7) \
{ _func(__VA_ARGS__); }
#if SHELL_USING_CMD_EXPORT == 1
/**
* @brief shell 命令定义
*
* @param _attr 命令属性
* @param _name 命令名
* @param _func 命令函数
* @param _desc 命令描述
* @param ... 其他参数
*/
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc, ...) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
SHELL_USED const ShellCommand \
shellCommand##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.cmd.name = shellCmd##_name, \
.data.cmd.function = (int (*)())_func, \
.data.cmd.desc = shellDesc##_name, \
##__VA_ARGS__ \
}
#if SHELL_USING_FUNC_SIGNATURE == 1
/**
* @brief shell 命令定义
*
* @param _attr 命令属性
* @param _name 命令名
* @param _func 命令函数
* @param _desc 命令描述
* @param _sign 命令签名
*/
#define SHELL_EXPORT_CMD_SIGN(_attr, _name, _func, _desc, _sign) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
const char shellSign##_name[] = #_sign; \
SHELL_USED const ShellCommand \
shellCommand##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.cmd.name = shellCmd##_name, \
.data.cmd.function = (int (*)())_func, \
.data.cmd.desc = shellDesc##_name, \
.data.cmd.signature = shellSign##_name \
}
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
/**
* @brief shell 代理命令定义
*
* @param _attr 命令属性
* @param _name 命令名
* @param _func 命令函数
* @param _desc 命令描述
* @param ... 代理参数
*/
#define SHELL_EXPORT_CMD_AGENCY(_attr, _name, _func, _desc, ...) \
SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \
SHELL_EXPORT_CMD(_attr, _name, SHELL_AGENCY_FUNC_NAME(_func), _desc)
/**
* @brief shell 变量定义
*
* @param _attr 变量属性
* @param _name 变量名
* @param _value 变量值
* @param _desc 变量描述
*/
#define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
SHELL_USED const ShellCommand \
shellVar##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.var.name = shellCmd##_name, \
.data.var.value = (void *)_value, \
.data.var.desc = shellDesc##_name \
}
/**
* @brief shell 用户定义
*
* @param _attr 用户属性
* @param _name 用户名
* @param _password 用户密码
* @param _desc 用户描述
*/
#define SHELL_EXPORT_USER(_attr, _name, _password, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellPassword##_name[] = #_password; \
const char shellDesc##_name[] = #_desc; \
SHELL_USED const ShellCommand \
shellUser##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \
.data.user.name = shellCmd##_name, \
.data.user.password = shellPassword##_name, \
.data.user.desc = shellDesc##_name \
}
/**
* @brief shell 按键定义
*
* @param _attr 按键属性
* @param _value 按键键值
* @param _func 按键函数
* @param _desc 按键描述
*/
#define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) \
const char shellDesc##_value[] = #_desc; \
SHELL_USED const ShellCommand \
shellKey##_value SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \
.data.key.value = _value, \
.data.key.function = (void (*)(Shell *))_func, \
.data.key.desc = shellDesc##_value \
}
/**
* @brief shell 代理按键定义
*
* @param _attr 按键属性
* @param _value 按键键值
* @param _func 按键函数
* @param _desc 按键描述
* @param ... 代理参数
*/
#define SHELL_EXPORT_KEY_AGENCY(_attr, _value, _func, _desc, ...) \
SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \
SHELL_EXPORT_KEY(_attr, _value, SHELL_AGENCY_FUNC_NAME(_func), _desc)
#if SHELL_USING_FUNC_SIGNATURE == 1
/**
* @brief shell 参数解析器定义
*
* @param _attr 参数解析器属性
* @param _type 参数解析器类型
* @param _parser 参数解析器函数
* @param _cleaner 参数清理器
*/
#define SHELL_EXPORT_PARAM_PARSER(_attr, _type, _parser, _cleaner) \
const char shellDesc##_parser[] = #_type; \
SHELL_USED const ShellCommand \
shellCommand##_parser SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
.data.paramParser.type = shellDesc##_parser, \
.data.paramParser.parser = (int (*)(char *, void **))_parser, \
.data.paramParser.cleaner = (int (*)(void *))_cleaner \
}
#endif
#else
/**
* @brief shell 命令item定义
*
* @param _attr 命令属性
* @param _name 命令名
* @param _func 命令函数
* @param _desc 命令描述
*/
#define SHELL_CMD_ITEM(_attr, _name, _func, _desc) \
{ \
.attr.value = _attr, \
.data.cmd.name = #_name, \
.data.cmd.function = (int (*)())_func, \
.data.cmd.desc = #_desc \
}
/**
* @brief shell 变量item定义
*
* @param _attr 变量属性
* @param _name 变量名
* @param _value 变量值
* @param _desc 变量描述
*/
#define SHELL_VAR_ITEM(_attr, _name, _value, _desc) \
{ \
.attr.value = _attr, \
.data.var.name = #_name, \
.data.var.value = (void *)_value, \
.data.var.desc = #_desc \
}
/**
* @brief shell 用户item定义
*
* @param _attr 用户属性
* @param _name 用户名
* @param _password 用户密码
* @param _desc 用户描述
*/
#define SHELL_USER_ITEM(_attr, _name, _password, _desc) \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \
.data.user.name = #_name, \
.data.user.password = #_password, \
.data.user.desc = #_desc \
}
/**
* @brief shell 按键item定义
*
* @param _attr 按键属性
* @param _value 按键键值
* @param _func 按键函数
* @param _desc 按键描述
*/
#define SHELL_KEY_ITEM(_attr, _value, _func, _desc) \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \
.data.key.value = _value, \
.data.key.function = (void (*)(Shell *))_func, \
.data.key.desc = #_desc \
}
#if SHELL_USING_FUNC_SIGNATURE == 1
/**
* @brief shell 参数解析器item定义
*
* @param _attr 参数解析器属性
* @param _type 参数解析器类型
* @param _parser 参数解析器函数
* @param _cleaner 参数清理器
*/
#define SHELL_PARAM_PARSER_ITEM(_attr, _type, _parser, _cleaner) \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
.data.paramParser.type = #_type, \
.data.paramParser.parser = (int (*)(char *, void **))_parser, \
.data.paramParser.cleaner = (int (*)(void *))_cleaner \
}
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc)
#if SHELL_USING_FUNC_SIGNATURE == 1
#define SHELL_EXPORT_CMD_SIGN(_attr, _name, _func, _desc, _sign)
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
#define SHELL_EXPORT_CMD_AGENCY(_attr, _name, _func, _desc, ...)
#define SHELL_EXPORT_VAR(_attr, _name, _value, _desc)
#define SHELL_EXPORT_USER(_attr, _name, _password, _desc)
#define SHELL_EXPORT_KEY(_attr, _value, _func, _desc)
#define SHELL_EXPORT_KEY_AGENCY(_attr, _name, _func, _desc, ...)
#if SHELL_USING_FUNC_SIGNATURE == 1
#define SHELL_EXPORT_PARAM_PARSER(_attr, _type, _parser, _cleaner)
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
#endif /** SHELL_USING_CMD_EXPORT == 1 */
/**
* @brief shell command类型
*/
typedef enum
{
SHELL_TYPE_CMD_MAIN = 0, /**< main形式命令 */
SHELL_TYPE_CMD_FUNC, /**< C函数形式命令 */
SHELL_TYPE_VAR_INT, /**< int型变量 */
SHELL_TYPE_VAR_SHORT, /**< short型变量 */
SHELL_TYPE_VAR_CHAR, /**< char型变量 */
SHELL_TYPE_VAR_STRING, /**< string型变量 */
SHELL_TYPE_VAR_POINT, /**< 指针型变量 */
SHELL_TYPE_VAR_NODE, /**< 节点变量 */
SHELL_TYPE_USER, /**< 用户 */
SHELL_TYPE_KEY, /**< 按键 */
#if SHELL_USING_FUNC_SIGNATURE == 1
SHELL_TYPE_PARAM_PARSER, /**< 参数解析器 */
#endif
} ShellCommandType;
/**
* @brief Shell定义
*/
typedef struct shell_def
{
struct
{
const struct shell_command *user; /**< 当前用户 */
int activeTime; /**< shell激活时间 */
char *path; /**< 当前shell路径 */
#if SHELL_USING_COMPANION == 1
struct shell_companion_object *companions; /**< 伴生对象 */
#endif
#if SHELL_KEEP_RETURN_VALUE == 1
int retVal; /**< 返回值 */
#endif
} info;
struct
{
unsigned short length; /**< 输入数据长度 */
unsigned short cursor; /**< 当前光标位置 */
char *buffer; /**< 输入缓冲 */
char *param[SHELL_PARAMETER_MAX_NUMBER]; /**< 参数 */
unsigned short bufferSize; /**< 输入缓冲大小 */
unsigned short paramCount; /**< 参数数量 */
int keyValue; /**< 输入按键键值 */
} parser;
#if SHELL_HISTORY_MAX_NUMBER > 0
struct
{
char *item[SHELL_HISTORY_MAX_NUMBER]; /**< 历史记录 */
unsigned short number; /**< 历史记录数 */
unsigned short record; /**< 当前记录位置 */
signed short offset; /**< 当前历史记录偏移 */
} history;
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
struct
{
void *base; /**< 命令表基址 */
unsigned short count; /**< 命令数量 */
} commandList;
struct
{
unsigned char isChecked : 1; /**< 密码校验通过 */
unsigned char isActive : 1; /**< 当前活动Shell */
unsigned char tabFlag : 1; /**< tab标志 */
} status;
signed short (*read)(char *, unsigned short); /**< shell读函数 */
signed short (*write)(char *, unsigned short); /**< shell写函数 */
#if SHELL_USING_LOCK == 1
int (*lock)(struct shell_def *); /**< shell 加锁 */
int (*unlock)(struct shell_def *); /**< shell 解锁 */
#endif
} Shell;
/**
* @brief shell command定义
*/
typedef struct shell_command
{
union
{
struct
{
unsigned char permission : 8; /**< command权限 */
ShellCommandType type : 4; /**< command类型 */
unsigned char enableUnchecked : 1; /**< 在未校验密码的情况下可用 */
unsigned char disableReturn : 1; /**< 禁用返回值输出 */
unsigned char readOnly : 1; /**< 只读 */
unsigned char reserve : 1; /**< 保留 */
unsigned char paramNum : 4; /**< 参数数量 */
} attrs;
int value;
} attr; /**< 属性 */
union
{
struct
{
const char *name; /**< 命令名 */
int (*function)(); /**< 命令执行函数 */
const char *desc; /**< 命令描述 */
#if SHELL_USING_FUNC_SIGNATURE == 1
const char *signature; /**< 函数签名 */
#endif
} cmd; /**< 命令定义 */
struct
{
const char *name; /**< 变量名 */
void *value; /**< 变量值 */
const char *desc; /**< 变量描述 */
} var; /**< 变量定义 */
struct
{
const char *name; /**< 用户名 */
const char *password; /**< 用户密码 */
const char *desc; /**< 用户描述 */
} user; /**< 用户定义 */
struct
{
int value; /**< 按键键值 */
void (*function)(Shell *); /**< 按键执行函数 */
const char *desc; /**< 按键描述 */
} key; /**< 按键定义 */
#if SHELL_USING_FUNC_SIGNATURE == 1
struct
{
const char *type; /**< 参数类型 */
int (*parser)(char *, void **); /**< 解析函数 */
int (*cleaner)(void *); /**< 清理器 */
} paramParser; /**< 参数解析器 */
#endif
} data;
} ShellCommand;
/**
* @brief shell节点变量属性
*/
typedef struct
{
void *var; /**< 变量引用 */
int (*get)(); /**< 变量get方法 */
int (*set)(); /**< 变量set方法 */
} ShellNodeVarAttr;
#define shellSetPath(_shell, _path) (_shell)->info.path = _path
#define shellGetPath(_shell) ((_shell)->info.path)
#define shellDeInit(shell) shellRemove(shell)
void shellInit(Shell *shell, char *buffer, unsigned short size);
void shellRemove(Shell *shell);
unsigned short shellWriteString(Shell *shell, const char *string);
void shellPrint(Shell *shell, const char *fmt, ...);
void shellScan(Shell *shell, char *fmt, ...);
Shell* shellGetCurrent(void);
void shellHandler(Shell *shell, char data);
void shellWriteEndLine(Shell *shell, char *buffer, int len);
void shellTask(void *param);
int shellRun(Shell *shell, const char *cmd);
#if SHELL_USING_COMPANION == 1
/**
* @brief shell伴生对象定义
*/
typedef struct shell_companion_object
{
int id; /**< 伴生对象ID */
void *obj; /**< 伴生对象 */
struct shell_companion_object *next; /**< 下一个伴生对象 */
} ShellCompanionObj;
signed char shellCompanionAdd(Shell *shell, int id, void *object);
signed char shellCompanionDel(Shell *shell, int id);
void *shellCompanionGet(Shell *shell, int id);
#endif
#endif

View File

@@ -0,0 +1,182 @@
/**
* @file shell_cfg.h
* @author Letter (nevermindzzt@gmail.com)
* @brief shell config
* @version 3.0.0
* @date 2019-12-31
*
* @copyright (c) 2019 Letter
*
*/
#ifndef __SHELL_CFG_H__
#define __SHELL_CFG_H__
#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "portable.h"
#define SHELL_GET_TICK() (xTaskGetTickCount() * portTICK_PERIOD_MS)
/**
* @brief 是否使用默认shell任务while循环使能宏`SHELL_USING_TASK`后此宏有意义
* 使能此宏,则`shellTask()`函数会一直循环读取输入一般使用操作系统建立shell
* 任务时使能此宏,关闭此宏的情况下,一般适用于无操作系统,在主循环中调用`shellTask()`
*/
#define SHELL_TASK_WHILE 1
/**
* @brief 是否使用命令导出方式
* 使能此宏后,可以使用`SHELL_EXPORT_CMD()`等导出命令
* 定义shell命令关闭此宏的情况下需要使用命令表的方式
*/
#define SHELL_USING_CMD_EXPORT 1
/**
* @brief 是否使用shell伴生对象
* 一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象
*/
#define SHELL_USING_COMPANION 0
/**
* @brief 支持shell尾行模式
*/
#define SHELL_SUPPORT_END_LINE 1
/**
* @brief 是否在输出命令列表中列出用户
*/
#define SHELL_HELP_LIST_USER 1
/**
* @brief 是否在输出命令列表中列出变量
*/
#define SHELL_HELP_LIST_VAR 0
/**
* @brief 是否在输出命令列表中列出按键
*/
#define SHELL_HELP_LIST_KEY 0
/**
* @brief 是否在输出命令列表中展示命令权限
*/
#define SHELL_HELP_SHOW_PERMISSION 0
/**
* @brief 使用LF作为命令行回车触发
* 可以和SHELL_ENTER_CR同时开启
*/
#define SHELL_ENTER_LF 0
/**
* @brief 使用CR作为命令行回车触发
* 可以和SHELL_ENTER_LF同时开启
*/
#define SHELL_ENTER_CR 1
/**
* @brief 使用CRLF作为命令行回车触发
* 不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启
*/
#define SHELL_ENTER_CRLF 0
/**
* @brief 使用执行未导出函数的功能
* 启用后,可以通过`exec [addr] [args]`直接执行对应地址的函数
* @attention 如果地址错误,可能会直接引起程序崩溃
*/
#define SHELL_EXEC_UNDEF_FUNC 0
/**
* @brief shell命令参数最大数量
* 包含命令名在内超过16个参数并且使用了参数自动转换的情况下需要修改源码
*/
#define SHELL_PARAMETER_MAX_NUMBER 8
/**
* @brief 历史命令记录数量
*/
#define SHELL_HISTORY_MAX_NUMBER 5
/**
* @brief 双击间隔(ms)
* 使能宏`SHELL_LONG_HELP`后此宏生效定义双击tab补全help的时间间隔
*/
#define SHELL_DOUBLE_CLICK_TIME 200
/**
* @brief 管理的最大shell数量
*/
#define SHELL_MAX_NUMBER 10
/**
* @brief shell格式化输出的缓冲大小
* 为0时不使用shell格式化输出
*/
#define SHELL_PRINT_BUFFER 128
/**
* @brief shell格式化输入的缓冲大小
* 为0时不使用shell格式化输入
* @note shell格式化输入会阻塞shellTask, 仅适用于在有操作系统的情况下使用
*/
#define SHELL_SCAN_BUFFER 128
/**
* @brief 获取系统时间(ms)
* 定义此宏为获取系统Tick如`HAL_GetTick()`
* @note 此宏不定义时无法使用双击tab补全命令help无法使用shell超时锁定
*/
#define SHELL_GET_TICK() (xTaskGetTickCount() * portTICK_PERIOD_MS)
/**
* @brief 使用锁
* @note 使用shell锁时需要对加锁和解锁进行实现
*/
#define SHELL_USING_LOCK 1
/**
* @brief shell内存分配
* shell本身不需要此接口若使用shell伴生对象需要进行定义
*/
#define SHELL_MALLOC(size) pvPortMalloc(size)
/**
* @brief shell内存释放
* shell本身不需要此接口若使用shell伴生对象需要进行定义
*/
#define SHELL_FREE(obj) vPortFree(obj)
/**
* @brief 是否显示shell信息
*/
#define SHELL_SHOW_INFO 1
/**
* @brief 是否在登录后清除命令行
*/
#define SHELL_CLS_WHEN_LOGIN 1
/**
* @brief shell默认用户
*/
#define SHELL_DEFAULT_USER "ziit"
/**
* @brief shell默认用户密码
* 若默认用户不需要密码,设为""
*/
#define SHELL_DEFAULT_USER_PASSWORD "ZIIT1234"
/**
* @brief shell自动锁定超时
* shell当前用户密码有效的时候生效超时后会自动重新锁定shell
* 设置为0时关闭自动锁定功能时间单位为`SHELL_GET_TICK()`单位
* @note 使用超时锁定必须保证`SHELL_GET_TICK()`有效
*/
#define SHELL_LOCK_TIMEOUT 5 * 60 * 1000
#endif

View File

@@ -0,0 +1,103 @@
/**
* @file shell_cmd_list.c
* @author Letter (NevermindZZT@gmail.com)
* @brief shell cmd list
* @version 3.0.0
* @date 2020-01-17
*
* @copyright (c) 2020 Letter
*
*/
#include "shell.h"
#if SHELL_USING_CMD_EXPORT != 1
extern int shellSetVar(char *name, int value);
extern void shellUp(Shell *shell);
extern void shellDown(Shell *shell);
extern void shellRight(Shell *shell);
extern void shellLeft(Shell *shell);
extern void shellTab(Shell *shell);
extern void shellBackspace(Shell *shell);
extern void shellDelete(Shell *shell);
extern void shellEnter(Shell *shell);
extern void shellHelp(int argc, char *argv[]);
extern void shellUsers(void);
extern void shellCmds(void);
extern void shellVars(void);
extern void shellKeys(void);
extern void shellClear(void);
#if SHELL_EXEC_UNDEF_FUNC == 1
extern int shellExecute(int argc, char *argv[]);
#endif
SHELL_AGENCY_FUNC(shellRun, shellGetCurrent(), (const char *)p1);
/**
* @brief shell命令表
*
*/
const ShellCommand shellCommandList[] =
{
{.attr.value=SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_USER),
.data.user.name = SHELL_DEFAULT_USER,
.data.user.password = SHELL_DEFAULT_USER_PASSWORD,
.data.user.desc = "default user"},
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
setVar, shellSetVar, set var),
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0), 0x1B5B4100, shellUp, up),
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0), 0x1B5B4200, shellDown, down),
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
0x1B5B4300, shellRight, right),
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
0x1B5B4400, shellLeft, left),
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0), 0x09000000, shellTab, tab),
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
0x08000000, shellBackspace, backspace),
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
0x7F000000, shellDelete, delete),
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
0x1B5B337E, shellDelete, delete),
#if SHELL_ENTER_LF == 1
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
0x0A000000, shellEnter, enter),
#endif
#if SHELL_ENTER_CR == 1
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
0x0D000000, shellEnter, enter),
#endif
#if SHELL_ENTER_CRLF == 1
SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
0x0D0A0000, shellEnter, enter),
#endif
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
help, shellHelp, show command info\r\nhelp [cmd]),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN,
users, shellUsers, list all user),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN,
cmds, shellCmds, list all cmd),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN,
vars, shellVars, list all var),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN,
keys, shellKeys, list all key),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN,
clear, shellClear, clear console),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN,
sh, SHELL_AGENCY_FUNC_NAME(shellRun), run command directly),
#if SHELL_EXEC_UNDEF_FUNC == 1
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
exec, shellExecute, execute function undefined),
#endif
};
/**
* @brief shell命令表大小
*
*/
const unsigned short shellCommandCount
= sizeof(shellCommandList) / sizeof(ShellCommand);
#endif

View File

@@ -0,0 +1,87 @@
/**
* @file shell_companion.c
* @author Letter (nevermindzzt@gmail.com)
* @brief shell companion object support
* @version 3.0.3
* @date 2020-07-22
*
* @copyright (c) 2020 Letter
*
*/
#include "shell.h"
#if SHELL_USING_COMPANION == 1
/**
* @brief shell添加伴生对象
*
* @param shell shell对象
* @param id 伴生对象ID
* @param object 伴生对象
* @return signed char 0 添加成功 -1 添加失败
*/
signed char shellCompanionAdd(Shell *shell, int id, void *object)
{
ShellCompanionObj *companions = shell->info.companions;
ShellCompanionObj *node = SHELL_MALLOC(sizeof(ShellCompanionObj));
SHELL_ASSERT(node, return -1);
node->id = id;
node->obj = object;
node->next = companions;
shell->info.companions = node;
return 0;
}
/**
* @brief shell删除伴生对象
*
* @param shell shell对象
* @param id 伴生对象ID
* @return signed char 0 删除成功 -1 无匹配对象
*/
signed char shellCompanionDel(Shell *shell, int id)
{
ShellCompanionObj *companions = shell->info.companions;
ShellCompanionObj *front = companions;
while (companions)
{
if (companions->id == id)
{
if (companions == shell->info.companions && !(companions->next))
{
shell->info.companions = (void *)0;
}
else
{
front->next = companions->next;
}
SHELL_FREE(companions);
return 0;
}
front = companions;
companions = companions->next;
}
return -1;
}
/**
* @brief shell获取伴生对象
*
* @param shell shell对象
* @param id 伴生对象ID
* @return void* 伴生对象无匹配对象时返回NULL
*/
void *shellCompanionGet(Shell *shell, int id)
{
SHELL_ASSERT(shell, return (void *)0);
ShellCompanionObj *companions = shell->info.companions;
while (companions)
{
if (companions->id == id)
{
return companions->obj;
}
companions = companions->next;
}
return (void *)0;
}
#endif /** SHELL_USING_COMPANION == 1 */

View File

@@ -0,0 +1,848 @@
/**
* @file shell_ext.c
* @author Letter (NevermindZZT@gmail.com)
* @brief shell extensions
* @version 3.0.0
* @date 2019-12-31
*
* @copyright (c) 2019 Letter
*
*/
#include "shell_cfg.h"
#include "shell.h"
#include "shell_ext.h"
#include "string.h"
extern ShellCommand* shellSeekCommand(Shell *shell,
const char *cmd,
ShellCommand *base,
unsigned short compareLength);
extern int shellGetVarValue(Shell *shell, ShellCommand *command);
#if SHELL_SUPPORT_ARRAY_PARAM == 1
extern int shellSplit(char *string, unsigned short strLen, char *array[], char splitKey, short maxNum);
static int shellExtParseArray(Shell *shell, char *string, char *type, size_t *result);
static int shellExtCleanerArray(Shell *shell, char *type, void *param);
#endif /** SHELL_SUPPORT_ARRAY_PARAM == 1 */
#if SHELL_USING_FUNC_SIGNATURE == 1
/**
* @brief 获取下一个参数类型
*
* @param signature 函数签名
* @param index 参数遍历在签名中的起始索引
* @param type 获取到的参数类型
*
* @return int 下一个参数在签名中的索引
*/
static int shellGetNextParamType(const char *signature, int index, char *type)
{
const char *p = signature + index;
#if SHELL_SUPPORT_ARRAY_PARAM == 1
if (*p == '[')
{
*type++ = *p++;
index++;
}
#endif /** SHELL_SUPPORT_ARRAY_PARAM == 1 */
if (*p == 'L')
{
while (*p != ';' && *p != 0)
{
*type++ = *p++;
index++;
}
*type++ = *p++;
index++;
}
else if (*p != 0)
{
*type++ = *p;
index++;
}
*type = '\0';
return index;
}
/**
* @brief 获取期待的参数个数
*
* @param signature 函数签名
*
* @return int 参数个数
*/
static int shellGetParamNumExcept(const char *signature)
{
int num = 0;
const char *p = signature;
while (*p)
{
#if SHELL_SUPPORT_ARRAY_PARAM == 1
if (*p == '[')
{
p++;
}
#endif /** SHELL_SUPPORT_ARRAY_PARAM == 1 */
if (*p == 'L')
{
while (*p != ';' && *p != 0)
{
p++;
}
p++;
}
else
{
p++;
}
num++;
}
return num;
}
#endif
/**
* @brief 判断数字进制
*
* @param string 参数字符串
* @return ShellNumType 进制
*/
static ShellNumType shellExtNumType(char *string)
{
char *p = string;
ShellNumType type = NUM_TYPE_DEC;
if ((*p == '0') && ((*(p + 1) == 'x') || (*(p + 1) == 'X')))
{
type = NUM_TYPE_HEX;
}
else if ((*p == '0') && ((*(p + 1) == 'b') || (*(p + 1) == 'B')))
{
type = NUM_TYPE_BIN;
}
else if (*p == '0')
{
type = NUM_TYPE_OCT;
}
while (*p++)
{
if (*p == '.' && *(p + 1) != 0)
{
type = NUM_TYPE_FLOAT;
break;
}
}
return type;
}
/**
* @brief 字符转数字
*
* @param code 字符
* @return char 数字
*/
static char shellExtToNum(char code)
{
if ((code >= '0') && (code <= '9'))
{
return code -'0';
}
else if ((code >= 'a') && (code <= 'f'))
{
return code - 'a' + 10;
}
else if ((code >= 'A') && (code <= 'F'))
{
return code - 'A' + 10;
}
else
{
return 0;
}
}
/**
* @brief 解析字符参数
*
* @param string 字符串参数
* @return char 解析出的字符
*/
static char shellExtParseChar(char *string)
{
char *p = (*string == '\'') ? (string + 1) : string;
char value = 0;
if (*p == '\\')
{
switch (*(p + 1))
{
case 'b':
value = '\b';
break;
case 'r':
value = '\r';
break;
case 'n':
value = '\n';
break;
case 't':
value = '\t';
break;
case '0':
value = 0;
break;
default:
value = *(p + 1);
break;
}
}
else
{
value = *p;
}
return value;
}
/**
* @brief 解析字符串参数
*
* @param string 字符串参数
* @return char* 解析出的字符串
*/
static char* shellExtParseString(char *string)
{
char *p = string;
unsigned short index = 0;
if (*string == '\"')
{
p = ++string;
}
while (*p)
{
if (*p == '\\')
{
*(string + index) = shellExtParseChar(p);
p++;
}
else if (*p == '\"')
{
*(string + index) = 0;
}
else
{
*(string + index) = *p;
}
p++;
index ++;
}
*(string + index) = 0;
return string;
}
/**
* @brief 解析数字参数
*
* @param string 字符串参数
* @return size_t 解析出的数字
*/
static size_t shellExtParseNumber(char *string)
{
ShellNumType type = NUM_TYPE_DEC;
char radix = 10;
char *p = string;
char offset = 0;
signed char sign = 1;
size_t valueInt = 0;
float valueFloat = 0.0;
size_t devide = 0;
if (*string == '-')
{
sign = -1;
}
type = shellExtNumType(string + ((sign == -1) ? 1 : 0));
switch ((char)type)
{
case NUM_TYPE_HEX:
radix = 16;
offset = 2;
break;
case NUM_TYPE_OCT:
radix = 8;
offset = 1;
break;
case NUM_TYPE_BIN:
radix = 2;
offset = 2;
break;
default:
break;
}
p = string + offset + ((sign == -1) ? 1 : 0);
while (*p)
{
if (*p == '.')
{
devide = 1;
p++;
continue;
}
valueInt = valueInt * radix + shellExtToNum(*p);
devide *= 10;
p++;
}
if (type == NUM_TYPE_FLOAT && devide != 0)
{
valueFloat = (float)valueInt / devide * sign;
return *(size_t *)(&valueFloat);
}
else
{
return valueInt * sign;
}
}
/**
* @brief 解析变量参数
*
* @param shell shell对象
* @param var 变量
* @param result 解析结果
*
* @return int 0 解析成功 --1 解析失败
*/
static int shellExtParseVar(Shell *shell, char *var, size_t *result)
{
ShellCommand *command = shellSeekCommand(shell,
var + 1,
shell->commandList.base,
0);
if (command)
{
*result = shellGetVarValue(shell, command);
return 0;
}
else
{
return -1;
}
}
/**
* @brief 解析参数
*
* @param shell shell对象
* @param string 参数
* @param type 参数类型
* @param result 解析结果
*
* @return int 0 解析成功 --1 解析失败
*/
int shellExtParsePara(Shell *shell, char *string, char *type, size_t *result)
{
if (type == NULL || (*string == '$' && *(string + 1)))
{
if (*string == '\'' && *(string + 1))
{
*result = (size_t)shellExtParseChar(string);
return 0;
}
else if (*string == '-' || (*string >= '0' && *string <= '9'))
{
*result = shellExtParseNumber(string);
return 0;
}
else if (*string == '$' && *(string + 1))
{
return shellExtParseVar(shell, string, result);
}
else if (*string)
{
*result = (size_t)shellExtParseString(string);
return 0;
}
}
#if SHELL_USING_FUNC_SIGNATURE == 1
else
{
if (*string == '$' && *(string + 1))
{
return shellExtParseVar(shell, string, result);
}
#if SHELL_SUPPORT_ARRAY_PARAM == 1
else if (type[0] == '[')
{
return shellExtParseArray(shell, string, type, result);
}
#endif /** SHELL_SUPPORT_ARRAY_PARAM == 1 */
else if (strcmp("c", type) == 0)
{
*result = (size_t)shellExtParseChar(string);
return 0;
}
else if (strcmp("q", type) == 0
|| strcmp("h", type) == 0
|| strcmp("i", type) == 0
|| strcmp("f", type) == 0
|| strcmp("p", type) == 0)
{
*result = shellExtParseNumber(string);
return 0;
}
else if (strcmp("s", type) == 0)
{
*result = (size_t)shellExtParseString(string);
return 0;
}
else
{
ShellCommand *command = shellSeekCommand(shell,
type,
shell->commandList.base,
0);
if (command != NULL)
{
void *param;
if (command->data.paramParser.parser(shellExtParseString(string), &param) == 0)
{
*result = (size_t)param;
return 0;
}
else
{
shellWriteString(shell, "Parse param for type: ");
shellWriteString(shell, type);
shellWriteString(shell, " failed\r\n");
return -1;
}
}
else
{
shellWriteString(shell, "Can't find the param parser for type: ");
shellWriteString(shell, type);
shellWriteString(shell, "\r\n");
return -1;
}
}
}
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
return -1;
}
#if SHELL_USING_FUNC_SIGNATURE == 1
/**
* @brief 清理参数
*
* @param shell shell
* @param type 参数类型
* @param param 参数
*
* @return int 0 清理成功 -1 清理失败
*/
int shellExtCleanerPara(Shell *shell, char *type, size_t param)
{
if (type == NULL)
{
return 0;
}
else
{
#if SHELL_SUPPORT_ARRAY_PARAM == 1
if (type[0] == '[') {
return shellExtCleanerArray(shell, type, (void *) param);
}
else
#endif /** SHELL_SUPPORT_ARRAY_PARAM == 1 */
if (strcmp("c", type) == 0
|| strcmp("q", type) == 0
|| strcmp("h", type) == 0
|| strcmp("i", type) == 0
|| strcmp("f", type) == 0
|| strcmp("p", type) == 0
|| strcmp("s", type) == 0)
{
return 0;
}
else
{
ShellCommand *command = shellSeekCommand(shell,
type,
shell->commandList.base,
0);
if (command != NULL && command->data.paramParser.cleaner != NULL)
{
return command->data.paramParser.cleaner((void *)param);
}
}
}
return -1;
}
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
#if SHELL_SUPPORT_ARRAY_PARAM == 1
/**
* @brief 估算数组长度
*
* @param string 数组参数
*
* @return int 估算的数组长度
*/
static int shellEstimateArrayLength(char *string)
{
int length = 0;
char *p = string;
while (*p)
{
if (*p == ',')
{
length++;
}
p++;
}
return length + 1;
}
/**
* @brief 分割数组参数
*
* @param string 数组参数
* @param array 分割后的字符串数组
*
* @return int 数组长度
*/
static int shellSplitArray(char *string, char ***array)
{
int strLen = strlen(string);
if (string[strLen - 1] == ']')
{
string[--strLen] = 0;
}
if (string[0] == '[')
{
--strLen;
string++;
}
int size = shellEstimateArrayLength(string);
*array = SHELL_MALLOC(size * sizeof(char *));
return shellSplit(string, strLen, *array, ',', size);
}
/**
* @brief 解析数组参数
*
* @param shell shell 对象
* @param string 数组参数
* @param type 参数类型
* @param result 解析结果
*
* @return int 0 解析成功 -1 解析失败
*/
static int shellExtParseArray(Shell *shell, char *string, char *type, size_t *result)
{
char **params;
int size = shellSplitArray(string, &params);
int elementBytes = sizeof(void *);
if (strcmp(type + 1, "q") == 0)
{
elementBytes = sizeof(char);
}
else if (strcmp(type + 1, "h") == 0)
{
elementBytes = sizeof(short);
}
else if (strcmp(type + 1, "i") == 0)
{
elementBytes = sizeof(int);
}
ShellArrayHeader *header = SHELL_MALLOC(elementBytes * size + sizeof(ShellArrayHeader));
*result = (size_t) ((size_t) header + sizeof(ShellArrayHeader));
header->size = size;
header->elementBytes = elementBytes;
for (short i = 0; i < size; i++)
{
size_t value;
if (shellExtParsePara(shell, params[i], type + 1, &value) != 0)
{
SHELL_FREE(header);
SHELL_FREE(params);
return -1;
}
memcpy((void *) ((size_t) *result + elementBytes * i), &value, elementBytes);
}
SHELL_FREE(params);
return 0;
}
/**
* @brief 清理数组参数
*
* @param shell shell 对象
* @param type 参数类型
* @param param 参数
*
* @return int 0 清理成功 -1 清理失败
*/
static int shellExtCleanerArray(Shell *shell, char *type, void *param)
{
ShellArrayHeader *header = (ShellArrayHeader *) ((size_t) param - sizeof(ShellArrayHeader));
for (short i = 0; i < header->size; i++)
{
if (shellExtCleanerPara(shell, type + 1, *(size_t *) ((size_t) param + header->elementBytes * i)) != 0)
{
return -1;
}
}
SHELL_FREE(header);
return 0;
}
/**
* @brief 获取数组大小
*
* @param param 数组
*
* @return int 数组大小
*/
int shellGetArrayParamSize(void *param)
{
ShellArrayHeader *header = (ShellArrayHeader *) ((size_t) param - sizeof(ShellArrayHeader));
return header->size;
}
#endif /** SHELL_SUPPORT_ARRAY_PARAM == 1 */
/**
* @brief 执行命令
*
* @param shell shell对象
* @param command 命令
* @param argc 参数个数
* @param argv 参数
* @return int 返回值
*/
int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[])
{
int ret = 0;
size_t params[SHELL_PARAMETER_MAX_NUMBER] = {0};
int paramNum = command->attr.attrs.paramNum > (argc - 1) ?
command->attr.attrs.paramNum : (argc - 1);
#if SHELL_USING_FUNC_SIGNATURE == 1
char type[16];
int index = 0;
if (command->data.cmd.signature != NULL)
{
int except = shellGetParamNumExcept(command->data.cmd.signature);
if (except != argc - 1)
{
shellWriteString(shell, "Parameters number incorrect\r\n");
return -1;
}
}
#endif
for (int i = 0; i < argc - 1; i++)
{
#if SHELL_USING_FUNC_SIGNATURE == 1
if (command->data.cmd.signature != NULL) {
index = shellGetNextParamType(command->data.cmd.signature, index, type);
if (shellExtParsePara(shell, argv[i + 1], type, &params[i]) != 0)
{
return -1;
}
}
else
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
{
if (shellExtParsePara(shell, argv[i + 1], NULL, &params[i]) != 0)
{
return -1;
}
}
}
switch (paramNum)
{
#if SHELL_PARAMETER_MAX_NUMBER >= 1
case 0:
ret = command->data.cmd.function();
break;
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 1 */
#if SHELL_PARAMETER_MAX_NUMBER >= 2
case 1:
{
int (*func)(size_t) = command->data.cmd.function;
ret = func(params[0]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 2 */
#if SHELL_PARAMETER_MAX_NUMBER >= 3
case 2:
{
int (*func)(size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 3 */
#if SHELL_PARAMETER_MAX_NUMBER >= 4
case 3:
{
int (*func)(size_t, size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 4 */
#if SHELL_PARAMETER_MAX_NUMBER >= 5
case 4:
{
int (*func)(size_t, size_t, size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 5 */
#if SHELL_PARAMETER_MAX_NUMBER >= 6
case 5:
{
int (*func)(size_t, size_t, size_t, size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 6 */
#if SHELL_PARAMETER_MAX_NUMBER >= 7
case 6:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 7 */
#if SHELL_PARAMETER_MAX_NUMBER >= 8
case 7:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5], params[6]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 8 */
#if SHELL_PARAMETER_MAX_NUMBER >= 9
case 8:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t)
= command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 9 */
#if SHELL_PARAMETER_MAX_NUMBER >= 10
case 9:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t,
size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7],
params[8]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 10 */
#if SHELL_PARAMETER_MAX_NUMBER >= 11
case 10:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t,
size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7],
params[8], params[9]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 11 */
#if SHELL_PARAMETER_MAX_NUMBER >= 12
case 11:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t,
size_t, size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7],
params[8], params[9], params[10]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 12 */
#if SHELL_PARAMETER_MAX_NUMBER >= 13
case 12:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t,
size_t, size_t, size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7],
params[8], params[9], params[10], params[11]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 13 */
#if SHELL_PARAMETER_MAX_NUMBER >= 14
case 13:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t,
size_t, size_t, size_t, size_t, size_t) = command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7],
params[8], params[9], params[10], params[11], params[12]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 14 */
#if SHELL_PARAMETER_MAX_NUMBER >= 15
case 14:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t,
size_t, size_t, size_t, size_t, size_t, size_t)
= command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7],
params[8], params[9], params[10], params[11], params[12], params[13]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 15 */
#if SHELL_PARAMETER_MAX_NUMBER >= 16
case 15:
{
int (*func)(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t,
size_t, size_t, size_t, size_t, size_t, size_t, size_t)
= command->data.cmd.function;
ret = func(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7],
params[8], params[9], params[10], params[11], params[12], params[13], params[14]);
break;
}
#endif /** SHELL_PARAMETER_MAX_NUMBER >= 16 */
default:
ret = -1;
break;
}
#if SHELL_USING_FUNC_SIGNATURE == 1
if (command->data.cmd.signature != NULL) {
index = 0;
for (int i = 0; i < argc - 1; i++)
{
index = shellGetNextParamType(command->data.cmd.signature, index, type);
shellExtCleanerPara(shell, type, params[i]);
}
}
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
return ret;
}

View File

@@ -0,0 +1,47 @@
/**
* @file shell_ext.h
* @author Letter (NevermindZZT@gmail.com)
* @brief shell extensions
* @version 3.0.0
* @date 2019-12-31
*
* @copyright (c) 2019 Letter
*
*/
#ifndef __SHELL_EXT_H__
#define __SHELL_EXT_H__
#include "shell.h"
/**
* @brief 数字类型
*
*/
typedef enum
{
NUM_TYPE_DEC, /**< 十进制整型 */
NUM_TYPE_BIN, /**< 二进制整型 */
NUM_TYPE_OCT, /**< 八进制整型 */
NUM_TYPE_HEX, /**< 十六进制整型 */
NUM_TYPE_FLOAT /**< 浮点型 */
} ShellNumType;
#if SHELL_SUPPORT_ARRAY_PARAM == 1
typedef struct
{
unsigned short size;
unsigned char elementBytes;
} ShellArrayHeader;
#endif /** SHELL_SUPPORT_ARRAY_PARAM == 1 */
int shellExtParsePara(Shell *shell, char *string, char *type, size_t *result);
#if SHELL_USING_FUNC_SIGNATURE == 1
int shellExtCleanerPara(Shell *shell, char *type, size_t param);
#endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
#if SHELL_SUPPORT_ARRAY_PARAM == 1
int shellGetArrayParamSize(void *param);
#endif /** SHELL_SUPPORT_ARRAY_PARAM == 1 */
int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[]);
#endif

View File

@@ -0,0 +1,121 @@
/**
* @file shell_port.c
* @author Letter (NevermindZZT@gmail.com)
* @brief
* @version 0.1
* @date 2019-02-22
*
* @copyright (c) 2019 Letter
*
*/
#include "FreeRTOS.h"
#include "task.h"
#include "shell.h"
#include "queue.h"
#include "semphr.h"
#include "stm32f10x.h"
#include "bsp_usart.h"
#include "string.h"
Shell shell;
char shellBuffer[512];
static SemaphoreHandle_t shellMutex;
/**
* @brief 用户shell写
*
* @param data 数据
* @param len 数据长度
*
* @return short 实际写入的数据长度
*/
short userShellWrite(char *data, unsigned short len)
{
Usart_SendString(USART1,data);
return len;
}
/**
* @brief 用户shell读
*
* @param data 数据
* @param len 数据长度
*
* @return short 实际读取到
*/
/* 自定义接口函数 */
extern uint8_t g_debugRxBuf[];
extern uint8_t g_debugRxFlag;
extern uint16_t g_debugRxLen;
void userShellRun(void)
{
if(g_debugRxFlag)
{
for(uint8_t i=0;i<=g_debugRxLen;i++)
{
shellHandler(&shell,g_debugRxBuf[i]);
}
g_debugRxLen = 0;
g_debugRxFlag = 0;
memset(g_debugRxBuf,0x00,255);
}
}
short userShellRead(char *data, unsigned short len)
{
userShellRun();
vTaskDelay(20);
return 0;
}
/**
* @brief 用户shell上锁
*
* @param shell shell
*
* @return int 0
*/
int userShellLock(Shell *shell)
{
xSemaphoreTake(shellMutex, portMAX_DELAY);
return 0;
}
/**
* @brief 用户shell解锁
*
* @param shell shell
*
* @return int 0
*/
int userShellUnlock(Shell *shell)
{
xSemaphoreGive(shellMutex);
return 0;
}
/**
* @brief 用户shell初始化
*
*/
void userShellInit(void)
{
shellMutex = xSemaphoreCreateMutex();
shell.write = userShellWrite;
shell.read = userShellRead;
shell.lock = userShellLock;
shell.unlock = userShellUnlock;
shellInit(&shell, shellBuffer, 512);
if (xTaskCreate(shellTask, "shell", 256, &shell, 5, NULL) != pdPASS)
{
printf("shell task creat failed");
}
}

View File

@@ -0,0 +1,21 @@
/**
* @file shell_port.h
* @author Letter (NevermindZZT@gmail.com)
* @brief
* @version 0.1
* @date 2019-02-22
*
* @copyright (c) 2019 Letter
*
*/
#ifndef __SHELL_PORT_H__
#define __SHELL_PORT_H__
#include "shell.h"
extern Shell shell;
void userShellInit(void);
void userShellRun(void);
#endif