480|2

504

帖子

4

TA的资源

纯净的硅(高级)

楼主
 

【NUCLEO H533RE】实现shell命令行交互 [复制链接]

完整的工程间附件,替换\STM32Cube_FW_H5_V1.2.0\Projects\NUCLEO-H533RE\Applications\ThreadX\Tx_Thread_Creation

Tx_Thread_Creation.zip (168.58 KB, 下载次数: 2)

 

一.前言

前面我们实现了标准输入输出的交互,为了进一步方面人机交互,我们在此基础上继续实现简单的shell。

参考微信公众号”嵌入式Lee”的文章:https://mp.weixin.qq.com/s/XLmbJn0SKoDT1aLdxHDrbg

一个超级精简高可移植的shell命令行C实现

 

 

二.准备

添加shell.c/h 和shell_func.c/h到工程中

 

代码分别如下

shell.c


#include <stdint.h>
#include "shell.h"

shell_read_pf s_input_pf = 0;      /* ??????     */
shell_write_pf s_output_pf = 0;    /* ??????     */
shell_cmd_cfg* s_cmd_cfg_pst = 0;  /* ??????     */
uint8_t s_enableecho_u8 = 0;       /* ????echo?? */
static uint8_t  s_cmd_buf_au8[SHELL_CMD_LEN]="\r"; /* ????? */
static uint32_t s_cmd_buf_index_u32 = 0;               /* ??????????? */

/**
 * ??????
*/
static void shell_putchar(uint8_t val)
{
    uint8_t tmp;
    if(s_output_pf != 0)
    {
        tmp = val;
        s_output_pf(&tmp, 1);
    }
}

/**
 * ???????
*/
static void shell_putstring(char* str)
{
    uint32_t len = 0;
    uint8_t*p = (uint8_t*)str;
    while(*str++)
    {
        len++;
    }
    s_output_pf(p, len);
}

/**
 * ?????
*/
static int shell_getchar(uint8_t *data)
{
    if(s_input_pf == 0)
    {
        return -1;
    }
  if(0 == s_input_pf(data, 1))
    {
    return -1;
  }
  else
  {
        return 0;
  }
}

/**
 * ??????????
 * ??????????
*/
static uint32_t shell_cmd_len(uint8_t *cmd)
{
    uint8_t *p = cmd;
    uint32_t len = 0;
    while((*p != ' ') && (*p != 0)) 
    {
        p++;
        len++;
    }
    return len;
}

/**
 * ???????????,????0
*/
static int shell_cmd_check(uint8_t *cmd, uint8_t *str)
{
    uint32_t len1 = shell_cmd_len(cmd);
    uint32_t len2 = shell_cmd_len(str);
    if(len1 != len2)
    {
        return -1;
    }
    for(uint32_t i=0; i<len1; i++)
    {
        if(*cmd++ != *str++)
        {
            return -1;
        }
    }
    return 0;
}

/**
 * ??????
*/
static uint32_t shell_read_line(void)
{
    uint8_t ch;
    uint32_t count;
    /* ????sh> */
    if(s_cmd_buf_au8[0]=='\r')
    {
        shell_putstring("sh>\r\n");
        s_cmd_buf_au8[0] = 0;
    }

    /* ????????? */
    if(shell_getchar(&ch) !=0 )
    {
        return 0;
    }

    /* ???????????????,????????? 
     * ????????,????????
    */
    if((ch == '\r' || ch == '\n' || ch < ' ' || ch > '~') && (ch != '\b'))
    {
        if(s_cmd_buf_index_u32==0)
        {
            /* ?????????????????,?????sh> */
            shell_putstring("sh>\r\n");
        }
        else
        {
            /* ????????,???????????????
             * ?????????,?????,??????
             * ???????0
            */
            count = s_cmd_buf_index_u32;
            s_cmd_buf_au8[s_cmd_buf_index_u32]=0;
            s_cmd_buf_index_u32 =0;
            shell_putstring("\r\n");
            return count;
        }
    }
    else 
    {
        if(ch == '\b') 
        {
            /* ????,???????????????,????? */
            if(s_cmd_buf_index_u32 != 0) 
            {
                s_cmd_buf_index_u32--;
                shell_putchar('\b');
                shell_putchar(' ');
                shell_putchar('\b');
                s_cmd_buf_au8[s_cmd_buf_index_u32]= '\0';
            }
        } 
        else 
        {
            /* ?????,??????
             * ??????????????-1,?????????
             * -1?????????0??
            */
            if(s_enableecho_u8 != 0)
            {
                shell_putchar(ch);
            }
            s_cmd_buf_au8[s_cmd_buf_index_u32++] = ch;
            if(s_cmd_buf_index_u32>=(sizeof(s_cmd_buf_au8)-1))
            {
                count = s_cmd_buf_index_u32;
                s_cmd_buf_au8[s_cmd_buf_index_u32]=0;
                s_cmd_buf_index_u32 =0;
                shell_putstring("\r\n");
                return count;
            }
        } 
    } 
    return 0;
}

