芯源半导体CW32
直播中

郭学深

3年用户 35经验值
擅长:嵌入式技术,处理器/DSP,控制/MCU
私信 关注

【CW32饭盒派开发板试用体验】+ 串口letter-shell 移植

本次主要移植letter-shell过程。
letter shell是一个C语言编写的,可以嵌入在程序中的嵌入式shell,主要面向嵌入式设备,以C语言函数为运行单位,可以通过命令行调用,运行程序中的函数。letter shell 增加了用户管理,权限管理,以及对文件系统的初步支持。

功能:

  • 命令自动补全
  • 快捷键功能定义
  • 命令权限管理
  • 用户管理
  • 变量支持
  • 代理函数和参数代理解析

下面说说移植。
首先调通串口发送接收数据。新建CW32的port接口文件。letter-shell的配置文件。

/**
 * [url=home.php?mod=space&uid=1455510]@file[/url] shell_cfg_user.h
 * [url=home.php?mod=space&uid=40524]@author[/url] Letter (nevermindzzt@gmail.com)
 * [url=home.php?mod=space&uid=2666770]@Brief[/url] shell config
 * [url=home.php?mod=space&uid=644434]@version[/url] 3.0.0
 * @date 2019-12-31
 * 
 * @copyright (c) 2019 Letter
 * 
 */

#ifndef __SHELL_CFG_USER_H__
#define __SHELL_CFG_USER_H__

#include "main.h"

#if 0
#define     SHELL_TASK_WHILE                //是否使用默认shell任务while循环 
#define     SHELL_USING_CMD_EXPORT          //是否使用命令导出方式 
#define     SHELL_USING_COMPANION           //是否使用shell伴生对象功能 
#define     SHELL_SUPPORT_END_LINE          //是否支持shell尾行模式 
#define     SHELL_HELP_LIST_USER            //是否在输入命令列表中列出用户 
#define     SHELL_HELP_LIST_VAR             //是否在输入命令列表中列出变量 
#define     SHELL_HELP_LIST_KEY             //是否在输入命令列表中列出按键 
#define     SHELL_ENTER_LF                  //使用LF作为命令行回车触发 
#define     SHELL_ENTER_CR                  //使用CR作为命令行回车触发 
#define     SHELL_ENTER_CRLF                //使用CRLF作为命令行回车触发 
#define     SHELL_EXEC_UNDEF_FUNC           //使用执行未导出函数的功能 
#define     SHELL_COMMAND_MAX_LENGTH        //shell命令最大长度 
#define     SHELL_PARAMETER_MAX_NUMBER      //shell命令参数最大数量 
#define     SHELL_HISTORY_MAX_NUMBER        //历史命令记录数量 
#define     SHELL_DOUBLE_CLICK_TIME         //双击间隔(ms) 
#define     SHELL_QUICK_HELP                //快速帮助 
#define     SHELL_MAX_NUMBER                //管理的最大shell数量 
#define     SHELL_GET_TICK()                //获取系统时间(ms) 
#define     SHELL_USING_LOCK                //是否使用锁 
#define     SHELL_MALLOC(size)              //内存分配函数(shell本身不需要) 
#define     SHELL_FREE(obj)                 //内存释放函数(shell本身不需要) 
#define     SHELL_SHOW_INFO                 //是否显示shell信息 
#define     SHELL_CLS_WHEN_LOGIN            //是否在登录后清除命令行 
#define     SHELL_DEFAULT_USER              //shell默认用户 
#define     SHELL_DEFAULT_USER_PASSWORD     //默认用户密码 
#define     SHELL_LOCK_TIMEOUT              //shell自动锁定超时 

#endif

/**
 * @brief 是否使用shell伴生对象
 *        一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象
 */
#define     SHELL_USING_COMPANION       1


/**
 * @brief 支持shell尾行模式
 */
#define     SHELL_SUPPORT_END_LINE      1


/**
 * @brief 使用LF作为命令行回车触发
 *        可以和SHELL_ENTER_CR同时开启
 */
#define     SHELL_ENTER_LF              1

/**
 * @brief 使用CR作为命令行回车触发
 *        可以和SHELL_ENTER_LF同时开启
 */
#define     SHELL_ENTER_CR              1

/**
 * @brief 使用CRLF作为命令行回车触发
 *        不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启
 */
#define     SHELL_ENTER_CRLF            0

/**
 * @brief shell格式化输入的缓冲大小
 *        为0时不使用shell格式化输入
 * @note shell格式化输入会阻塞shellTask, 仅适用于在有操作系统的情况下使用
 */
