1992|1

504

帖子

4

TA的资源

纯净的硅(高级)

楼主
 

【RTT&英飞凌PSoC6评估板(带触摸)】CLI命令行实现 [复制链接]

前言

前面我们进行了串口的测试,参考

https://bbs.eeworld.com.cn/thread-1247060-1-1.html

https://bbs.eeworld.com.cn/thread-1247447-1-1.html

为了方便后续调试,我们现在来实现简单SHELL命令行。

 

过程

 

首先需要实现串口收发接口

int uart_read(uint8_t* buffer, uint32_t len)

{

    if (cyhal_uart_getc(&cy_retarget_io_uart_obj, buffer, len)

         == CY_RSLT_SUCCESS)

    {

     return len;

    }

    else

    {

     return 0;

    }

}

 

 

int uart_write(uint8_t* buffer, uint32_t len)

{

while(len--)

{

cyhal_uart_putc(&cy_retarget_io_uart_obj, *buffer++);

}

}

 

 

Shell.c中实现和putchar,putchar已经重定向实现了所以不需要实现,否则可以改为uart_write

/**

 *****************************************************************************

 * \fn          static int shell_getchar(unsigned char *data)

 * \brief       读取一个字符.

 * \note        .

 * \param[out]  data 存储读到的数据.

 * retval       0  成功.

 * retval       -1 失败.

 *****************************************************************************

 */

static int shell_getchar(unsigned char *data)

{

    int erro=0;

    //driver_uart_recv(getstdiouart(), data, 1,10,&erro);

  if(0 == uart_read(data, 1))

{

erro = 1;

}

  else

  {

  uart_write(data,1);

  }

    if(erro!=0)

    {

        return -1;

    }

    return 0;

}

 

核心数据结构

typedef void ( * CommandFunc )( void *);   /**< shell命令回调函数 */

 

/**

 * \struct shell_cmd_cfg

 * SHELL命令结构体.

 */

typedef struct

{

    unsigned char const* name;           /**< shell命令名 */

    CommandFunc func;           /**< shell命令回调函数 */

    char const* helpstr;       /**< 帮助字符串 */

}shell_cmd_cfg;

 

 

定义表格

const shell_cmd_cfg shell_cmd_list[ ] =

{

  /*1.帮助相关*/

  { (const uint8_t*)"help",         HelpFun,         "help"},                 /*打印帮助信息*/

  { 0, 0 },

};

 

 

接收到命令行时搜索shell_cmd_list比对name命令名,如果比对上则调用函数func执行。

 

读一行命令关键代码

static unsigned int shell_read_line(int get(unsigned char* tmp))

{

    unsigned char ch = '\r';

    unsigned int count;

    unsigned char tmp;

    /*开始打印一次"sh>"*/

    if(cmd_buf[0]=='\r')

    {

        printf("sh>\r\n");

        memset(cmd_buf,0x00,sizeof(cmd_buf));

    }

    /*如果接收到字符往下走,否则返回*/

    if(get(&tmp)==0)

    {

        ch = tmp;

    }

    else

    {

        return 0;

    }

    /*如果接收到非打印字符且当前接收缓冲区不为0则认为接收到一帧否则打印"SH>"*/

    if((ch == '\r' || ch == '\n' || ch < ' ' || ch > '~') && (ch != '\b'))

    {

        if(cmd_buf_index==0)

        {

            printf("sh>\r\n");

        }

        else

        {

            count = cmd_buf_index;

            cmd_buf[cmd_buf_index]=0;

            cmd_buf_index =0;

            printf("\r\n");

            return count;

        }

    }

    else 

    {

        if(ch == '\b')

        {

            if(cmd_buf_index != 0)

            {

                cmd_buf_index--;

                putchar('\b');

                putchar(' ');

                putchar('\b');

                cmd_buf[cmd_buf_index]= '\0';

            }

        }

        else 

        {

            /*如果接收到打印字符且当前接收缓冲区满则认为接收完一帧"*/

            putchar(ch);

            cmd_buf[cmd_buf_index++] = ch;

            if(cmd_buf_index>=(sizeof(cmd_buf)-1))

            {

                count = cmd_buf_index;

                cmd_buf[cmd_buf_index]=0;

                cmd_buf_index =0;

                printf("\r\n");

                return count;

            }

        }

    }

    return 0;

}

 

测试

编译运行,可以输入help查看命令列表

 

代码

shell.c

