小猫爪:动手笔记03-简单Shell在MCU上的实现

小猫爪:动手笔记03-简单Shell在MCU上的实现

1 前言

经常调试MCU的时候都是通过简单的发布命令a,b,c让MCU执行一些特定的功能,但是这样不是特别的方便,后来接触到了Linux的控制台,原来世界上还有这么好的东西,用在MCU上也是非常好的,所以我就在网上找资源,结果大神无处不在啊,很快就找到了一个大神的shell源码,于是我就是对其裁剪了一下,然后就移植了一下,并且稍微的小小的封装了一下,以后移植就省事了。源码地址:https://gitee.com/somebug/atomlib。站在大神的肩膀上真的香。

2 下载

我处理后的代码可以在链接下下载:https://download.csdn.net/download/Oushuwen/14890835,下载后解压,文件如下:
在这里插入图片描述
引用一下原作者的一些介绍:
在这里插入图片描述其中shell_io.c和cmd.c是我添加的文件。
shell_io.c:移植的接口文件
cmd.c:放了一些demo命令

将其中文件全部添加进项目中,如下:
在这里插入图片描述

3 移植

(1)添加shell初始化函数

移植就更加简单了。在main函数中调用ShellInit函数,参数为控制台名称:

/*参数为控制台名称*/
ShellInit("~#:");

(2)添加UART中断回调函数

在UART中断调用回调函数,这里分两种情况:

第一种就是你的UART有类似IDLE中断这样的完整包接收机制,也就确保整包接收完毕。在这种情况下,在UART接收中断调用ShellIdelHandleCallBack(data, RX_BYTE_HANDLE),其中data为UART的数据寄存器的值; 在完整包接收后(或者IDEL中断)调用ShellIdelHandleCallBack(NULL, IDELE_HANDLE)。如下是我的UART中断处理函数:

void DEMO_LPUART_IRQHandler(void)
{
    uint8_t data;
    /* If new data arrived. */
    if ((kLPUART_RxDataRegFullFlag)&LPUART_GetStatusFlags(DEMO_LPUART))
    {
        data = LPUART_ReadByte(DEMO_LPUART);

        ShellIdelHandleCallBack(data, RX_BYTE_HANDLE);   
        
        LPUART_ClearStatusFlags(DEMO_LPUART, kLPUART_RxDataRegFullFlag);
    }
    if ((kLPUART_IdleLineFlag)&LPUART_GetStatusFlags(DEMO_LPUART))
    {
        ShellIdelHandleCallBack(NULL, IDELE_HANDLE);
                
        LPUART_ClearStatusFlags(DEMO_LPUART, kLPUART_IdleLineFlag);
    }
    SDK_ISR_EXIT_BARRIER;
}

第二种情况就是没有完整包处理机制的情况下,则可以直接在UART接收中断中调用ShellNoIdelHandleCallBack(uint8_t data)函数,其中data为UART接收字节数据,如下:

void DEMO_LPUART_IRQHandler(void)
{
    uint8_t data;
    /* If new data arrived. */
    if ((kLPUART_RxDataRegFullFlag)&LPUART_GetStatusFlags(DEMO_LPUART))
    {
        data = LPUART_ReadByte(DEMO_LPUART);

        ShellNoIdelHandleCallBack(data);
        
        LPUART_ClearStatusFlags(DEMO_LPUART, kLPUART_RxDataRegFullFlag);
    }
}

在这种情况下,shell则会丧失插入输入,翻看历史的功能,但是不影响使用。

(3)添加输出UART发送接口

找到shell_io.c文件,修改SerialPuts函数,实现shell输出,示例如下:

void SerialPuts(char * data, unsigned short len)
{
    UARTSendBytes(USART1, (uint8_t*) data, len);
}

这样就移植成功了,效果如下:
在这里插入图片描述

4 添加自己的命令

添加命令也非常简单,在shell_io.c中的ShellCommandInit函数中使用用函数shell_register_command(name,func)注册命令,其中name为命令的名字,func则是注册服务函数,比如我想注册一个LED_Control的命令,示例如下:

void LED_Control(void * arg)
{
  	char * argv[4];
	int argc = cmdline_strtok((char*)arg,argv,4);
        
        if(strcmp(argv[1], "ON") == NULL)
        {
            printk("LED IS ON NOW\r\n", argc);
        }
        else if(strcmp(argv[1], "OFF") == NULL)
        {
           printk("LED IS OFF NOW\r\n", argc);
        }
        else
        {
            printk("Param error, please check it\r\n");
        }
}

void ShellCommandInit(void)
{
    shell_register_command("hello-world",helloworld);
    shell_register_confirm("hello-world2",helloworld,"sure to test this command?");
    shell_register_command("param2int",demo_cmd);
    shell_register_command("param-get",demo2_cmd);
    shell_register_command("getopt-demo",demo3_cmd);
    shell_register_command("LED_Control", LED_Control);
}

这样一个新的命令就注册好了,效果如下:
在这里插入图片描述
另外在cmd.c中有许多命令处理demo,比如处理有参数的命令,处理有限制符的命令,大家自行体会。

END

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猫爪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值