【嵌入式】开源shell命令行的移植和使用(1)——nr_micro_shell

news2024/11/23 21:22:47

目录

一 背景说明

二 移植准备

三 移植过程

四 实际使用


一 背景说明

        在进行调试和维护时,常常需要与单片机进行交互,获取、设置某些参数或执行某些操作,nr_micro_shell正是为满足这一需求,针对资源较少的MCU编写的基本命令行工具。虽然RT_Thread组件中已经提供了强大的finsh命令行交互工具,但对于ROM、RAM资源较少的单片机,finsh还是略显的庞大,在这些平台上,若仍想保留基本的命令行交互功能,nr_micro_shell是一个不错的选择。

        nr_micro_shell具有以下优点:

        1.占用资源少,使用简单,灵活方便。使用过程只涉及两个shell_init()和shell()两个函数,无论是使用RTOS还是裸机都可以方便的应用该工具,不需要额外的编码工作。

        2.交互体验好。完全类似于linux shell命令行,当串口终端支持ANSI(如Hypertrm终端)时,其不仅支持基本的命令行交互,还提供Tab键命令补全,查询历史命令,方向键移动光标修改功能。

        3.扩展性好。nr_micro_shell为用户提供自定义命令的标准函数原型,只需要按照命令编写命令函数,并注册命令函数,即可使用命令。

二 移植准备

【1】nr_micro_shell下载地址:

nr_micro_shell: shell for MCU. 单片机命令行交互。

【2】文件目录结构:

名称说明
docs文档目录,包含演示的GIF图片等
examples例子目录,包括命令函数示例: nr_micro_shell_commands.c 和RT_Thread下使用示例 nr_micro_shell_thread.c
inc头文件目录
src源代码目录

【3】提前准备好芯片UART串口的初始化以及收发接口;

三 移植过程

【1】目录移植:将下载好的nr_micro_shell文件解压到自己的工程目录下,并在IDE中包含所需的src源文件以及inc头文件(其中 nr_micro_shell_commands.c 文件位于examples文件夹中,也一并移过来方便移植)

        此时编译一下,会出现报错,这就需要修改以下配置

【2】修改配置文件 nr_micro_shell_config.h :

        (i)把下面第44、45行包含了 RT-Thread 的头文件给注释掉,或者自己定义 NR_MICRO_SHELL_SIMULATOR 这个宏进行头文件包含屏蔽也可以:

        (ii)根据自己的shell运行终端配置 NR_SHELL_END_OF_LINE 宏,这个宏配置的是指令是以空格结尾还是换行结尾有效。我这边用的SecureCRT,这边改成1:

        (iii)将上面 shell_printf 宏 改成自己的 printf 打印或者重定向fputc使得printf输出用的是串口的输出接口,我这边用的后一种方式:

int32_t fputc(int32_t ch, FILE *f)
{
    (void)f;  /* Prevent unused argument compilation warning */
    return (Ok == Uart_SendDataPollTimeOut(M0P_UART0, (char)ch, SystemCoreClock/DBG_PRINTF_BAUDRATE)) ? ch: -1;
}

        (iv)可以修改 NR_SHELL_USER_NAME 以使用自定义的用户名。

【3】基本配置完成之后,就完成输出了。下面接着实现串口接收的移植:要实现交互,就需要串口接收中断函数调用 shell() 这个宏(根据自己程序,在串口接收中断函数处接收数据,传递给 shell() 这个宏,也可以使用轮询的机制),我这边是在串口中断中调用的

/**************************************************************************
* 函数名称: Uart0_IRQHandler
* 功能描述: 串口接收中断
**************************************************************************/
void Uart0_IRQHandler(void)
{
    uint8_t ch;

    if(Uart_GetStatus(M0P_UART0, UartRC))       //UART0数据接收
    {
        Uart_ClrStatus(M0P_UART0, UartRC);      //清中断状态位
        ch = Uart_ReceiveData(M0P_UART0);       //接收数据字节
        shell(ch);
    }
    
    if(Uart_GetStatus(M0P_UART0, UartTC))         //UART0数据发送
    {
        Uart_ClrStatus(M0P_UART0, UartTC);        //清中断状态位
    }
}

【4】在程序初始化的时候调用串口的初始化以及shell初始化接口(shell_init()),上电之后即可看到shell的logo,按TAB键即可看到注册的几个命令:

#include "nr_micro_shell.h"

int main(void)
{
    //串口初始化
    Dbg_Init();
    Dbg_Cfg();

    //命令行初始化
    shell_init();

    while(1)
    {
        
    }
}

【5】自定义命令的注册:

        参考 nr_micro_shell_commands.c 中的命令模板,实现自定义的命令,并放在 static_cmd 中进行注册(注意:这边的 {"\0", NULL} 不能删除)。

