运行在微控制器上的简单易用的shell

这里给出的shell 代码(或称为lsh、cli)都是在 GitHub上开源项目。

       在大学里写一个Shell代码可能是必需的,它不仅可以提高程序能力,在实际程序应用中也非常方便,同时也可以以此为基础扩展其它功能。

shell 使用步骤

Shell不仅要稳定可靠,还要简单易用,以下三点是必要的。

  • 初始化:在这一步中, shell 将读取并执行其配置文件。这里还注册了shell 的功能函数、初始化输入输出端口等。
  • 运行处理: shell 从标准输入(可以是交互式的或文件)读取命令并执行它们并输出运行结果。
  • 结束退出:在不需要shell后,shell 执行关闭命令,释放内存等。

严格按照这三点实现目的是为了简单而易用。

目标已经明确,那是写一个shell,还是不要重造轮子呢?当然是后者。

下面是几个开源shell:

letter-shell :https://github.com/NevermindZZT/letter-shell

 lwshell : https://github.com/MaJerle/lwshell

Shell : https://github.com/geekfactory/Shell

uC-Shell :https://github.com/weston-embedded/uC-Shell

letter-shell :

       letter-shell其功能强大,并且一直在更新演化,其资料也较多请搜索网络。

lwshell :

       lwshell是MaJerle开源,他不仅开源有lwshell, 还有lwrb,lwprintf等等。其官网还有详细说明资料。其开源项目无其它依懒,直接可移植使用。

Shell

       跟lwshell相差不大,真是简单到漏水,但也满足基本需求。

uC-Shell

       这个就是著名的uc-os的开源附件。其功能强大,设计精巧,其程序说明还和原理方法都有详细指引。经典设计和久经沙场不得不让人佩服。唯一不足是依懒uc库,这些都不是问题,有源码可以随意DIY。

前面讲到基本使用步骤,下面列出shell使用方法

shell循环方式:

  • 在裸机中以while非阻塞式循环。
  • 在裸机中以1mS定时非阻塞式循环。
  • 在OS系统中以1ms间隔周期非阻塞式循环。
  • 在OS系统中以消息、事件、信号等任务同步的方式阻塞式循环。

第一种最为简单,其余依次递增。

对于这四种循环方式,其shell 在运行过程中做了什么,分为以下四个工作内容。

Shell循环工作内容

  • 读取:从标准输入读取命令和数据串。
  • 解析:将命令字符串分成程序和参数。
  • 执行:运行解析的命令。
  • 输出: 输出执行结果

以上为Shell的整体结构,图示如下所示

下面以lwshell和shell的代码为示范:

我们以shell基本循环中的第一个为例.

我们以STM32cubeMx生成的任意一个工程的Main函数并在while循环中加入shell函数,注意在这我项目中我们将lwshell和shell同时进行运行。

为了调试方便我们用SEGGER_RTT作为输出。

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    rtt_init();
    
    shell_shell_init();
    shell_shell_register();

    lwshell_shell_init(); 
    lwshell_register();

    while (1) {
        read_port();
        shell_task();
        lwshell_task();
    }
}

在最后没有作退出处理,而是让shell一直工作。

下面我们来看项目工程:

下面为函数代码:

void shell_shell_init(void)
{
    // 初始化注册读写功能函数
    shell_init(shell_read, shell_shell_write, 0);
    xprintf("Shell_shell initialization complete\r\n");
}

// Add commands to the shell
void shell_shell_register(void)
{
    shell_register(command_mycommand, ("shellcmd"));
    shell_register(command_othercommand, ("shell"));
    shell_register(Simultaneous_processing_command, ("cmd"));
}

void lwshell_shell_init(void)
{
    lwshell_init();
    lwshell_set_output_fn(lwshell_out);
    xprintf("lwshell_shell initialization complete\r\n");
}

// Add commands to the shell
void lwshell_register(void)
{
    /* Define shell commands */
    lwshell_register_cmd("lwshell", lwshell_command, "lwshell running command");
    lwshell_register_cmd("lw", lwshell_othercommand, "lwshell other command");   
    lwshell_register_cmd("cmd", lwshell_othercommand, "lwshell other command");
}

void lwshell_task(void)
{
    uint8_t input;
    if(RingBuf_get(&lwshellRB, &input) == true) {
        lwshell_input((const void *)&input, sizeof(input));
    }
}

我们注册了五个命令调用函数,分别为Shell库和lwshell库分别单独操作各两个函数,另一个为两个库同时调用一个函数,共用一个命令“cmd”。如下:

int command_mycommand(int argc, char** argv)

int command_othercommand(int argc, char** argv)

int32_t lwshell_command(int32_t argc, char** argv)

int32_t lwshell_othercommand(int32_t argc, char** argv)

int32_t Simultaneous_processing_command(int32_t argc, char** argv)

{
  xprintf("Shell_shell Running \"mycommand\" now argv: %d\r\n",argc);
    for(int32_t i = 0; i < argc; ++i) {
        xprintf("ARG[%d]: %s\r\n", (int)i, argv[i]);
    }
  xprintf("Exit...");
  return SHELL_RET_SUCCESS;
}

其函数执行的功能都是一样。这里只列出一个。

Shell库的执行命令为:shellcmd; shell; cmd

Lwshell库的执行命令为:lwshell; lw; cmd

Cmd为两个共用命令。

测试效果如下:

 项目中包含一个SEGGER_RTT文件,一个环形队列库,一个xprintf打印库,还有两个shell库和我增加一个测试用例。

下面把项目文件打包,大家可以自行测试。

运行在微控制器上的简单易用的shell源文件-C/C++文档类资源-CSDN下载

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值