1
0
mirror of https://github.com/NevermindZZT/letter-shell.git synced 2025-01-21 10:02:54 +08:00

Merge pull request #82 from NevermindZZT/shell3.1

Shell3.1
This commit is contained in:
Letter 2021-05-22 22:26:03 +08:00 committed by GitHub
commit 8c87c8cd22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 332 additions and 144 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
CMakeFiles
cmake_install.cmake
CMakeCache.txt
demo/x86-gcc/Makefile

139
README.md
View File

@ -1,15 +1,15 @@
# letter shell 3.0
# letter shell 3.x
![version](https://img.shields.io/badge/version-3.0.6-brightgreen.svg)
![version](https://img.shields.io/badge/version-3.1.0-brightgreen.svg)
![standard](https://img.shields.io/badge/standard-c99-brightgreen.svg)
![build](https://img.shields.io/badge/build-2020.11.29-brightgreen.svg)
![build](https://img.shields.io/badge/build-2021.05.09-brightgreen.svg)
![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)
一个功能强大的嵌入式shell
![shell_info.png](doc/img/shell_info.png)
- [letter shell 3.0](#letter-shell-30)
- [letter shell 3.x](#letter-shell-3x)
- [简介](#简介)
- [功能](#功能)
- [移植说明](#移植说明)
@ -26,23 +26,27 @@
- [命令属性字段说明](#命令属性字段说明)
- [代理函数和代理参数解析](#代理函数和代理参数解析)
- [权限系统说明](#权限系统说明)
- [锁说明](#锁说明)
- [伴生对象](#伴生对象)
- [尾行模式](#尾行模式)
- [建议终端软件](#建议终端软件)
- [命令遍历工具](#命令遍历工具)
- [x86 demo](#x86-demo)
## 简介
[letter shell 3.0](https://github.com/NevermindZZT/letter-shell/tree/shell3.0)是一个C语言编写的可以嵌入在程序中的嵌入式shell主要面向嵌入式设备以C语言函数为运行单位可以通过命令行调用运行程序中的函数
[letter shell](https://github.com/NevermindZZT/letter-shell)是一个C语言编写的可以嵌入在程序中的嵌入式shell主要面向嵌入式设备以C语言函数为运行单位可以通过命令行调用运行程序中的函数
相对2.x版本letter shell 3.0增加了用户管理权限管理后续会增加对文件系统的支持
相对2.x版本letter shell 3.x增加了用户管理权限管理以及对文件系统的初步支持
此外3.0版本修改了命令格式和定义2.x版本的工程需要经过简单的修改才能完成迁移
此外3.x版本修改了命令格式和定义2.x版本的工程需要经过简单的修改才能完成迁移
若只需要使用基础功能,可以使用[letter shell 2.x](https://github.com/NevermindZZT/letter-shell/tree/shell2.x)版本
使用说明可参考[Letter shell 3.0 全新出发](https://nevermindzzt.github.io/2020/01/19/Letter%20shell%203.0%E5%85%A8%E6%96%B0%E5%87%BA%E5%8F%91/)
如果从3.0版本迁移到3.1以上版本请注意3.1版本对读写函数原型的修改
## 功能
- 命令自动补全
@ -60,7 +64,9 @@
Shell shell;
```
2. 定义shell读写函数函数原型如下
2. 定义shell读写函数
对于使用letter shell 3.0版本,读写函数原型如下:
```C
/**
@ -81,6 +87,30 @@
typedef void (*shellWrite)(const char);
```
对于使用letter shell 3.1版本,为了优化效率,修改了读写函数原型,如下:
```C
/**
* @brief shell读取数据函数原型
*
* @param data shell读取的字符
* @param len 请求读取的字符数量
*
* @return unsigned short 实际读取到的字符数量
*/
typedef unsigned short (*shellRead)(char *data, unsigned short len);
/**
* @brief shell写数据函数原型
*
* @param data 需写的字符数据
* @param len 需要写入的字符数
*
* @return unsigned short 实际写入的字符数量
*/
typedef unsigned short (*shellWrite)(const char *data, unsigned short len);
```
3. 申请一片缓冲区
```C
@ -108,7 +138,7 @@
6. 说明
- 对于中断方式使用shell不用定义`shell->read`,但需要在中断中调用`shellHandler`
- 对于使用操作系统的情况,使能```SHEHLL_TASK_WHILE```然后创建shellTask任务
- 对于使用操作系统的情况,使能`SHEHLL_TASK_WHILE`然后创建shellTask任务
7. 其他配置
@ -137,6 +167,7 @@
| SHELL_DOUBLE_CLICK_TIME | 双击间隔(ms) |
| SHELL_MAX_NUMBER | 管理的最大shell数量 |
| SHELL_GET_TICK() | 获取系统时间(ms) |
| SHELL_USING_LOCK | 是否使用锁 |
| SHELL_MALLOC(size) | 内存分配函数(shell本身不需要) |
| SHELL_FREE(obj) | 内存释放函数(shell本身不需要) |
| SHELL_SHOW_INFO | 是否显示shell信息 |
@ -149,7 +180,7 @@
### 函数定义
letter shell 3.0同时支持两种形式的函数定义方式形如main函数定义的`func(int argc, char *agrv[])`以及形如普通C函数的定义`func(int i, char *str, ...)`,两种函数定义方式适用于不同的场景
letter shell 3.x同时支持两种形式的函数定义方式形如main函数定义的`func(int argc, char *agrv[])`以及形如普通C函数的定义`func(int i, char *str, ...)`,两种函数定义方式适用于不同的场景
#### main函数形式
@ -196,7 +227,7 @@ input int: 666, char: A, string: hello world
### 变量使用
letter shell 3.0支持导出变量,通过命令行查看,设置以及使用变量的值
letter shell 3.x支持导出变量,通过命令行查看,设置以及使用变量的值
- 导出变量
@ -239,7 +270,7 @@ letter shell 3.0支持导出变量,通过命令行查看,设置以及使用
- 使用变量
letter shell 3.0的变量可以在命令中作为参数传递,对于需要传递结构体引用到命令中的场景特别适用,使用`$`+变量名的方式传递
letter shell 3.x的变量可以在命令中作为参数传递,对于需要传递结构体引用到命令中的场景特别适用,使用`$`+变量名的方式传递
```sh
letter:/$ shellPrint $shell "hello world\r\n"
@ -260,7 +291,7 @@ letter shell支持通过函数地址直接执行函数可以方便执行那
## 命令定义
letter shell 3.0将可执行的函数命令定义,用户定义,按键定义以及变量定义统一归为命令定义,使用相同的结构储存,查找和执行
letter shell 3.x将可执行的函数命令定义,用户定义,按键定义以及变量定义统一归为命令定义,使用相同的结构储存,查找和执行
### 定义方式
@ -297,7 +328,7 @@ letter shell 支持使用命令导出方式和命令表方式进行命令的添
### 定义宏说明
letter shell 3.0对可执行命令,按键,用户以及变量分别提供了一个宏,用于进行命令定义
letter shell 3.x对可执行命令,按键,用户以及变量分别提供了一个宏,用于进行命令定义
1. 可执行命令定义
@ -315,8 +346,8 @@ letter shell 3.0对可执行命令,按键,用户以及变量分别提供了
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
const ShellCommand \
shellCommand##_name SECTION("shellCommand") = \
SHELL_USED const ShellCommand \
shellCommand##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.cmd.name = shellCmd##_name, \
@ -341,8 +372,8 @@ letter shell 3.0对可执行命令,按键,用户以及变量分别提供了
#define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
const ShellCommand \
shellVar##_name SECTION("shellCommand") = \
SHELL_USED const ShellCommand \
shellVar##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.var.name = shellCmd##_name, \
@ -370,8 +401,8 @@ letter shell 3.0对可执行命令,按键,用户以及变量分别提供了
const char shellCmd##_name[] = #_name; \
const char shellPassword##_name[] = #_password; \
const char shellDesc##_name[] = #_desc; \
const ShellCommand \
shellUser##_name SECTION("shellCommand") = \
SHELL_USED const ShellCommand \
shellUser##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \
.data.user.name = shellCmd##_name, \
@ -395,8 +426,8 @@ letter shell 3.0对可执行命令,按键,用户以及变量分别提供了
*/
#define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) \
const char shellDesc##_value[] = #_desc; \
const ShellCommand \
shellKey##_value SECTION("shellCommand") = \
SHELL_USED const ShellCommand \
shellKey##_value SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \
.data.key.value = _value, \
@ -431,7 +462,7 @@ union
## 代理函数和代理参数解析
letter shell 3.0原生支持将整数字符字符串参数以及在某些情况下的浮点参数直接传递给执行命令的函数一般情况下这几种参数类型完全可以满足调试需要然而在某些情况下用户确实需要传递其他类型的参数此时可以选择将命令定义成main函数形式使用字符串传递参数然后自行对参数进行解析除此之外letter shell还提供了代理函数的机制可以对任意类型的参数进行自定义解析
letter shell 3.x原生支持将整数字符字符串参数以及在某些情况下的浮点参数直接传递给执行命令的函数一般情况下这几种参数类型完全可以满足调试需要然而在某些情况下用户确实需要传递其他类型的参数此时可以选择将命令定义成main函数形式使用字符串传递参数然后自行对参数进行解析除此之外letter shell还提供了代理函数的机制可以对任意类型的参数进行自定义解析
关于代理函数的实现原理和具体使用示例,可以参考[letter-shell代理函数解析](https://nevermindzzt.github.io/2020/04/17/letter-shell%E4%BB%A3%E7%90%86%E5%87%BD%E6%95%B0%E8%A7%A3%E6%9E%90/)
@ -453,7 +484,51 @@ p1, SHELL_PARAM_FLOAT(p2), p3, SHELL_PARAM_FLOAT(p4));
## 权限系统说明
letter shell 3.0的权限管理同用户定义紧密相关letter shell 3.0使用8个bit位表示命令权限当用户和命令的权限按位与为真或者命令权限为0时表示该用户拥有此命令的权限可以调用改命令
letter shell 3.x的权限管理同用户定义紧密相关letter shell 3.x使用8个bit位表示命令权限当用户和命令的权限按位与为真或者命令权限为0时表示该用户拥有此命令的权限可以调用该命令
## 锁说明
letter shell 3.1增加了shell锁主要目的是为了防止shell输出和其他输入(比如说日志)对终端的竞争导致输出混乱的现象如果使用场景中没有出现终端输出混乱的情况可以不使用shell锁
注意: 请使用支持嵌套的锁
1. 使能宏并实现锁
使能`SHELL_USING_LOCK`实现shell上锁和解锁函数函数原型如下
```c
/**
* @brief shell上锁
*
* @param struct shell_def shell对象
*
* @return 0
*/
typedef int (*shellLock)(struct shell_def *);
/**
* @brief shell解锁
*
* @param struct shell_def shell对象
*
* @return 0
*/
typedef int (*shellLock)(struct shell_def *);
```
2. 使用锁
在可能产生终端竞争的地方加上shell锁比如如果调用`shellPrint`进行格式化输出
```C
SHELL_LOCK(shell);
shellPrint(shell, ...);
SHELL_UNLOCK(shell);
```
3. 注意
- 不要在shell命令中调用shell锁除非实现的shell锁为可嵌套的锁
## 伴生对象
@ -467,7 +542,7 @@ letter shell 3.0.4版本新增了尾行模式适用于需要在shell所使用
使用letter shell尾行模式结合[log](./extensions/log/readme.md)日志输出的效果如下:
![end lin mode](doc/img/shell_end_line_mode.gif)
![end line mode](doc/img/shell_end_line_mode.gif)
## 建议终端软件
@ -475,10 +550,22 @@ letter shell 3.0.4版本新增了尾行模式适用于需要在shell所使用
## 命令遍历工具
letter shell 3.0提供了一个用于遍历工程中命令导出的工具位于tools/shellTools.py需要python3环境运行可以列出工程中所有使用`SHELL_EXPORT_XXX`导出的命令名以及位置结合VS Code可以直接进行跳转
letter shell 3.x提供了一个用于遍历工程中命令导出的工具位于tools/shellTools.py需要python3环境运行可以列出工程中所有使用`SHELL_EXPORT_XXX`导出的命令名以及位置结合VS Code可以直接进行跳转
```sh
python shellTools.py project
```
注意shellTools会遍历指定目录中所有文件所以当工程中文件较多时速度会比较慢建议只用于遍历用户模块的目录
## x86 demo
letter shell 3.x提供了一个x86的demo可以直接编译运行其中包含了一条按键键值测试命令可以测试按键键值用于快捷键的定义编译运行方法如下
```sh
mv src/shell_cfg.h src/shell_cfg.h.bak
cd demo/x86-gcc/
cmake .
make
./LetterShell
```

View File

@ -87,7 +87,7 @@
/**
* @brief shell命令参数最大数量
* 8使
* 16使
*/
#define SHELL_PARAMETER_MAX_NUMBER 8

View File

@ -87,7 +87,7 @@
/**
* @brief shell命令参数最大数量
* 8使
* 16使
*/
#define SHELL_PARAMETER_MAX_NUMBER 8

View File

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.0.0)
project(LetterShell VERSION 0.1.0)
add_executable(LetterShell
main.c
shell_port.c
shell_cpp.cpp
../../src/shell.c
../../src/shell_companion.c
../../src/shell_ext.c
../../extensions/fs_support/shell_fs.c
../../extensions/log/log.c
)
target_include_directories(LetterShell PUBLIC
"${PROJECT_BINARY_DIR}"
../../src
../../extensions/fs_support
../../extensions/cpp_support
../../extensions/log
)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T shell.lds")

View File

@ -1,41 +0,0 @@
all : mkdir out
out : main.o shell_port.o shell.o shell_ext.o shell_cmd_list.o shell_companion.o shell_fs.o shell_cmd_group.o shell_cpp.o
gcc -o build/out -T shell.lds build/main.o build/shell_port.o \
build/shell.o build/shell_ext.o build/shell_cmd_list.o \
build/shell_companion.o build/shell_fs.o build/shell_cmd_group.o \
build/shell_cpp.o
main.o : main.c shell_port.h
gcc -c main.c -I ./ -I ../../src -o build/main.o
shell_port.o : shell_port.c ../../src/shell.h ../../extensions/fs_support/shell_fs.h
gcc -c shell_port.c -I ./ -I ../../src -I ../../extensions/fs_support -o build/shell_port.o
shell.o : ../../src/shell.c ../../src/shell.h shell_cfg.h
gcc -c ../../src/shell.c -I ./ -I ../../src -o build/shell.o
shell_ext.o : ../../src/shell_ext.c ../../src/shell_ext.h ../../src/shell.h shell_cfg.h
gcc -c ../../src/shell_ext.c -I ./ -I ../../src -o build/shell_ext.o
shell_cmd_list.o : ../../src/shell_cmd_list.c ../../src/shell.h shell_cfg.h
gcc -c ../../src/shell_cmd_list.c -I ./ -I ../../src -o build/shell_cmd_list.o
shell_companion.o : ../../src/shell_companion.c ../../src/shell.h shell_cfg.h
gcc -c ../../src/shell_companion.c -I ./ -I ../../src -o build/shell_companion.o
shell_fs.o : ../../extensions/fs_support/shell_fs.c ../../extensions/fs_support/shell_fs.h shell_cfg.h ../../src/shell.h
gcc -c ../../extensions/fs_support/shell_fs.c -I ./ -I ../../src -I ../../extensions/fs_support -o build/shell_fs.o
shell_cmd_group.o : ../../extensions/shell_enhance/shell_cmd_group.c ../../extensions/shell_enhance/shell_cmd_group.h shell_cfg.h ../../src/shell.h
gcc -c ../../extensions/shell_enhance/shell_cmd_group.c -I ./ -I ../../src -I ../../extensions/shell_enhance -o build/shell_cmd_group.o
shell_cpp.o : shell_cpp.cpp ../../extensions/cpp_support/shell_cpp.h
g++ -c shell_cpp.cpp -I ./ -I ../../src -I ../../extensions/cpp_support -o build/shell_cpp.o
.PHONY : all clean mkdir
clean :
-rm -r build
mkdir :
if [ ! -d "build" ]; then (mkdir build) fi

View File

@ -126,6 +126,12 @@
*/
#define SHELL_GET_TICK() 0
/**
* @brief 使
* @note 使shell锁时
*/
#define SHELL_USING_LOCK 0
/**
* @brief shell内存分配
* shell本身不需要此接口使shell伴生对象

View File

@ -11,6 +11,7 @@
#include "shell.h"
#include "shell_fs.h"
#include "log.h"
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
@ -21,15 +22,39 @@ Shell shell;
char shellBuffer[512];
ShellFs shellFs;
char shellPathBuffer[512] = "/";
Log log = {
.active = 1,
.level = LOG_DEBUG
};
/**
* @brief
*
* @param buffer
* @param len
*
*/
void terminalLogWrite(char *buffer, short len)
{
if (log.shell)
{
shellWriteEndLine(log.shell, buffer, len);
}
}
/**
* @brief shell写
*
* @param data
*/
void userShellWrite(char data)
unsigned short userShellWrite(char *data, unsigned short len)
{
putchar(data);
unsigned short length = len;
while (length--)
{
putchar(*data++);
}
return len;
}
/**
@ -38,16 +63,36 @@ void userShellWrite(char data)
* @param data
* @return char
*/
signed char userShellRead(char *data)
unsigned short userShellRead(char *data, unsigned short len)
{
unsigned short length = len;
system("stty -echo");
system("stty -icanon");
*data = getchar();
while (length--)
{
*data++ = getchar();
}
system("stty icanon");
system("stty echo");
return len;
}
#if SHELL_USING_LOCK == 1
static int lockCount = 0;
int userShellLock(struct shell_def *shell)
{
printf("lock: %d\r\n", lockCount);
return 0;
}
int userShellUnlock(struct shell_def *shell)
{
printf("unlock: %d\r\n", lockCount);
return 0;
}
#endif
/**
* @brief
*
@ -85,9 +130,19 @@ void userShellInit(void)
shell.write = userShellWrite;
shell.read = userShellRead;
#if SHELL_USING_LOCK == 1
shell.lock = userShellLock;
shell.unlock = userShellUnlock;
#endif
shellSetPath(&shell, shellPathBuffer);
shellInit(&shell, shellBuffer, 512);
shellCompanionAdd(&shell, SHELL_COMPANION_ID_FS, &shellFs);
log.write = terminalLogWrite;
logRegister(&log, &shell);
logDebug("hello world");
logHexDump(LOG_ALL_OBJ, LOG_DEBUG, (void *)&shell, sizeof(shell));
}
@ -138,7 +193,7 @@ void shellKeyTest(void)
SHELL_ASSERT(shell && shell->read, return);
while (1)
{
if (shell->read(&data) == 0)
if (shell->read(&data, 1) == 1)
{
if (data == '\n' || data == '\r')
{

View File

@ -74,8 +74,8 @@ typedef struct shell_command_cpp_key
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
extern "C" const ShellCommandCppCmd \
shellCommand##_name SECTION("shellCommand") = \
extern "C" SHELL_USED const ShellCommandCppCmd \
shellCommand##_name SHELL_SECTION("shellCommand") = \
{ \
_attr, \
shellCmd##_name, \
@ -95,8 +95,8 @@ typedef struct shell_command_cpp_key
#define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
extern "C" const ShellCommandCppVar \
shellVar##_name SECTION("shellCommand") = \
extern "C" SHELL_USED const ShellCommandCppVar \
shellVar##_name SHELL_SECTION("shellCommand") = \
{ \
_attr, \
shellCmd##_name, \
@ -117,8 +117,8 @@ typedef struct shell_command_cpp_key
const char shellCmd##_name[] = #_name; \
const char shellPassword##_name[] = #_password; \
const char shellDesc##_name[] = #_desc; \
extern "C" const ShellCommandCppUser \
shellUser##_name SECTION("shellCommand") = \
extern "C" SHELL_USED const ShellCommandCppUser \
shellUser##_name SHELL_SECTION("shellCommand") = \
{ \
_attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \
shellCmd##_name, \
@ -137,9 +137,9 @@ typedef struct shell_command_cpp_key
*/
#define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) \
const char shellDesc##_value[] = #_desc; \
extern "C" const ShellCommandCppKey \
shellKey##_value SECTION("shellCommand") = \
{ \
extern "C" SHELL_USED const ShellCommandCppKey \
shellKey##_value SHELL_SECTION("shellCommand") = \
{ \
_attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \
_value, \
(void (*)(Shell *))_func, \

View File

@ -16,10 +16,11 @@
#if LOG_USING_COLOR == 1
#define memPrintHead CSI(31) \
" Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" \
CSI(39)
CSI(39) \
"\r\n"
#define memPrintAddr CSI(31)"0x%08x: "CSI(39)
#else
#define memPrintHead " Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"
#define memPrintHead " Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n"
#define memPrintAddr "0x%08x: "
#endif
@ -92,7 +93,7 @@ logSetLevel, logSetLevel, set log level);
* @param buffer buffer
* @param len buffer长度
*/
void logWriteBuffer(Log *log, LogLevel level, char *buffer, short len)
static void logWriteBuffer(Log *log, LogLevel level, char *buffer, short len)
{
if (log == LOG_ALL_OBJ)
{
@ -137,27 +138,30 @@ void logWrite(Log *log, LogLevel level, char *fmt, ...)
* @brief 16
*
* @param log log对象
* @param level
* @param base
* @param length
*/
void logHexDump(Log *log, void *base, unsigned int length)
void logHexDump(Log *log, LogLevel level, void *base, unsigned int length)
{
unsigned char *address;
unsigned int len = length;
unsigned int len;
unsigned int printLen = 0;
if (length == 0)
if (length == 0 || (log != LOG_ALL_OBJ && log->level < level))
{
return;
}
logWrite(log, LOG_NONE, "memory of 0x%08x, size: %d:\r\n", (unsigned int)base, length);
len = snprintf(logBuffer, LOG_BUFFER_SIZE - 1, "memory of 0x%08x, size: %d:\r\n%s",
(unsigned int)base, length, memPrintHead);
logWriteBuffer(log, level, logBuffer, len);
address = (unsigned char *)((unsigned int)base & (~0x0000000F));
length += (unsigned int)base - (unsigned int)address;
length = (length + 15) & (~0x0000000F);
logWrite(log, LOG_NONE, memPrintHead"\r\n");
len = length;
while (length)
{
@ -200,15 +204,22 @@ void logHexDump(Log *log, void *base, unsigned int length)
logBuffer[printLen ++] = '|';
logBuffer[printLen ++] = '\r';
logBuffer[printLen ++] = '\n';
logWriteBuffer(log, LOG_NONE, logBuffer, printLen);
logWriteBuffer(log, level, logBuffer, printLen);
address += 16;
length -= 16;
printLen = 0;
}
}
#if SHELL_USING_COMPANION == 1
SHELL_EXPORT_CMD_AGENCY(
SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN,
hexdump, logHexDump, hex dump\r\n hexdump [base] [len],
(void *)shellCompanionGet(shellGetCurrent(), SHELL_COMPANION_ID_LOG), LOG_NONE, p1, p2);
#else
SHELL_EXPORT_CMD(
SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN,
hexdump, logHexDump, hex dump\r\n hexdump [log] [base] [len]);
hexdump, logHexDump, hex dump\r\n hexdump [log] [level] [base] [len]);
#endif /** SHELL_USING_COMPANION == 1 */
#if SHELL_USING_COMPANION == 1
void logSwitchLevel(Shell *shell)
@ -219,5 +230,4 @@ void logSwitchLevel(Shell *shell)
logPrintln("set log level: %d", log->level);
}
SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x04000000, logSwitchLevel, switch log level);
#endif /** SHELL_USING_COMPANION == 1 */

View File

@ -13,7 +13,7 @@
#include "shell.h"
#define LOG_VERSION "1.0.0"
#define LOG_VERSION "1.0.1"
#define SHELL_COMPANION_ID_LOG -2
@ -182,10 +182,19 @@ typedef struct
action; \
}
/**
* @brief 16
*
* @param base
* @param length
*/
#define logHexDumpAll(base, length) \
logHexDump(LOG_ALL_OBJ, LOG_ALL, base, length)
void logRegister(Log *log, Shell *shell);
void logUnRegister(Log *log);
void logSetLevel(Log *log, LogLevel level);
void logWrite(Log *log, LogLevel level, char *fmt, ...);
void logHexDump(Log *log, void *base, unsigned int length);
void logHexDump(Log *log, LogLevel level, void *base, unsigned int length);
#endif

View File

@ -1,6 +1,6 @@
# log
![version](https://img.shields.io/badge/version-1.0.0-brightgreen.svg)
![version](https://img.shields.io/badge/version-1.0.1-brightgreen.svg)
![standard](https://img.shields.io/badge/standard-c99-brightgreen.svg)
![build](https://img.shields.io/badge/build-2020.08.02-brightgreen.svg)
![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)
@ -160,11 +160,12 @@ void logSetLevel(Log *log, LogLevel level)
数据16进制打印
```C
void logHexDump(Log *log, void *base, unsigned int length)
void logHexDump(Log *log, LogLevel level, void *base, unsigned int length)
```
- 参数
- `log` log对象
- `level` 日志级别
- `base` 数据基址
- `length` 数据长度

View File

@ -22,7 +22,7 @@
const char shellCmdDefaultUser[] = SHELL_DEFAULT_USER;
const char shellPasswordDefaultUser[] = SHELL_DEFAULT_USER_PASSWORD;
const char shellDesDefaultUser[] = "default user";
const ShellCommand shellUserDefault SECTION("shellCommand") =
SHELL_USED const ShellCommand shellUserDefault SHELL_SECTION("shellCommand") =
{
.attr.value = SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_USER),
.data.user.name = shellCmdDefaultUser,
@ -260,7 +260,7 @@ Shell* shellGetCurrent(void)
*/
static void shellWriteByte(Shell *shell, const char data)
{
shell->write(data);
shell->write(&data, 1);
}
@ -275,13 +275,13 @@ static void shellWriteByte(Shell *shell, const char data)
unsigned short shellWriteString(Shell *shell, const char *string)
{
unsigned short count = 0;
char *p = string;
SHELL_ASSERT(shell->write, return 0);
while(*string)
while(*p++)
{
shell->write(*string ++);
count ++;
}
return count;
return shell->write(string, count);
}
@ -296,22 +296,24 @@ unsigned short shellWriteString(Shell *shell, const char *string)
static unsigned short shellWriteCommandDesc(Shell *shell, const char *string)
{
unsigned short count = 0;
char *p = string;
SHELL_ASSERT(shell->write, return 0);
while(*string
&& *string != '\r'
&& *string != '\n'
&& count < 36)
while (*p && *p != '\r' && *p != '\n')
{
shell->write(*string ++);
count ++;
if (count >= 36 && *(string + 1))
{
shell->write('.');
shell->write('.');
shell->write('.');
}
p++;
count++;
}
return count;
if (count > 36)
{
shell->write(string, 36);
shell->write("...", 3);
}
else
{
shell->write(string, count);
}
return count > 36 ? 36 : 39;
}
@ -385,9 +387,9 @@ void shellScan(Shell *shell, char *fmt, ...)
if (shell->read)
{
do {
if (shell->read(&buffer[index]) == 0)
if (shell->read(&buffer[index], 1) == 1)
{
shell->write(buffer[index]);
shell->write(buffer[index], 1);
index++;
}
} while (buffer[index -1] != '\r' && buffer[index -1] != '\n' && index < SHELL_SCAN_BUFFER);
@ -1660,6 +1662,7 @@ help, shellHelp, show command info\r\nhelp [cmd]);
void shellHandler(Shell *shell, char data)
{
SHELL_ASSERT(data, return);
SHELL_LOCK(shell);
#if SHELL_LOCK_TIMEOUT > 0
if (shell->info.user->data.user.password
@ -1732,20 +1735,20 @@ void shellHandler(Shell *shell, char data)
{
shell->info.activeTime = SHELL_GET_TICK();
}
SHELL_UNLOCK(shell);
}
#if SHELL_SUPPORT_END_LINE == 1
void shellWriteEndLine(Shell *shell, char *buffer, int len)
{
SHELL_LOCK(shell);
if (!shell->status.isActive)
{
shellWriteString(shell, shellText[SHELL_TEXT_CLEAR_LINE]);
}
while (len --)
{
shell->write(*buffer++);
}
shell->write(buffer, len);
if (!shell->status.isActive)
{
shellWriteCommandLine(shell, 0);
@ -1754,10 +1757,11 @@ void shellWriteEndLine(Shell *shell, char *buffer, int len)
shellWriteString(shell, shell->parser.buffer);
for (short i = 0; i < shell->parser.length - shell->parser.cursor; i++)
{
shell->write('\b');
shell->write('\b', 1);
}
}
}
SHELL_UNLOCK(shell);
}
#endif /** SHELL_SUPPORT_END_LINE == 1 */
@ -1776,7 +1780,7 @@ void shellTask(void *param)
while(1)
{
#endif
if (shell->read && shell->read(&data) == 0)
if (shell->read && shell->read(&data, 1) == 1)
{
shellHandler(shell, data);
}
@ -1906,7 +1910,6 @@ int shellExecute(int argc, char *argv[])
if (shell && argc >= 2)
{
int (*func)() = (int (*)())shellExtParsePara(shell, argv[1]);
shellPrint(shell, "%08x\r\n", func);
ShellCommand command = {
.attr.value = SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)
|SHELL_CMD_DISABLE_RETURN,

View File

@ -14,7 +14,7 @@
#include "shell_cfg.h"
#define SHELL_VERSION "3.0.6" /**< 版本号 */
#define SHELL_VERSION "3.1.0" /**< 版本号 */
/**
@ -28,6 +28,13 @@
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
*
@ -68,15 +75,27 @@
#define SHELL_CMD_PARAM_NUM(num) \
((num & 0x0000000F)) << 16
#ifndef SECTION
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000)
#define SECTION(x) __attribute__((used, section(x)))
#elif defined(__ICCARM__) || defined(__ICCRX__)
#define SECTION(x) @ x
#ifndef SHELL_SECTION
#if defined(__CC_ARM) || defined(__CLANG_ARM)
#define SHELL_SECTION(x) __attribute__((section(x)))
#elif defined (__IAR_SYSTEMS_ICC__)
#define SHELL_SECTION(x) @ x
#elif defined(__GNUC__)
#define SECTION(x) __attribute__((section(x)))
#define SHELL_SECTION(x) __attribute__((section(x)))
#else
#define SECTION(x)
#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
@ -113,8 +132,8 @@
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
const ShellCommand \
shellCommand##_name SECTION("shellCommand") = \
SHELL_USED const ShellCommand \
shellCommand##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.cmd.name = shellCmd##_name, \
@ -146,8 +165,8 @@
#define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
const ShellCommand \
shellVar##_name SECTION("shellCommand") = \
SHELL_USED const ShellCommand \
shellVar##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.var.name = shellCmd##_name, \
@ -167,8 +186,8 @@
const char shellCmd##_name[] = #_name; \
const char shellPassword##_name[] = #_password; \
const char shellDesc##_name[] = #_desc; \
const ShellCommand \
shellUser##_name SECTION("shellCommand") = \
SHELL_USED const ShellCommand \
shellUser##_name SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \
.data.user.name = shellCmd##_name, \
@ -186,8 +205,8 @@
*/
#define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) \
const char shellDesc##_value[] = #_desc; \
const ShellCommand \
shellKey##_value SECTION("shellCommand") = \
SHELL_USED const ShellCommand \
shellKey##_value SHELL_SECTION("shellCommand") = \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \
.data.key.value = _value, \
@ -340,8 +359,12 @@ typedef struct shell_def
unsigned char isActive : 1; /**< 当前活动Shell */
unsigned char tabFlag : 1; /**< tab标志 */
} status;
signed char (*read)(char *); /**< shell读函数 */
void (*write)(const char); /**< shell写函数 */
signed short (*read)(char *, unsigned short); /**< shell读函数 */
signed short (*write)(const char *, unsigned short); /**< shell写函数 */
#if SHELL_USING_LOCK == 1
int (*lock)(struct shell_def *); /**< shell 加锁 */
int (*unlock)(struct shell_def *); /**< shell 解锁 */
#endif
} Shell;

View File

@ -85,7 +85,7 @@
/**
* @brief shell命令参数最大数量
* 8使
* 16使
*/
#define SHELL_PARAMETER_MAX_NUMBER 8
@ -125,6 +125,12 @@
*/
#define SHELL_GET_TICK() 0
/**
* @brief 使
* @note 使shell锁时
*/
#define SHELL_USING_LOCK 0
/**
* @brief shell内存分配
* shell本身不需要此接口使shell伴生对象