void shell_show_cmd(char argc, char *argv)
{
    shell_printf("show cmd \r\n");
}

void shell_set_cmd(char argc, char *argv)
{
    shell_printf("set cmd \r\n");
}

#ifdef NR_SHELL_USING_EXPORT_CMD
NR_SHELL_CMD_EXPORT(ls, shell_ls_cmd);
NR_SHELL_CMD_EXPORT(test, shell_test_cmd);
#else
const static_cmd_st static_cmd[] =
	{
		{"ls", shell_ls_cmd},
		{"show", shell_show_cmd},
        {"set", shell_set_cmd},
		{"\0", NULL}};
#endif

        至此,移植结束。

四 实际使用

        实际使用的效果如下:

补充几个别人遇到的问题以及自己遇到的问题待查:

(i)nr_micro_shell 还不支持一些特殊的按键,如果按下了这些特殊按键会导致程序崩溃。而且在使用方向键获取历史命令的时候,会把前导符 ”:“ 给覆盖掉,所以还是有些需要完善的地方的;

(ii)在xshell终端输入指令,nr_micro_shell没有反馈回来指令字母,需要完成一条指令按回车才有反馈,输入指令过程中没有反馈,查看了一下源码,需要在此处修改一下代码,将上面NR_MICRO_SHELL_SIMULATOR这个宏判断去掉,如下:

(iii)在使用TAB键补充的时候,会出现程序崩溃,需要在TAB处理函数处加入一下代码:

(iv)自己调试的时候遇到一个问题:实际使用shell的时候,有时候按空格或者退格键会使得程序直接重启,更换了串口波特率9600为115200之后,问题解决。具体原因不明,希望有大神看到能够帮忙解惑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1266117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VT-MRPA1-151-1X/V0/0控制2FRE16模块式模拟放大器

适用于控制带有电气位置反馈的直动式比例减压阀(DBETR- 1X 类型)或带有电气位置反馈的比例流量控制阀(2FRE... 类型);控制值输入 1 0 V(差动输入); 可分别调节“上/下”斜坡时间的斜…

计算机网络:快速了解网络框架

文章目录 前言一、什么是Internet?1.从具体构成角度什么是协议? 2.从服务角度3小结 二、网络边缘1.采用网络设施面向连接服务(TCP)2.采用基础设施的无连接服务(UDP) 三、网络的核心1.电路交换2.分组交换3.分…

vue2 el-table 封装

vue2 el-table 封装 在 custom 文件夹下面创建 tableList.vue直接上代码&#xff08;代码比较多&#xff0c;复制可直接用&#xff09; <template><div class"mp-list"><el-tableref"multipleTable"class"mp-custom-table":dat…

一起学docker系列之十二什么是dockerfile

目录 1 基本概念2 语法规则3 Dockerfile构建步骤4 Dockerfile、Docker镜像和Docker容器的关系5 保留字介绍5.1 FROM5.2 MAINTAINER5.3 RUN5.4 EXPOSE5.5 WORKDIR5.6 USER5.7 ENV5.8 ADD5.9 COPY5.10 VOLUME5.11 CMD5.12 ENTRYPOINT 6 总结7 参考地址 1 基本概念 Dockerfile是一…

cpu飙升问题排查以及解决