//#define     SHELL_SCAN_BUFFER          0

/**
 * @brief 获取系统时间(ms)
 *        定义此宏为获取系统Tick,如`HAL_GetTick()`
 * @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
 */
//#define     SHELL_GET_TICK()            HAL_GetTick()

/**
 * @brief 使用锁
 * @note 使用shell锁时,需要对加锁和解锁进行实现
 */
//#define     SHELL_USING_LOCK            0

/**
 * @brief shell内存分配
 *        shell本身不需要此接口,若使用shell伴生对象,需要进行定义
 */
#define     SHELL_MALLOC(size)          malloc(size)

/**
 * @brief shell内存释放
 *        shell本身不需要此接口,若使用shell伴生对象,需要进行定义
 */
#define     SHELL_FREE(obj)             free(obj)
#endif

letter-shell发送接收函数接口初始化。

/**
 * @file shell_port.c
 * @author Letter (NevermindZZT@gmail.com)
 * @brief 
 * @version 0.1
 * @date 2019-02-22
 * 
 * @copyright (c) 2019 Letter
 * 
 */

#include "shell_cfg_user.h"
#include "drv_uart.h"
#include "shell.h"


Shell shell;
char shellBuffer[512];


/**
 * @brief 用户shell写
 * 
 * @param data 数据
 * @param len 数据长度
 * 
 * @return short 实际写入的数据长度
 */
short userShellWrite(char *data, unsigned short len)
{
    for(uint32_t i=0;i<len;i++)
        stdout_putchar(data[i]);
    return len;
}


/**
 * @brief 用户shell读
 * 
 * @param data 数据
 * @param len 数据长度
 * 
 * @return short 实际读取到
 */
short userShellRead(char *data, unsigned short len)
{
    uint32_t rlen = 0;
    for(uint32_t i=0;i<len;i++)
    {
        if(shell_uart_rx.read_i != shell_uart_rx.write_i)
        {
            data[rlen++] = shell_uart_rx.buff[shell_uart_rx.read_i++];
            shell_uart_rx.read_i &= 0x7f;
        }
    }
    return rlen;
}

/**
 * @brief 用户shell上锁
 * 
 * @param shell shell
 * 
 * @return int 0
 */
int userShellLock(Shell *shell)
{
    return 0;
}

/**
 * @brief 用户shell解锁
 * 
 * @param shell shell
 * 
 * @return int 0
 */
int userShellUnlock(Shell *shell)
{
    return 0;
}

/**
 * @brief 用户shell初始化
 * 
 */
void userShellInit(void)
{
    shell.write = userShellWrite;
    shell.read = userShellRead;
//    shell.lock = userShellLock;
//    shell.unlock = userShellUnlock;
    shellInit(&shell, shellBuffer, 512);

}

下面是对接串口。
首先main中初始化shell。
userShellInit(); //letter shell
然后在main的主循环中调用,处理输入的字符。

void uart_shell_loop(void)
{
    if(shell_uart_rx.read_i != shell_uart_rx.write_i)
    {
            shellHandler(&shell, shell_uart_rx.buff[shell_uart_rx.read_i++]); //letter shell
            shell_uart_rx.read_i &= 0x7f;
    }
}

这样基本就移植完成了。
下面就是 添加测试的函数和测试用户方法。

//测试添加用户:
SHELL_EXPORT_USER(SHELL_CMD_PERMISSION(0x01), root, 123456, add user);

下面是添加函数的2种方式。

//测试添加mian命令
int func(int argc, char *argv[])
{
    printf("%d parameter(s)\r\n", argc);
    for (char i = 1; i < argc; i++)
    {
        printf("%s\r\n", argv[i]);
    }
    return  0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0x01)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), func, func, test1);
//letter:/$ func "hello world"
//2 parameter(s)
//hello world
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0x02)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), func2, func, test2);
//func加到新的root用户权限在。

//测试添加func命令
int func1(int i, char ch, char *str)
{
    printf("input int: %d, char: %c, string: %s\r\n", i, ch, str);
    return  0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), func1, func1, test3);
//letter:/$ func1 666 'A' "hello world"
//input int: 666, char: A, string: hello world

测试letter-shell输出。更换用户直接输入用户名即可。如果设置了用户密码就需要输入密码才能进入。
image.png
上面是默认的letter用户权限函数

image.png

上面是新加的root用户权限函数。
测试新加命令。

image.png

移植工程:
image.png

*附件:Demo.rar

更多回帖

发帖
×
20
完善资料,
赚取积分