/**
 *****************************************************************************        
 * \brief       平台相关(PLATFORM)SHELL模块(SHELL)相关接口实现.
 * \details     
 *              All rights reserved.    
 * \file        shell.c  
 * \author      
 * \version     1.0 
 * \date       
 * \note        使用前请参考注释.\n
 * \since       新建 
 * \par 修订记录
 * - 初始版本
 * \par 资源说明
 * - RAM:              
 * - ROM:
 *****************************************************************************
 */

#include <stdio.h>
#include <string.h>
#include "shell.h"
#include "cy_retarget_io.h"

extern int uart_read(uint8_t* buffer, uint32_t len);
extern int uart_write(uint8_t* buffer, uint32_t len);
/*****************************************************************************    
 *                                                                           
 *                             内部数据                                   
 *                                                                            
 ****************************************************************************/
#define SHELL_CMD_LEN 64                          /**< shell命令缓冲区长度  */
extern const shell_cmd_cfg shell_cmd_list[ ];     /**< shell_fun中定义  */
extern const shell_cmd_cfg shell_cmd_list_app[ ]; /**< app_shellfun中定义  */
static int shellpassed = 1;  /**< shell密码是否校验 0已经校验 1未校验  */
static unsigned char cmd_buf[SHELL_CMD_LEN]="\r";
static int cmd_buf_index=0;  /**< 当前接收到的命令字符数  */

/*****************************************************************************    
 *                                                                           
 *                             内部接口函数实现                                   
 *                                                                            
 ****************************************************************************/

/**
 *****************************************************************************
 * \fn          static int shell_getchar(unsigned char *data)
 * \brief       读取一个字符.
 * \note        . 
 * \param[out]  data 存储读到的数据.
 * retval       0  成功.
 * retval       -1 失败.
 *****************************************************************************
 */
static int shell_getchar(unsigned char *data)
{
    int erro=0;
    //driver_uart_recv(getstdiouart(), data, 1,10,&erro);
      if(0 == uart_read(data, 1))
        {
            erro = 1;
        }
      else
      {
          uart_write(data,1);
      }
    if(erro!=0)
    {
        return -1;
    }
    return 0;
}


/**
 *****************************************************************************
 * \fn          static unsigned int shell_cmd_len(char const *cmd)
 * \brief       获取命令字符长度.
 * \note        空格或者\0结束. 
 * \param[in]   cmd 字符串
 * return       unsigned int 命令字符的长度
 *****************************************************************************
 */
static unsigned int shell_cmd_len(unsigned char const *cmd)
{
    unsigned char const *p = cmd;
    unsigned int len = 0;
    while((*p != ' ') && (*p != 0)) 
    {
        p++;
        len++;
    }
    return len;
}

/**
 *****************************************************************************
 * \fn          static void shell_check_passwd(void)
 * \brief       shell密码确认.
 * \note        空格或者\0结束. 
 *****************************************************************************
 */
static void shell_check_passwd(void)
{
    unsigned int i;
    unsigned char ch[6] = {0};
    unsigned char pw[7] = SHELL_PASSWORD_STR;

    while(1)
    {
        printf("\r\nPassword:");
        memset(ch, 0, sizeof(ch));
        for (i = 0; i < sizeof(ch); i++)
        {
            ch = getchar();
            putchar('\b');
            putchar('*');
        }
        if (memcmp(pw, ch, sizeof(ch)) == 0)
        {
            printf("\r\n");
            break;
        }
        printf("\r\nAccess denied\r\n");
    }
}

/**
 *****************************************************************************
 * \fn          static int shell_cmd_check(unsigned char *cmd, char const *str)
 * \brief       匹配命令字符.
 * \note        . 
 * \param[in]   cmd 字符串
 * \param[in]   str 匹配字符
 * retval       0 匹配成功
 * retval       1 匹配失败
 *****************************************************************************
 */
static int shell_cmd_check(unsigned char *cmd, unsigned char const *str)
{
    unsigned int len1 = shell_cmd_len((unsigned char const *)cmd);
    unsigned int len2 = shell_cmd_len(str);
    if(len1 != len2)
    {
        return 1;
    }
    return memcmp(cmd, str, len1);
}

/**
 *****************************************************************************
 * \fn          static unsigned int shell_read_line(int get(void), unsigned int len)
 * \brief       shell读命令行.
 * \note        回车结束,可以使用Backspace键清除输入. 
 * \param[in]   get 输入接口函数
 * \param[in]   p   接收缓冲区
 * \param[in]   len 需要接收的长度
 * return       unsigned int 实际接收的长度
 *****************************************************************************
 */