/**
 * ??????????
*/
static int shell_exec_cmdlist(uint8_t* cmd)
{
    int i;
    if(s_cmd_cfg_pst == 0)
    {
        return -1;
    }
    for (i=0; s_cmd_cfg_pst[i].name != 0; i++)
    {
        if (shell_cmd_check(cmd, s_cmd_cfg_pst[i].name) == 0) 
        {
            s_cmd_cfg_pst[i].func(cmd);
            return 0;
        }            
    } 
    if(s_cmd_cfg_pst[i].name == 0)
    {
        shell_putstring("unkown command\r\n");
        return -1;
    }
    return 0;
}

/**
 * ????,????
*/
void shell_exec(void)
{
    if(shell_read_line() > 0)
    {
        shell_exec_cmdlist(s_cmd_buf_au8);
    }
}

/**
 * ????,???????
*/
void shell_set_itf(shell_read_pf input, shell_write_pf output, shell_cmd_cfg* cmd_list, uint8_t enableecho)
{
    s_input_pf = input;
    s_output_pf = output;
    s_cmd_cfg_pst = cmd_list;
    s_enableecho_u8 = enableecho;
}

shell.h

#ifndef SHELL_H
#define SHELL_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

#define SHELL_CMD_LEN 64                                          /**< ??????? */

typedef void (*shell_command_pf)(uint8_t *);                      /**< ??????   */
typedef uint32_t (*shell_read_pf)(uint8_t *buff, uint32_t len);   /**< ?????     */
typedef void (*shell_write_pf)(uint8_t *buff, uint32_t len);      /**< ?????     */

/**
 * \struct shell_cmd_cfg
 * ????
*/
typedef struct
{
    uint8_t * name;          /**< ?????   */
    shell_command_pf func;   /**< ?????? */ 
    uint8_t * helpstr;       /**< ?????? */   
}shell_cmd_cfg;

/**
 * \fn shell_exec
 * ???????,??????,????????????
 * ???
*/
void shell_exec(void);

/**
 * \fn shell_set_itf
 * ??????????,??????
 * ??shell_exec_shellcmd??,???????????
 * \param[in] input \ref shell_read_pf ????
 * \param[in] output \ref shell_write_pf ????
 * \param[in] cmd_list \ref shell_cmd_cfg ????
 * \param[in] enableecho 0:?????, ???:????
*/
void shell_set_itf(shell_read_pf input, shell_write_pf output, shell_cmd_cfg* cmd_list, uint8_t enableecho);

#ifdef __cplusplus
}
#endif

#endif

shell_func.c


#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

#include "shell.h"
#include "shell_func.h"
#include "xprintf.h"

static void helpfunc(uint8_t* param);

/**
 * ???????0,??????
*/
const shell_cmd_cfg g_shell_cmd_list_ast[ ] = 
{
  { (uint8_t*)"help",         helpfunc,         (uint8_t*)"help"}, 
  { (uint8_t*)0,              0 ,               0},
};

void helpfunc(uint8_t* param)
{
    (void)param;
    unsigned int i;
    xprintf("\r\n");
    xprintf("**************\r\n");
    xprintf("*   SHELL    *\r\n");
    xprintf("*   V1.0     *\r\n");
    xprintf("**************\r\n");
    xprintf("\r\n");
    for (i=0; g_shell_cmd_list_ast[i].name != 0; i++)
    {
        xprintf("%02d.",i);
        xprintf("%-16s",g_shell_cmd_list_ast[i].name);
        xprintf("%s\r\n",g_shell_cmd_list_ast[i].helpstr);
    }
}

