Skip to content

Commit

Permalink
Merge pull request #92 from NevermindZZT/shell3.1
Browse files Browse the repository at this point in the history
Shell3.1.1
  • Loading branch information
NevermindZZT authored Jun 27, 2021
2 parents abba67c + a34f08a commit 6d6803e
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 36 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# letter shell 3.x

![version](https://img.shields.io/badge/version-3.1.0-brightgreen.svg)
![version](https://img.shields.io/badge/version-3.1.1-brightgreen.svg)
![standard](https://img.shields.io/badge/standard-c99-brightgreen.svg)
![build](https://img.shields.io/badge/build-2021.05.24-brightgreen.svg)
![build](https://img.shields.io/badge/build-2021.06.27-brightgreen.svg)
![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)

一个功能强大的嵌入式shell
Expand Down Expand Up @@ -165,6 +165,7 @@
| SHELL_PARAMETER_MAX_NUMBER | shell命令参数最大数量 |
| SHELL_HISTORY_MAX_NUMBER | 历史命令记录数量 |
| SHELL_DOUBLE_CLICK_TIME | 双击间隔(ms) |
| SHELL_QUICK_HELP | 快速帮助 |
| SHELL_MAX_NUMBER | 管理的最大shell数量 |
| SHELL_GET_TICK() | 获取系统时间(ms) |
| SHELL_USING_LOCK | 是否使用锁 |
Expand Down Expand Up @@ -283,7 +284,7 @@ letter shell采取一个静态数组对定义的多个shell进行管理,shell
### 执行未导出函数
letter shell支持通过函数地址直接执行函数,可以方便执行那些没有导出,但是有临时需要使用的函数,使用命令`exec [addr] [args]`执行,使用此功能需要开启`SHELL_EXEC_UNDEF_FUNC`宏,注意,由于直接操作函数地址执行,如果给进的地址有误,可能引起程序崩溃
letter shell支持通过函数地址直接执行函数,可以方便执行那些没有导出,但是又临时需要使用的函数,使用命令`exec [addr] [args]`执行,使用此功能需要开启`SHELL_EXEC_UNDEF_FUNC`宏,注意,由于直接操作函数地址执行,如果给进的地址有误,可能引起程序崩溃
函数的地址可以通过编译生成的文件查找,比如说对于keil,可以在`.map`文件中查找到每个函数的地址,对于keil,`.map`文件中的地址需要偏移一个字节,才可以成功执行,比如说`shellClear`函数地址为`0x08028620`,则通过`exec`执行应为`exec 0x08028621`
Expand All @@ -297,7 +298,7 @@ letter shell 3.x将可执行的函数命令定义,用户定义,按键定义
letter shell 支持使用命令导出方式和命令表方式进行命令的添加,定义,通过宏```SHELL_USING_CMD_EXPORT```控制
命令导出方式支持keil,IAR(未测试)以及GCC
命令导出方式支持keil,IAR以及GCC
1. 命令导出方式
Expand Down
9 changes: 8 additions & 1 deletion demo/x86-gcc/shell_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define __SHELL_CFG_H__

#include "stdlib.h"
unsigned int userGetTick();

/**
* @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义
Expand Down Expand Up @@ -101,6 +102,12 @@
*/
#define SHELL_DOUBLE_CLICK_TIME 200

/**
* @brief 快速帮助
* 作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息
*/
#define SHELL_QUICK_HELP 1

/**
* @brief 管理的最大shell数量
*/
Expand All @@ -124,7 +131,7 @@
* 定义此宏为获取系统Tick,如`HAL_GetTick()`
* @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
*/
#define SHELL_GET_TICK() 0
#define SHELL_GET_TICK() userGetTick()

/**
* @brief 使用锁
Expand Down
21 changes: 17 additions & 4 deletions demo/x86-gcc/shell_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <unistd.h>
#include <stddef.h>
#include <string.h>
#include <sys/time.h>

Shell shell;
char shellBuffer[512];
Expand All @@ -28,6 +29,18 @@ Log log = {
.level = LOG_DEBUG
};

/**
* @brief 获取系统tick
*
* @return unsigned int 系统tick
*/
unsigned int userGetTick()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000 + tv.tv_usec / 1000) & 0x7FFFFFFF;
}

/**
* @brief 日志写函数实现
*
Expand Down Expand Up @@ -73,8 +86,8 @@ unsigned short userShellRead(char *data, unsigned short len)
{
*data++ = getchar();
}
system("stty icanon");
system("stty echo");
// system("stty icanon");
// system("stty echo");
return len;
}

Expand Down Expand Up @@ -142,8 +155,8 @@ void userShellInit(void)
log.write = terminalLogWrite;
logRegister(&log, &shell);

logDebug("hello world");
logHexDump(LOG_ALL_OBJ, LOG_DEBUG, (void *)&shell, sizeof(shell));
// logDebug("hello world");
// logHexDump(LOG_ALL_OBJ, LOG_DEBUG, (void *)&shell, sizeof(shell));
}


Expand Down
15 changes: 8 additions & 7 deletions extensions/shell_enhance/shell_passthrough.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,21 @@ unsigned int shellPassthrough(Shell *shell, const char *prompt, ShellPassthrough
{
if (data == '\r' || data == '\n')
{
if (shell->parser.length == 0)
shellWriteString(shell, "\r\n");
if (shell->parser.length != 0)
{
continue;
shell->parser.buffer[shell->parser.length] = 0;
handler(shell->parser.buffer, shell->parser.length);
shell->parser.length = 0;
shell->parser.cursor = 0;
}
shellWriteString(shell, "\r\n");
shell->parser.buffer[shell->parser.length] = 0;
handler(shell->parser.buffer, shell->parser.length);
shell->parser.length = 0;
shell->parser.cursor = 0;
shellWriteString(shell, prompt);
}
else if (data == SHELL_PASSTHROUGH_EXIT_KEY)
{
shellWriteString(shell, "\r\n");
shell->parser.length = 0;
shell->parser.cursor = 0;
return -1;
}
else
Expand Down
65 changes: 46 additions & 19 deletions src/shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ ShellCommand* shellSeekCommand(Shell *shell,
const char *cmd,
ShellCommand *base,
unsigned short compareLength);
static void shellWriteCommandHelp(Shell *shell, char *cmd);

/**
* @brief shell 初始化
Expand All @@ -168,18 +169,21 @@ void shellInit(Shell *shell, char *buffer, unsigned short size)
{
shell->parser.length = 0;
shell->parser.cursor = 0;
shell->history.offset = 0;
shell->history.number = 0;
shell->history.record = 0;
shell->info.user = NULL;
shell->status.isChecked = 1;

shell->parser.buffer = buffer;
shell->parser.bufferSize = size / (SHELL_HISTORY_MAX_NUMBER + 1);

#if SHELL_HISTORY_MAX_NUMBER > 0
shell->history.offset = 0;
shell->history.number = 0;
shell->history.record = 0;
for (short i = 0; i < SHELL_HISTORY_MAX_NUMBER; i++)
{
shell->history.item[i] = buffer + shell->parser.bufferSize * (i + 1);
}
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */

#if SHELL_USING_CMD_EXPORT == 1
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000)
Expand Down Expand Up @@ -1271,6 +1275,7 @@ static void shellWriteReturnValue(Shell *shell, int value)
}


#if SHELL_HISTORY_MAX_NUMBER > 0
/**
* @brief shell历史记录添加
*
Expand Down Expand Up @@ -1350,6 +1355,7 @@ static void shellHistory(Shell *shell, signed char dir)
}

}
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */


/**
Expand Down Expand Up @@ -1382,7 +1388,9 @@ void shellExec(Shell *shell)

if (shell->status.isChecked)
{
#if SHELL_HISTORY_MAX_NUMBER > 0
shellHistoryAdd(shell);
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
shellParserParam(shell);
shell->parser.length = shell->parser.cursor = 0;
if (shell->parser.paramCount == 0)
Expand Down Expand Up @@ -1411,6 +1419,7 @@ void shellExec(Shell *shell)
}


#if SHELL_HISTORY_MAX_NUMBER > 0
/**
* @brief shell上方向键输入
*
Expand All @@ -1433,6 +1442,7 @@ void shellDown(Shell *shell)
shellHistory(shell, -1);
}
SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x1B5B4200, shellDown, down);
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */


/**
Expand Down Expand Up @@ -1543,6 +1553,12 @@ void shellTab(Shell *shell)
&& shell->status.tabFlag
&& SHELL_GET_TICK() - shell->info.activeTime < SHELL_DOUBLE_CLICK_TIME)
{
#if SHELL_QUICK_HELP == 1
shellWriteString(shell, "\r\n");
shellWriteCommandHelp(shell, shell->parser.buffer);
shellWritePrompt(shell, 1);
shellWriteString(shell, shell->parser.buffer);
#else
shellClearCommandLine(shell);
for (short i = shell->parser.length; i >= 0; i--)
{
Expand All @@ -1553,6 +1569,7 @@ void shellTab(Shell *shell)
shell->parser.length += 5;
shell->parser.cursor = shell->parser.length;
shellWriteString(shell, shell->parser.buffer);
#endif
}
else
{
Expand Down Expand Up @@ -1614,6 +1631,31 @@ SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
0x0D0A0000, shellEnter, enter);
#endif

/**
* @brief shell 写命令帮助信息
*
* @param shell shell对象
* @param cmd 命令字符串
*/
static void shellWriteCommandHelp(Shell *shell, char *cmd)
{
ShellCommand *command = shellSeekCommand(shell,
cmd,
shell->commandList.base,
0);
if (command)
{
shellWriteString(shell, shellText[SHELL_TEXT_HELP_HEADER]);
shellWriteString(shell, shellGetCommandName(command));
shellWriteString(shell, "\r\n");
shellWriteString(shell, shellGetCommandDesc(command));
shellWriteString(shell, "\r\n");
}
else
{
shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]);
}
}