static unsigned int shell_read_line(int get(unsigned char* tmp))
{
    unsigned char ch = '\r';
    unsigned int count;
    unsigned char tmp;
    /*开始打印一次"sh>"*/
    if(cmd_buf[0]=='\r')
    {
        printf("sh>\r\n");
        memset(cmd_buf,0x00,sizeof(cmd_buf));
    }
    /*如果接收到字符往下走,否则返回*/
    if(get(&tmp)==0)
    {
        ch = tmp; 
    }
    else
    {
        return 0;
    }
    /*如果接收到非打印字符且当前接收缓冲区不为0则认为接收到一帧否则打印"SH>"*/
    if((ch == '\r' || ch == '\n' || ch < ' ' || ch > '~') && (ch != '\b'))
    {
        if(cmd_buf_index==0)
        {
            printf("sh>\r\n");
        }
        else
        {
            count = cmd_buf_index;
            cmd_buf[cmd_buf_index]=0;
            cmd_buf_index =0;
            printf("\r\n");
            return count;
        }
    }
    else 
    {
        if(ch == '\b') 
        {
            if(cmd_buf_index != 0) 
            {
                cmd_buf_index--;
                putchar('\b');
                putchar(' ');
                putchar('\b');
                cmd_buf[cmd_buf_index]= '\0';
            }
        } 
        else 
        {
            /*如果接收到打印字符且当前接收缓冲区满则认为接收完一帧"*/
            putchar(ch);
            cmd_buf[cmd_buf_index++] = ch;
            if(cmd_buf_index>=(sizeof(cmd_buf)-1))
            {
                count = cmd_buf_index;
                cmd_buf[cmd_buf_index]=0;
                cmd_buf_index =0;
                printf("\r\n");
                return count;
            }
        } 
    } 
    return 0;
}

/**
 *****************************************************************************
 * \fn          int shell_exec_cmdlist(unsigned char* cmd)
 * \brief       搜索命令列表并执行.
 * retval       0 成功
 * retval       -1 失败
 * \note        . 
 *****************************************************************************
 */
int shell_exec_cmdlist(unsigned char* cmd)
{
    int i;
    /*平台相关命令*/
    for (i=0; shell_cmd_list.name != 0; i++)
    {
        if (shell_cmd_check(cmd, shell_cmd_list.name) == 0) 
        {
            shell_cmd_list.func(cmd);
            return 0;
        }            
    } 
//    /*应用相关命令*/
//    for (i=0; shell_cmd_list_app.name != 0; i++)
//    {
//        if (shell_cmd_check(cmd, shell_cmd_list_app.name) == 0) 
//        {
//            shell_cmd_list_app.func(cmd);
//            return 0;
//        }            
//    }  
    if(shell_cmd_list.name == NULL)
    {
        printf("unkown command\r\n");
        return -1;
    }
    return 0;
}

/*****************************************************************************    
 *                                                                           
 *                             对外接口函数实现                                   
 *                                                                            
 ****************************************************************************/
/**
 *****************************************************************************
 * \fn          void shell_exec_shellcmd(void)
 * \brief       执行shell命令.
 * \note        任务周期调用该函数. 
 *****************************************************************************
 */
void shell_exec_shellcmd(void)
{
    if (!shellpassed)
    {
        shell_check_passwd();
        shellpassed = 1;
    } 
    if(shell_read_line(shell_getchar))
    {
        shell_exec_cmdlist(cmd_buf);
    }
}
 

 

shell.h

/**
 *****************************************************************************        
 * \brief       平台相关(PLATFORM)SHELL模块(SHELL)相关数据结构和接口描述.
 * \details     
 *              All rights reserved.    
 * \file        shell.h  
 * \author      
 * \version     1.0 
 * \date       
 * \note        使用前请参考注释.\n
 * \since       新建 
 * \par 修订记录
 * - 初始版本
 * \par 资源说明
 * - RAM:              
 * - ROM:
 *****************************************************************************
 */

#ifndef _SHELL_H_
#define _SHELL_H_