shell_func.h


#ifndef SHELL_FUNC_H
#define SHELL_FUNC_H

#include <stdint.h>

#ifdef __cplusplus
 extern "C" {
#endif
 
extern const shell_cmd_cfg g_shell_cmd_list_ast[ ];
   
#ifdef __cplusplus
}
#endif

#endif

 

三.初始化接口

Main_task.c中

#include “shell.h”
#include "shell_func.h"

uint32_t uart_api_read(uint8_t *buff, uint32_t len)
{
	return uart_read(buff,len);
}

void uart_api_write(uint8_t *buff, uint32_t len)
{
	uart_write(buff,len);
}

static void main_task_entry(ULONG thread_input)
{
	tx_thread_sleep(100);  /* wait uart and xprintf init done */
	xprintf("start main task\r\n");
	while(1)
	{
		#if 0
			uint32_t len = uart_read(rx_buffer,sizeof(rx_buffer));
		  if(len > 0)
      { 
					uart_write(rx_buffer,len);
			}
			//uart_write(tx_buffer,sizeof(tx_buffer));
			tx_thread_sleep(1);
		#endif
		
		#if 0
    xprintf("%d\n", 1234);             /* "1234" */
    xprintf("%6d,%3d%%\n", -200, 5);   /* "  -200,  5%" */
    xprintf("%-6u\n", 100);            /* "100   " */
    xprintf("%ld\n", 12345678);        /* "12345678" */
    xprintf("%llu\n", 0x100000000);    /* "4294967296"   <XF_USE_LLI> */
    xprintf("%lld\n", -1LL);           /* "-1"           <XF_USE_LLI> */
    xprintf("%04x\n", 0xA3);           /* "00a3" */
    xprintf("%08lX\n", 0x123ABC);      /* "00123ABC" */
    xprintf("%016b\n", 0x550F);        /* "0101010100001111" */
    xprintf("%*d\n", 6, 100);          /* "   100" */
    xprintf("%s\n", "abcdefg");        /* "abcdefg" */
    xprintf("%5s\n", "abc");           /* "  abc" */
    xprintf("%-5s\n", "abc");          /* "abc  " */
    xprintf("%.5s\n", "abcdefg");      /* "abcde" */
    xprintf("%-5.2s\n", "abcdefg");    /* "ab   " */
    xprintf("%c\n", 'a');              /* "a" */
    xprintf("%12f\n", 10.0);           /* "   10.000000" <XF_USE_FP> */
    xprintf("%.4E\n", 123.45678);      /* "1.2346E+02"   <XF_USE_FP> */
		#endif
		
    shell_set_itf(uart_api_read, uart_api_write, (shell_cmd_cfg*)g_shell_cmd_list_ast, 1);

		while(1)
    {
			#if 0
			char input_buffer[32];
			char* str = input_buffer;
			xprintf("please input two int\r\n");
			xgets(input_buffer, sizeof(input_buffer));
			long a;
			xatoi(&str,&a);
			long b;
			xatoi(&str,&b);
			xprintf("%d+%d=%d\r\n",a,b,a+b);
			#endif
			
			shell_exec();
			tx_thread_sleep(1);
		}
	}
}

 

四.测试

输入help回车调用help对应的接口打印如下

 

五.总结

以上实现了shell命令行交互,后面就可以方便的实现自己的命令,方便开发调试了。

此帖出自stm32/stm8论坛

最新回复

可以,找个挺好的!   详情 回复 发表于 2024-7-8 12:31
点赞 关注
 

回复
举报

6960

帖子

11

TA的资源

版主

沙发
 

以上实现了shell命令行交互,后面就可以方便的实现自己的命令,方便开发调试了。

涨知识了。

此帖出自stm32/stm8论坛
 
 

回复

106

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

可以,找个挺好的!

此帖出自stm32/stm8论坛
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
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
快速回复 返回顶部 返回列表