/**
* @brief shell help
Expand All @@ -1631,22 +1673,7 @@ void shellHelp(int argc, char *argv[])
}
else if (argc > 1)
{
ShellCommand *command = shellSeekCommand(shell,
argv[1],
shell->commandList.base,
0);
if (command)
{
shellWriteString(shell, shellText[SHELL_TEXT_HELP_HEADER]);
shellWriteString(shell, shellGetCommandName(command));
shellWriteString(shell, "\r\n");
shellWriteString(shell, shellGetCommandDesc(command));
shellWriteString(shell, "\r\n");
}
else
{
shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]);
}
shellWriteCommandHelp(shell, argv[1]);
}
}
SHELL_EXPORT_CMD(
Expand Down
4 changes: 3 additions & 1 deletion src/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#include "shell_cfg.h"

#define SHELL_VERSION "3.1.0" /**< 版本号 */
#define SHELL_VERSION "3.1.1" /**< 版本号 */


/**
Expand Down Expand Up @@ -341,13 +341,15 @@ typedef struct shell_def
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; /**< 命令表基址 */
Expand Down
7 changes: 7 additions & 0 deletions src/shell_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@
*/
#define SHELL_DOUBLE_CLICK_TIME 200

/**
* @brief 快速帮助
* 作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息
*/
#define SHELL_QUICK_HELP 1


/**
* @brief 管理的最大shell数量
*/
Expand Down

0 comments on commit 6d6803e

Please sign in to comment.