letterShell 工程解析

letter shell

码云地址

1. 文件结构分析

letterShell 工程解析_第1张图片

  1. shell_cfg.h
    配置文件,用于管理整个 letterShell 工程的相关配置,包括是否使用task任务,是否使用导出功能,触发方式,双击键盘有效时间间隔等设置。
  2. shell_cmd_list.c
    shell的静态命令列表,在工程初始化时创建,
    使用 shell_cfg.h 中的 SHELL_USING_CMD_EXPORT 宏进行控制,如果 #define SHELL_USING_CMD_EXPORT 0 的话,则生成 shell 命令表。
  3. shell_ext
    用于数据类型解析、转换,命令执行
  4. shell
    本工程的主要函数文件都在此文件内,本节也主要分析这个文件。

2. shell.c 文件分析

  1. shell 初始化
void shellInit(Shell *shell, char *buffer, unsigned short size)
{
    // 初始化参数
    shell->parser.length = 0;
    shell->parser.cursor = 0;
    ......
    // 设置 shell 所使用的  buffer 空间
    shell->parser.buffer = buffer;
    // 设置每个 buffer 空间大小,具体算法为 总大小 / (历史条数+1)  此处的1为当前使用的buffer大小
    shell->parser.bufferSize = size / (SHELL_HISTORY_MAX_NUMBER + 1);
    for (short i = 0; i < SHELL_HISTORY_MAX_NUMBER; i++)
    {
        // 设置每个历史buffer的位置,第一个buffer为当前使用位置,所以不设置
        shell->history.item[i] = buffer + shell->parser.bufferSize * (i + 1);
    }
    ......
 	// 设置命令列表基地址和命令列表大小   
    shell->commandList.base = (ShellCommand *)shellCommandList;
    shell->commandList.count = shellCommandCount;
	.......
	
    // 创建shell
    shellAdd(shell);

	// 设置当前用户。当前用户为 SHELL_DEFAULT_USER 对应的用户名称
    shellSetUser(shell, shellSeekCommand(shell,
                                         SHELL_DEFAULT_USER,
                                         shell->commandList.base,
                                         0));
	// 开启shell第一个输出
    shellWriteCommandLine(shell);
}
  1. 运行 shellTask 函数
void shellTask(void *param)
{
	// 当前shell由形参传入,可以用于不同串口执行不同用户。
    Shell *shell = (Shell *)param;
    char data;
    // 由 shell_cfg.h 中的 SHELL_TASK_WHILE 控制是否在 shellTask 中执行 while(1) 操作
#if SHELL_TASK_WHILE == 1
    while(1)
    {
#endif
        if (shell->read && shell->read(&data) == 0)
        {
            // 如果有字符读取,则执行句柄函数。解析当前buffer区域的数据。
            shellHandler(shell, data);
        }
#if SHELL_TASK_WHILE == 1
    }
#endif
}
  1. shellHandler函数
void shellHandler(Shell *shell, char data)
{
    SHELL_ASSERT(data, return);

#if SHELL_LOCK_TIMEOUT > 0
    // 用户加锁的条件为  用户设置密码 且 设置有获取时间的借口 SHELL_GET_TICK() 如果和上次的字符输入时间相差超过 LOCK_TIMEOUT 时间,则认为用户被锁。
    if (shell->info.user->data.user.password
        && strlen(shell->info.user->data.user.password) != 0
        && SHELL_GET_TICK())
    {
        if (SHELL_GET_TICK() - shell->info.activeTime > SHELL_LOCK_TIMEOUT)
        {
            shell->status.isChecked = 0;
        }
    }
#endif

    /* 根据记录的按键键值计算当前字节在按键键值中的偏移 */
	......
	
    /* 遍历ShellCommand列表,尝试进行按键键值匹配 */
    /* 匹配之后,执行所对应的函数 */
    ......
    
    if (data != 0x00)
    {
    	// 执行回显功能
        shellNormalInput(shell, data);
    }

    if (SHELL_GET_TICK())
    {
        // 由于有字符输入,则需要更新时间
        shell->info.activeTime = SHELL_GET_TICK();
    }
}
  1. 针对每个按键所对应的函数功能,在 SHELL_EXPORT_KEY 宏定义都可以看到按键所对应的键值和函数。

你可能感兴趣的:(letterShell)