#ifdef __cplusplus
extern "C" {
#endif
     
/** \addtogroup PLATFORM PLATFORM
 *  \{
 */
         
/** \addtogroup PLATFORM_SHELL PLATFORM_SHELL
 *  \{
 */
/*****************************************************************************    
 *                                                                           *
 *                             数据结构描述                                  *
 *                                                                          *
 ****************************************************************************/
     
/** \defgroup PLATFORM_SHELL_data PLATFORM_SHELL_data
  * \{
  */

typedef void ( * CommandFunc )( void *);   /**< shell命令回调函数 */

/**
 * \struct shell_cmd_cfg
 * SHELL命令结构体.
 */
typedef struct
{
    unsigned char const* name;           /**< shell命令名 */
    CommandFunc func;           /**< shell命令回调函数 */
    char const* helpstr;       /**< 帮助字符串 */
}shell_cmd_cfg;

#define SHELL_PASSWORD_STR "DSWYBS"  /**< shell密码固定6个字符  */
#define SHELL_CMDBUF_SIZE  64         /**< shell命令缓冲区大小  */


/**
  * \}
  */
     
/*****************************************************************************    
 *                                                                           
 *                             接口函数描述                                   
 *                                                                            
 ****************************************************************************/

/** \defgroup PLATFORM_SHELL_if PLATFORM_SHELL_if
  * \{
  */
    
/**
 *****************************************************************************
 * \fn          void shell_exec_shellcmd(void)
 * \brief       执行shell命令.
 * \note        任务周期调用该函数. 
 *****************************************************************************
 */
void shell_exec_shellcmd(void);
/**
 *****************************************************************************
 * \fn          int shell_exec_cmdlist(unsigned char* cmd)
 * \brief       搜索命令列表并执行.
 * retval       0 成功
 * retval       -11 失败
 * \note        . 
 *****************************************************************************
 */
int shell_exec_cmdlist(unsigned char* cmd);
/**
  * \}
  */

/**
  * \}
  */

/**
  * \}
  */

#ifdef __cplusplus
}
#endif

#endif
 

 

shell_func.c

  /**
 *****************************************************************************        
 * \brief       平台层(PLATFORM)SHELL命令模块(SHELL_FUN)相关接口实现.
 * \details     
 *              All rights reserved.    
 * \file        shell_fun.c 
 * \author     
 * \version     1.0 
 * \date       
 * \note        平台相关命令.\n
 * \since       新建 
 * \par 修订记录
 * - 初始版本
 * \par 资源说明
 * - RAM:              
 * - ROM:
 *****************************************************************************
 */

#include <stdio.h>
#include <time.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include "shell_fun.h"
#include "shell.h"


/*****************************************************************************    
 *                                                                           
 *                             内部数据                                   
 *                                                                            
 ****************************************************************************/

const shell_cmd_cfg shell_cmd_list[ ] = 
{
  /*1.帮助相关*/
  { (const uint8_t*)"help",         HelpFun,         "help"},                 /*打印帮助信息*/
  { 0,        0 },
};

/*****************************************************************************    
 *                                                                           
 *                             内部接口函数实现                                   
 *                                                                            
 ****************************************************************************/

/*****************************************************************************    
 *                                                                           
 *                             对外接口函数实现                                   
 *                                                                            
 ****************************************************************************/

/*****************************************************************************    
 *                                                                           
 *                             帮助相关                                  
 *                                                                            
 ****************************************************************************/

void HelpFun(void* param)
{
    unsigned int i;
    printf("\r\n");
    printf("**************\r\n");
    printf("*   SHELL    *\r\n");
    printf("*   V1.0     *\r\n");
    printf("**************\r\n");
    printf("\r\n");
    for (i=0; shell_cmd_list.name != 0; i++)
    {
        printf("%02d.",i);
        printf("%-16s",shell_cmd_list.name);
        printf("%s\r\n",shell_cmd_list.helpstr);
    }
}
 

 

shell_func.h

/**
 *****************************************************************************        
 * \brief       平台层(PLATFORM)SHELL命令模块(SHELL_FUN)相关数据结构和接口描述.
 * \details     
 *              All rights reserved.    
 * \file        shell_fun.h 
 * \author      
 * \version     1.0 
 * \date        
 * \note        平台相关命令.\n
 * \since        新建 
 * \par 修订记录
 * -
 * \par 资源说明
 * - RAM:              
 * - ROM:
 *****************************************************************************
 */

#ifndef __SHELL_FUN_H
#define __SHELL_FUN_H

#ifdef __cplusplus
 extern "C" {
#endif

/*****************************************************************************    
 *                                                                           
 *                             帮助相关                                  
 *                                                                            
 ****************************************************************************/   
void HelpFun(void* param);
void DeadTimeFun(void* param);
void DirFun(void* param);
void SpeedFun(void* param);

#ifdef __cplusplus
}
#endif

#endif

 

总结

以上实现了简单的eSHELL命令行,后面就可以基于此进行交互了。

此帖出自ARM技术论坛

最新回复

这个CLI命令行实现,代码可够长了   详情 回复 发表于 2023-6-24 21:25
点赞 关注
 

回复
举报

1705

帖子

0

TA的资源

五彩晶圆(初级)

沙发
 

这个CLI命令行实现,代码可够长了

此帖出自ARM技术论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表