Support XiZi_AIoT

This commit is contained in:
TXuian
2024-01-31 10:30:34 +08:00
parent f6cf46027d
commit 494312183b
351 changed files with 46408 additions and 450091 deletions
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Letter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,27 @@
toolchain ?= arm-none-eabi-
cc = ${toolchain}gcc
ld = ${toolchain}g++
objdump = ${toolchain}objdump
# user_ldflags = -N -Ttext 0
cflags = -std=c11 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie -no-pie
c_useropts = -O0
INC_DIR = -I$(KERNEL_ROOT)/services/boards/imx6q-sabrelite -I$(KERNEL_ROOT)/services/lib/ipc -I$(KERNEL_ROOT)/services/fs/include
all: shell_cmd_list.o shell_ext.o shell.o
@mv shell_cmd_list.o ../../boards/imx6q-sabrelite
@mv shell_ext.o ../../boards/imx6q-sabrelite
@mv shell.o ../../boards/imx6q-sabrelite
shell_cmd_list.o: shell_cmd_list.c
@echo "cc shell_cmd_list"
@${cc} ${cflags} ${c_useropts} -o $@ -c $<
shell_ext.o: shell_ext.c
@echo "cc shell_ext"
@${cc} ${cflags} ${c_useropts} -o $@ -c $<
shell.o: shell.c
@echo "cc shell"
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $<
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,558 @@
/**
* @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.3" /**< 版本号 */
/**
* @brief data 断言
*
* @param data 接收数据
* @param action 断言失败操作
*/
#define CHECK_DATA(data, action) \
if (data == 0xFF) { \
action; \
}
/**
* @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);
extern int test_syscall(int sysnum, char* path, char** argv);
#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
@@ -0,0 +1,267 @@
/**
* @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__
#ifdef SHELL_CFG_USER
#include SHELL_CFG_USER
#endif
#ifndef SHELL_TASK_WHILE
/**
* @brief 是否使用默认shell任务while循环
* 使能此宏,则`shellTask()`函数会一直循环读取输入,一般使用操作系统建立shell
* 任务时使能此宏,关闭此宏的情况下,一般适用于无操作系统,在主循环中调用`shellTask()`
*/
#define SHELL_TASK_WHILE 1
#endif /** SHELL_TASK_WHILE */
#ifndef SHELL_USING_CMD_EXPORT
/**
* @brief 是否使用命令导出方式
* 使能此宏后,可以使用`SHELL_EXPORT_CMD()`等导出命令
* 定义shell命令,关闭此宏的情况下,需要使用命令表的方式
*/
#define SHELL_USING_CMD_EXPORT 0
#endif /** SHELL_USING_CMD_EXPORT */
#ifndef SHELL_USING_COMPANION
/**
* @brief 是否使用shell伴生对象
* 一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象
*/
#define SHELL_USING_COMPANION 0
#endif /** SHELL_USING_COMPANION */
#ifndef SHELL_SUPPORT_END_LINE
/**
* @brief 支持shell尾行模式
*/
#define SHELL_SUPPORT_END_LINE 0
#endif /** SHELL_SUPPORT_END_LINE */
#ifndef SHELL_HELP_LIST_USER
/**
* @brief 是否在输出命令列表中列出用户
*/
#define SHELL_HELP_LIST_USER 0
#endif /** SHELL_HELP_LIST_USER */
#ifndef SHELL_HELP_LIST_VAR
/**
* @brief 是否在输出命令列表中列出变量
*/
#define SHELL_HELP_LIST_VAR 0
#endif /** SHELL_HELP_LIST_VAR */
#ifndef SHELL_HELP_LIST_KEY
/**
* @brief 是否在输出命令列表中列出按键
*/
#define SHELL_HELP_LIST_KEY 0
#endif /** SHELL_HELP_LIST_KEY */
#ifndef SHELL_HELP_SHOW_PERMISSION
/**
* @brief 是否在输出命令列表中展示命令权限
*/
#define SHELL_HELP_SHOW_PERMISSION 1
#endif /** SHELL_HELP_SHOW_PERMISSION */
#ifndef SHELL_ENTER_LF
/**
* @brief 使用LF作为命令行回车触发
* 可以和SHELL_ENTER_CR同时开启
*/
#define SHELL_ENTER_LF 1
#endif /** SHELL_ENTER_LF */
#ifndef SHELL_ENTER_CR
/**
* @brief 使用CR作为命令行回车触发
* 可以和SHELL_ENTER_LF同时开启
*/
#define SHELL_ENTER_CR 1
#endif /** SHELL_ENTER_CR */
#ifndef SHELL_ENTER_CRLF
/**
* @brief 使用CRLF作为命令行回车触发
* 不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启
*/
#define SHELL_ENTER_CRLF 0
#endif /** SHELL_ENTER_CRLF */
#ifndef SHELL_EXEC_UNDEF_FUNC
/**
* @brief 使用执行未导出函数的功能
* 启用后,可以通过`exec [addr] [args]`直接执行对应地址的函数
* @attention 如果地址错误,可能会直接引起程序崩溃
*/
#define SHELL_EXEC_UNDEF_FUNC 0
#endif /** SHELL_EXEC_UNDEF_FUNC */
#ifndef SHELL_PARAMETER_MAX_NUMBER
/**
* @brief shell命令参数最大数量
* 包含命令名在内,超过16个参数并且使用了参数自动转换的情况下,需要修改源码
*/
#define SHELL_PARAMETER_MAX_NUMBER 8
#endif /** SHELL_PARAMETER_MAX_NUMBER */
#ifndef SHELL_HISTORY_MAX_NUMBER
/**
* @brief 历史命令记录数量
*/
#define SHELL_HISTORY_MAX_NUMBER 5
#endif /** SHELL_HISTORY_MAX_NUMBER */
#ifndef SHELL_DOUBLE_CLICK_TIME
/**
* @brief 双击间隔(ms)
* 使能宏`SHELL_LONG_HELP`后此宏生效,定义双击tab补全help的时间间隔
*/
#define SHELL_DOUBLE_CLICK_TIME 200
#endif /** SHELL_DOUBLE_CLICK_TIME */
#ifndef SHELL_QUICK_HELP
/**
* @brief 快速帮助
* 作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息
*/
#define SHELL_QUICK_HELP 1
#endif /** SHELL_QUICK_HELP */
#ifndef SHELL_KEEP_RETURN_VALUE
/**
* @brief 保存命令返回值
* 开启后会默认定义一个`RETVAL`变量,会保存上一次命令执行的返回值,可以在随后的命令中进行调用
* 如果命令的`SHELL_CMD_DISABLE_RETURN`标志被设置,则该命令不会更新`RETVAL`
*/
#define SHELL_KEEP_RETURN_VALUE 0
#endif /** SHELL_KEEP_RETURN_VALUE */
#ifndef SHELL_MAX_NUMBER
/**
* @brief 管理的最大shell数量
*/
#define SHELL_MAX_NUMBER 5
#endif /** SHELL_MAX_NUMBER */
#ifndef SHELL_PRINT_BUFFER
/**
* @brief shell格式化输出的缓冲大小
* 为0时不使用shell格式化输出
*/
#define SHELL_PRINT_BUFFER 0
#endif /** SHELL_PRINT_BUFFER */
#ifndef SHELL_SCAN_BUFFER
/**
* @brief shell格式化输入的缓冲大小
* 为0时不使用shell格式化输入
* @note shell格式化输入会阻塞shellTask, 仅适用于在有操作系统的情况下使用
*/
#define SHELL_SCAN_BUFFER 0
#endif /** SHELL_SCAN_BUFFER */
#ifndef SHELL_GET_TICK
/**
* @brief 获取系统时间(ms)
* 定义此宏为获取系统Tick,如`HAL_GetTick()`
* @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
*/
#define SHELL_GET_TICK() 0
#endif /** SHELL_GET_TICK */
#ifndef SHELL_USING_LOCK
/**
* @brief 使用锁
* @note 使用shell锁时,需要对加锁和解锁进行实现
*/
#define SHELL_USING_LOCK 0
#endif /** SHELL_USING_LOCK */
#ifndef SHELL_MALLOC
/**
* @brief shell内存分配
* shell本身不需要此接口,若使用shell伴生对象,需要进行定义
*/
#define SHELL_MALLOC(size) 0
#endif /** SHELL_MALLOC */
#ifndef SHELL_FREE
/**
* @brief shell内存释放
* shell本身不需要此接口,若使用shell伴生对象,需要进行定义
*/
#define SHELL_FREE(obj) 0
#endif /** SHELL_FREE */
#ifndef SHELL_SHOW_INFO
/**
* @brief 是否显示shell信息
*/
#define SHELL_SHOW_INFO 1
#endif /** SHELL_SHOW_INFO */
#ifndef SHELL_CLS_WHEN_LOGIN
/**
* @brief 是否在登录后清除命令行
*/
#define SHELL_CLS_WHEN_LOGIN 0
#endif /** SHELL_CLS_WHEN_LOGIN */
#ifndef SHELL_DEFAULT_USER
/**
* @brief shell默认用户
*/
#define SHELL_DEFAULT_USER "letter"
#endif /** SHELL_DEFAULT_USER */
#ifndef SHELL_DEFAULT_USER_PASSWORD
/**
* @brief shell默认用户密码
* 若默认用户不需要密码,设为""
*/
#define SHELL_DEFAULT_USER_PASSWORD ""
#endif /** SHELL_DEFAULT_USER_PASSWORD */
#ifndef SHELL_LOCK_TIMEOUT
/**
* @brief shell自动锁定超时
* shell当前用户密码有效的时候生效,超时后会自动重新锁定shell
* 设置为0时关闭自动锁定功能,时间单位为`SHELL_GET_TICK()`单位
* @note 使用超时锁定必须保证`SHELL_GET_TICK()`有效
*/
#define SHELL_LOCK_TIMEOUT 0 * 60 * 1000
#endif /** SHELL_LOCK_TIMEOUT */
#ifndef SHELL_USING_FUNC_SIGNATURE
/**
* @brief 使用函数签名
* 使能后,可以在声明命令时,指定函数的签名,shell 会根据函数签名进行参数转换,
* 而不是自动判断参数的类型,如果参数和函数签名不匹配,会停止执行命令
*/
#define SHELL_USING_FUNC_SIGNATURE 0
#endif /** SHELL_USING_FUNC_SIGNATURE */
#ifndef SHELL_SUPPORT_ARRAY_PARAM
/**
* @brief 支持数组参数
* 使能后,可以在命令中使用数组参数,如`cmd [1,2,3]`
* 需要使能 `SHELL_USING_FUNC_SIGNATURE` 宏,并且配置 `SHELL_MALLOC`, `SHELL_FREE`
*/
#define SHELL_SUPPORT_ARRAY_PARAM 0
#endif /** SHELL_SUPPORT_ARRAY_PARAM */
#endif
@@ -0,0 +1,131 @@
/**
* @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);
// fs cmds
extern void shellLs(const char* path, ...);
extern void shellCd(const char* path);
extern void shellMkdir(const char* path);
extern void shellRm(const char* path);
extern void shellCat(const char* path);
extern void shellShowTasks();
extern void shellShowMemInfo();
extern void shellShowCpusInfo();
#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, shellBackspace, 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),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
ls, shellLs, ls files),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
cd, shellCd, go to target path),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
mkdir, shellMkdir, create a new dir),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
rm, shellRm, remove a file or a dir),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
cat, shellCat, print the file content on the console),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
showTasks, shellShowTasks, display tasks info),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
showMemInfo, shellShowMemInfo, display memory info),
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
showCpusInfo, shellShowCpusInfo, display cpus info),
#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
@@ -0,0 +1,297 @@
/**
* @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_ext.h"
#include "shell.h"
extern ShellCommand* shellSeekCommand(Shell* shell,
const char* cmd,
ShellCommand* base,
unsigned short compareLength);
extern int shellGetVarValue(Shell* shell, ShellCommand* command);
/**
* @brief Judging the number base
*
* @param string Parameter string
* @return NUM_Type Base
*/
static NUM_Type shellExtNumType(char* string)
{
char* p = string;
NUM_Type type = NUM_TYPE_INT;
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 character to number
*
* @param code character
* @return char number
*/
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 Parse character parameters
*
* @param string String parameter
* @return char Parsed character
*/
static char shellExtParseChar(char* string)
{
char* p = string + 1;
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 Parse string parameters
*
* @param string String parameter
* @return char* Parsed string
*/
static char* shellExtParseString(char* string)
{
char* p = string;
unsigned short index = 0;
if (*string == '\"') {
p = ++string;
}
while (*p) {
if (*p == '\\') {
*(string + index) = shellExtParseChar(p - 1);
p++;
} else if (*p == '\"') {
*(string + index) = 0;
} else {
*(string + index) = *p;
}
p++;
index++;
}
*(string + index) = 0;
return string;
}
/**
* @brief Parse numeric parameters
*
* @param string String parameter
* @return unsigned int Parsed number
*/
static unsigned int shellExtParseNumber(char* string)
{
NUM_Type type = NUM_TYPE_INT;
char radix = 10;
char* p = string;
char offset = 0;
signed char sign = 1;
unsigned int valueInt = 0;
float valueFloat = 0.0;
unsigned int 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 *(unsigned int*)(&valueFloat);
} else {
return valueInt * sign;
}
}
/**
* @brief Analyze variable parameters
*
* @param shell shell object
* @param var variable
* @return unsigned int variable value
*/
static unsigned int shellExtParseVar(Shell* shell, char* var)
{
ShellCommand* command = shellSeekCommand(shell,
var + 1,
shell->commandList.base,
0);
if (command) {
return shellGetVarValue(shell, command);
} else {
return 0;
}
}
/**
* @brief Parsing parameters
*
* @param shell shell
* @param string parameter
* @return unsigned int Analysis result
*/
unsigned int shellExtParsePara(Shell* shell, char* string)
{
if (*string == '\'' && *(string + 1)) {
return (unsigned int)shellExtParseChar(string);
} else if (*string == '-' || (*string >= '0' && *string <= '9')) {
return (unsigned int)shellExtParseNumber(string);
} else if (*string == '$' && *(string + 1)) {
return shellExtParseVar(shell, string);
} else if (*string) {
return (unsigned long)shellExtParseString(string);
}
return 0;
}
/**
* @brief Excuting function
*
* @param shell shell
* @param command command
* @param argc Number of parameters
* @param argv parameter
* @return int return value
*/
int shellExtRun(Shell* shell, ShellCommand* command, int argc, char* argv[])
{
unsigned int params[8] = { 0 };
int paramNum = command->attr.attrs.paramNum > (argc - 1) ? command->attr.attrs.paramNum : (argc - 1);
for (int i = 0; i < argc - 1; i++) {
params[i] = shellExtParsePara(shell, argv[i + 1]);
}
switch (paramNum) {
case 0:
return command->data.cmd.function();
// break;
case 1:
return command->data.cmd.function(params[0]);
// break;
case 2:
return command->data.cmd.function(params[0], params[1]);
// break;
case 3:
return command->data.cmd.function(params[0], params[1],
params[2]);
// break;
case 4:
return command->data.cmd.function(params[0], params[1],
params[2], params[3]);
// break;
case 5:
return command->data.cmd.function(params[0], params[1],
params[2], params[3],
params[4]);
// break;
case 6:
return command->data.cmd.function(params[0], params[1],
params[2], params[3],
params[4], params[5]);
// break;
case 7:
return command->data.cmd.function(params[0], params[1],
params[2], params[3],
params[4], params[5],
params[6]);
// break;
default:
return -1;
// break;
}
}
@@ -0,0 +1,32 @@
/**
* @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 type of number
*
*/
typedef enum {
NUM_TYPE_INT, /**< Decimal integer */
NUM_TYPE_BIN, /**< Binary integer */
NUM_TYPE_OCT, /**< Octal integer */
NUM_TYPE_HEX, /**< Hexadecimal integer */
NUM_TYPE_FLOAT /**< Floating point */
} NUM_Type;
unsigned int shellExtParsePara(Shell* shell, char* string);
int shellExtRun(Shell* shell, ShellCommand* command, int argc, char* argv[]);
#endif