栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

嵌入式–实现最简单shell

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

嵌入式–实现最简单shell

嵌入式–实现最简单Shell

​ 实现一个shell难不难,本人曾经参考过很多开源的,都觉得他们的代码量比较多。下面我们将实现一个史上最简单的shell。最有两个源文件,代码量也非常少,同时也是拿来就可以用 ,shell.c 中删减了部分内容,移植好就可以用。

​ 开发环境:keil、armcc

​ 硬件平台:ARM

头文件 通用头文件 typedef.h
#ifndef __TYPEDEF_H__
#define __TYPEDEF_H__

#include          // 类型定义
#include         // bool

#include          // offsetof 、typeof


#define container_of(ptr, type, member) ( (type *)( (char *)(ptr) - offsetof(type,member) ) )


#define  __DEF_VAR(type, var, line)  type  var##line
#define  _DEF_VAR(type,prefix,line)  __DEF_VAR(type, prefix, line)
#define  DEFINE_TYPE(type,prefix)      _DEF_VAR(type, prefix, __LINE__)


#if defined(__CC_ARM) || defined(__GNUC__) 
    #define CC_SECTION(x)                  __attribute__((section(x)))
    #define CC_UNUSED                      __attribute__((unused))
    #define CC_USED                        __attribute__((used))
    #define CC_ALIGN(n)                    __attribute__((aligned(n)))
    #define CC_WEAK                        __attribute__((weak))
#elif defined (__ICCARM__)              
    #define CC_SECTION(x)                  @ x
    #define CC_UNUSED                      
    #define CC_USED                        __root
    #define CC_WEAK                        __weak
#else
    #error "Current tool chain haven't supported yet!"
#endif


//check whether a number is in the range[low, high] 
#define IN_RANGE(x, low, high)		((low) <= (x) && (x) <= (high))

// min
#define MIN(x, y)                   ((x) > (y) ? (y) : (x))
// max
#define MAX(x, y)                   ((x) > (y) ? (x) : (y))

// 得到一个field在结构体(struct)中的偏移量
#define FPOS( type, field ) ( (unsigned long) &(( type *) 0)-> field )

// 得到一个结构体中field所占用的字节数
#define FSIZ( type, field ) sizeof( ((type *) 0)->field )

// 返回数组元素的个数
#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )

#endif
头文件 command.h
#ifndef __COMMAND_H__
#define __COMMAND_H__

#include "typedef.h"