1、查看内存占用排行 top -c 2、查看服务器内存使用情况 free -h 3、查看文件夹磁盘空间大小 Linux 查看各文件夹大小命令du -h --max-depth1 (1)查看文件目录一级目录磁盘空间 du -h --max-depth1 (2&#xff09;查看指定文件目录 du sh home --max-depth2 4、Linux下…

Linux系统---环境变量+内核进程调度队列(选学)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、环境变量 1.基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数&#xff0c;如: 我们在编写CI/…

Java-多线程基本知识学习总结

多线程 前言一、线程的创建1、继承Thread类2、实现Runnable接口 二、线程的生命周期三、操作线程的方法1、线程的休眠2、线程的加入3、线程的礼让4、线程的优先级 四、线程同步End 前言 Java是支持多线程的编程语言&#xff0c;所谓多线程就是程序能够同时完成多种操作。 计算…

MSB3541 Files 的值“<<<<<<< HEAD”无效。路径中具有非法字符。

MSB3541 Files 的值“<<<<<<< HEAD”无效。路径中具有非法字符。 一般来说出现这个问题是因为使用git版本控制工具合并代码出现了问题&#xff0c;想要解决也很简单。 如图点击错误后定位到文件&#xff0c;发现也没有什么问题。 根据错误后边的提示&a…

GoWeb学习-第二天

文章目录 从零开始学Go web——第二天一、安装Go语言二、建立web目录2.1 创建GO语言包目录2.2 创建Go web文件 三、编译并运行Go web应用3.1 编译并运行3.2 查看结果 从零开始学Go web——第二天 ​ 第一天我们了解了与web息息相关的HTTP协议&#xff0c;聊了聊Go与web的关系等…

深度解读:为什么要做数据合规?如何做到数据合规?

数据资源“入表”在即&#xff0c;企业更需筑牢数据合规防线。但企业主企业购买数据、获取数据到底是否合法合规&#xff0c;入表如何防范合规风险&#xff1f;上周三&#xff0c;亿信华辰邀请到北京鑫诺律师事务所高级合伙人、管委会副主任武婕将和大家分享《数据入表法律合规…

扩散模型DDPM学习笔记

扩散模型DDPM 文章目录 扩散模型DDPM如何运作基本概念训练过程推理过程&#xff1a; 目标损失函数推导评估标准 论文地址&#xff1a; Denoising Diffusion Probabilistic Models (DDPM) 如何运作 ​ 从guassian distribution进行采样得到一个噪声的图片&#xff0c;图片大小…

使字符串的单词倒序输出表示

题目 任务描述 本关任务&#xff1a;请实现函数 revWordoder&#xff0c;能够将 pa 指向的单词表字符串中的所有单词&#xff0c;按相反顺序放入 pb&#xff0c;同时去除多余的空格&#xff0c;单词之间只留一个空格. 例如 pa 中为 red blue, 则调用函数后&#xff0c;pb 中为b…

如何通过Portal实现消息集成

在数字化时代浪潮下&#xff0c;信息的流通与交互已变得至关重要&#xff0c;不论是在企业内部日常协作&#xff0c;还是与外部客户的紧密沟通&#xff0c;信息的快速、准确、实时传递都成为了确保业务顺畅进行的关键因素、决策精准的核心要素。 为了满足这种日益增长的需求&a…

学生护眼灯怎么选?2023备考护眼台灯推荐

近期&#xff0c;许多“护眼台灯是否是智商税”的帖子频繁出现&#xff0c;引起了许多群众的关注&#xff0c;作为一名护眼台灯资深使用者&#xff0c;在这里声明一下&#xff0c;护眼台灯绝对不是智商税。护眼台灯是通过调节光线亮度和色温&#xff0c;降低蓝光辐射&#xff0…

苹果提醒事项怎么用?几个简单步骤就能学会!

苹果提醒事项可以帮助你轻松管理待办事项&#xff0c;让你更好地安排自己的时间和工作。但是&#xff0c;有些小伙伴可能对如何使用这个功能还有一些疑问。苹果提醒事项怎么用&#xff1f;不要担心&#xff0c;小编将为大家提供使用提醒事项的方法&#xff0c;帮助你学会如何使…

代码随想录算法训练营第四十九天【动态规划part10】 | 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

121. 买卖股票的最佳时机 题目链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 求解思路&#xff1a; 动规五部曲 确定dp数组及其下标含义&#xff1a;使用一个二维数组dp[i][2]&#xff0c;dp[i][0]代表持有股票的最大收益&…

【VRTK】【VR开发】【Unity】9-瞬移

课程配套学习资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【移动的种类】 瞬移只是VR中移动的一种种类,其它还有连续移动,物理移动,摔臂移动等等。 瞬移自身也有多个分类,本篇介绍: 即时瞬移冲刺瞬移定点瞬移【瞬…

一篇教会你java内存图怎么画

首先我们要知道&#xff1a; 线程的本质是栈&#xff1b;程序执行时&#xff0c;在java栈中&#xff0c;成立一个线程栈&#xff0c;调用方法时方法不断压栈出栈&#xff0c;这个压栈出栈的过程就是线程执行的过程。方法执行 拷贝入栈 &#xff0c;执行完成 出栈&#xff0c;从…

leetcode刷题详解十一

⭕️583. 两个字符串的删除操作 思路&#xff1a;核心代码就是最长公共子序列&#xff0c;但是需要注意的是结果 就是如果说公共子序列为0&#xff0c;则需要两个字符串长度的才行 如果有&#xff0c;就是 n m ∗ 2 d p [ n ] [ m ] nm*2dp[n][m] nm∗2dp[n][m] int minDist…

企业人力资源公司抖音直播招聘断播怎么处理?

企业人力资源公司抖音直播招聘断播怎么处理&#xff1f; 最直接的处理方式就是进行抖音直播招聘报白&#xff0c;报白后在直播和视频中发布招聘和企业信息&#xff0c;不用担心被封禁和限制流量。 可以通过抖音直播进行招聘&#xff0c;也可以在视频中添加小程序&#xff0c;…