#ifdef __cplusplus
extern "C" {
#endif

#define CMD_MAX_LEN                 64                                 
#define CMD_MAX_ARG                 16                
#define CMD_MAX_NUM                 32                

#define SHELL_PROMPT        "root #"

struct cmdobj;

typedef struct cmdops{
    uint8_t (*write)(const uint8_t *buf, uint8_t len);
    int (*read) (uint8_t *buf, const int len);
}CmdOps_t;

typedef struct cmdobj {
    uint8_t (*write)(const uint8_t *buf, uint8_t len);
    int (*read) (uint8_t *buf, const int len);
    void (*print)(struct cmdobj *this, const char *fmt, ...);    
    char  recvbuf[CMD_MAX_LEN + 1];                             
    uint16_t recvcnt;                                               
    uint32_t enable : 1;
}CmdObj_t;


typedef struct {
	char *name;		                                            
	int (*handler)(CmdObj_t *o, int argc, char *argv[]);           
    const char *brief;                                          
}CmdItem_t;

#define Cmd_Register(name, handler, brief)
    CC_USED DEFINE_TYPE(const CmdItem_t, cmd_item_##handler)
    CC_SECTION("cmd.item.1") = {name, handler, brief}

void Cmd_Init(CmdObj_t *obj, const CmdOps_t *p);

void Cmd_Enable(CmdObj_t *obj);

void Cmd_Disable(CmdObj_t *obj);

void Cmd_Exec(CmdObj_t *obj, const char *cmd);

void Cmd_Process(CmdObj_t *obj);


#ifdef __cplusplus
}
#endif  

#endif
头文件 shell.h
#ifndef __SHELL_H__
#define __SHELL_H__



void Shell_Init(void);

void Shell_Run(const char *cmd);

void Shell_Process(void);



#endif
源文件 源文件 command.c
#include 
#include 
#include 
#include 
#include 

#include "command.h"

const CC_USED CmdItem_t cmd_tbl_start CC_SECTION("cmd.item.0") = {NULL, NULL, NULL};
const CC_USED CmdItem_t cmd_tbl_end CC_SECTION("cmd.item.2") = {NULL, NULL, NULL};

static const CmdItem_t* Cmd_Find(const char *keyword)
{                   
	const CmdItem_t *it;
    for (it = &cmd_tbl_start + 1; it < &cmd_tbl_end; it++) 
    {
		if (!strcasecmp(keyword, it->name))
		    return it;
    }
	return NULL;
}

  
 static size_t strsplit(char *s, const char *separator, char *list[],  size_t len)
 {
    size_t count = 0;      
    if (s == NULL || list == NULL || len == 0) 
        return 0;     
        
    list[count++] = s;    
    while(*s && count < len) 
    {       
        if (strchr(separator, *s) != NULL) 
        {
            *s = '';                                       
            list[count++] = s + 1;                          
        }
        s++;        
    }    
    return count;
 }

static void Cmd_Print(CmdObj_t *obj, const char *format, ...)
{
	va_list args;
    int len;
	char buf[CMD_MAX_LEN + CMD_MAX_LEN / 2];
	va_start (args, format);
	len = vsnprintf (buf, sizeof(buf), format, args);
	va_end (args);
    obj->write((uint8_t*)buf, len);
}

static void Cmd_ProcessLine(CmdObj_t *obj)
{
    char *argv[CMD_MAX_ARG];
    int   argc;
    
    const CmdItem_t *it;
    argc = strsplit(obj->recvbuf, " ,", argv, CMD_MAX_ARG);
    if ((it = Cmd_Find(argv[0])) == NULL) 
    {
        obj->print(obj, "Unknown command '%s' - try 'help'rn", argv[0]);
        return;
    }
    it->handler(obj, argc, argv);
}

void Cmd_Init(CmdObj_t *obj, const CmdOps_t *p)
{
    obj->read = p->read;
    obj->write = p->write;
    obj->print = Cmd_Print;
    obj->enable = true;
}

void Cmd_Enable(CmdObj_t *obj)
{
    obj->enable = true;
}

void Cmd_Disable(CmdObj_t *obj)
{
    obj->enable = false;
}

void Cmd_Exec(CmdObj_t *obj, const char *cmd)
{
    snprintf(obj->recvbuf, CMD_MAX_LEN, "%s", cmd);
    Cmd_ProcessLine(obj);
    obj->print(obj, "%s ", SHELL_PROMPT);
}

void Cmd_Process(CmdObj_t *obj)
{
    int i = 0;
    if (!obj->read || !obj->enable)
    {
        return;
    }
    
    i = obj->recvcnt;
    obj->recvcnt += obj->read((uint8_t*)&obj->recvbuf[i], CMD_MAX_LEN - i);
    while (i < obj->recvcnt) 
    {
        if (obj->recvbuf[i] == 'r' || obj->recvbuf[i] == 'n') 
        {
            obj->recvbuf[i] = '';
            
            obj->print(obj, "rn");
            
            if(obj->recvbuf[0] != '')
            {
                Cmd_ProcessLine(obj);
            }
            
            obj->print(obj, "%s ", SHELL_PROMPT);
            
            memset(&obj->recvbuf[0], 0x0, sizeof(obj->recvbuf));
            obj->recvcnt = 0;
        }
        else
        {
            obj->print(obj, "%c", obj->recvbuf[i]);
        }
        i++;
    }
    
    
    if (obj->recvcnt >= CMD_MAX_LEN)
    {
        obj->recvcnt = 0;
    }
}

static int Cmd_Compare(const void *item1,const void *item2)
{
    CmdItem_t *it1 = *((CmdItem_t **)item1); 
    CmdItem_t *it2 = *((CmdItem_t **)item2);    
    return strcmp(it1->name, it2->name);
}


 static int do_help(CmdObj_t *s, int argc, char *argv[])
 {
	int i,j, count;
    const CmdItem_t *item_start = &cmd_tbl_start + 1; 
    const CmdItem_t *item_end   = &cmd_tbl_end;	
	const CmdItem_t *cmdtbl[CMD_MAX_NUM];
    
    if (argc == 2) 
    {
        if ((item_start = Cmd_Find(argv[1])) != NULL) 
        {
            s->print(s, item_start->brief); 
            s->print(s, "rn");   
        }
        return 0;
    }
    
    for (i = 0; i < item_end - item_start && i < CMD_MAX_NUM; i++)
    {
        cmdtbl[i] = &item_start[i];
	}
    count = i;
    
    qsort(cmdtbl, i, sizeof(CmdItem_t*), Cmd_Compare);    		        
    s->print(s, "rn");
    for (i = 0; i < count; i++) 
    {
        
        s->print(s, cmdtbl[i]->name);                        
        
        j = strlen(cmdtbl[i]->name);
        if (j < 10)
        {
            j = 10 - j;
        }
            
        while (j--)
        {
            s->print(s, " ");
        }
            
        s->print(s, "- "); 
        
	    s->print(s, cmdtbl[i]->brief);                       
        s->print(s, "rn");        
    }
	return 1;
 }
 Cmd_Register("help", do_help, "list all command.");   
 Cmd_Register("?",    do_help, "alias for 'help'");
源文件 shell.c
#include 
 #include 
 
 
 
 #include "bsp_uart.h"
 
 #include "command.h"
 
 #include "shell.h"
 
 
 
 static CmdObj_t g_Shell_Obj;
 
 const static CmdOps_t g_cmd_ops = { USART1_Send, USART1_Recv};
 
 
 
 int fputc(int ch, FILE *f)
 {
     if(g_Shell_Obj.write)
     {
         g_Shell_Obj.write((uint8_t *)&ch, 1);
     }
     else
     {
         USART1_Send((uint8_t *)&ch, 1);
     }
 	return ch;
 }
 
 void Shell_Init(void)
 {
     Cmd_Init(&g_Shell_Obj, &g_cmd_ops);
     
     g_Shell_Obj.print(&g_Shell_Obj, "rn");
     g_Shell_Obj.print(&g_Shell_Obj, "******************************rn");
     g_Shell_Obj.print(&g_Shell_Obj, " kiwi shell. QQ: 995868145 rn");
 #if (FW_TYPE_CURR == FW_TYPE_BOOT)
     g_Shell_Obj.print(&g_Shell_Obj, " Bootloader rn");
 #else
     g_Shell_Obj.print(&g_Shell_Obj, " Application rn");
 #endif    
     g_Shell_Obj.print(&g_Shell_Obj, "******************************rn");
     g_Shell_Obj.print(&g_Shell_Obj, "%s ", SHELL_PROMPT);
 }
 
 void Shell_Run(const char *cmd)
 {
     if(!cmd)return;
     
     Cmd_Exec(&g_Shell_Obj, cmd);
 }
 
 void Shell_Process(void)
 {
    Cmd_Process(&g_Shell_Obj); 
 }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/998563.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号