FinSH

article/2025/9/24 19:23:38

finSH介绍

FinSH 是 RT-Thread 的命令行组件,提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口 / 以太网 / USB 等与 PC 机进行通信。

命令执行过程

FinSH 命令执行流程图

功能:

  1. 支持鉴权,可在系统配置中选择打开/关闭。(TODO:具体操作过程)
  2. tap键自动补全命令,如果什么都没有输入会列出所有命令。(TODO:原理)
    按键功能描述
    Tab 键当没有输入任何字符时按下 Tab 键将会打印当前系统支持的所有命令。若已经输入部分字符时按下 Tab 键,将会查找匹配的命令,也会按照文件系统的当前目录下的文件名进行补全,并可以继续输入,多次补全
    ↑↓键上下翻阅最近输入的历史命令
    退格键删除符
    ←→键向左或向右移动标
  3. 历史命令查看。(上下键翻阅)
  4. FinSH 完全采用 ANSI C 编写,具备极好的移植性。(前面章节中介绍的函数方式动态地向 FinSH 添加符号,FinSH 将不会动态申请内存??什么方式?)

传统命令行模式msh VS C-style模式

最初 FinSH 仅支持 C-Style 模式,后来随着 RT-Thread 的不断发展,C-Style 模式在运行脚本或者程序时不太方便,而使用传统的 shell 方式则比较方便。另外,C-Style 模式下,FinSH 占用体积比较大。(TODO:为什么会比较大)出于这些考虑,在 RT-Thread 中增加了 msh 模式,msh 模式体积小,使用方便,推荐使用 msh 模式。

  1. modemshC-style
    examplecommand [arg1] [arg2] […]list_thread()
    switchexit ===>to c-style modemsh() ===> to msh mode
    cmd defineMSH_CMD_EXPORT(name, desc);
    MSH_CMD_EXPORT_ALIAS
    FINSH_FUNCTION_EXPORT(name,desc);
    FINSH_VAR_EXPORT(name, type, desc);
    FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc);(当函数名称超过16个字节的时候,需要导出别名,否则执行会出错,在重命名的命令名字前加 __cmd_ 就可以将命令导出到 msh 模式,否则,命令会被导出到 C-Style 模式)

FinSH功能配置

在rt-thread配置文件rt-config.h 中,在env开发环境下,可以使用menuconfig 命令在图形化界面当中进行配置。

宏定义取值类型描述默认值
#define RT_USING_FINSH使能 FinSH开启
#define FINSH_THREAD_NAME字符串FinSH 线程的名字“tshell”
#define FINSH_USING_HISTORY打开历史回溯功能开启
#define FINSH_HISTORY_LINES整数型能回溯的历史命令行数5
#define FINSH_USING_SYMTAB可以在 FinSH 中使用符号表开启
#define FINSH_USING_DESCRIPTION给每个 FinSH 的符号添加一段描述开启
#define FINSH_USING_MSH使能 msh 模式开启
#define FINSH_USING_MSH_ONLY只使用 msh 模式开启
#define FINSH_ARG_MAX整数型最大输入参数数量10
#define FINSH_USING_AUTH使能权限验证关闭
#define FINSH_DEFAULT_PASSWORD字符串权限验证密码关闭

FiniSH代码阅读提示:

每次的命令执行都是在 FinSH 线程(即 tshell 线程)的上下文中完成。

初始化:finsh_system_init() 函数。

输出:在 RT-Thread 中依赖 rt_kprintf() 输出。在启动函数 rt_hw_board_init() 中,rt_console_set_device(const char* name) 函数设置了 FinSH 的打印输出设备。

输入:获得了信号量后,调用rt_device_read() 函数从设备 (选用串口设备) 中获得一个字符然后处理。而 rx_sem 信号量的释放通过调用 rx_indicate() 函数以完成对 FinSH 线程的输入通知。通常的过程是,当串口接收中断发生时(即串口有输入),接受中断服务例程调用 rx_indicate() 函数通知 FinSH 线程有输入,而后 FinSH 线程获取串口输入最后做相应的命令处理。

TODO:获得一个字符就处理吗?还是整个命令获得了再处理?

FinSH代码阅读

文件结构

route:rt-thread/components/finish
├─ finsh│  ├─ cmd.c                // place rt-thread  cmd│  ├─ finsh.h            // cmd export相关的宏和函数的声明,涉及到的函数的声明(TODO:函数实现在哪?)│  ├─ msh.c                // msh cmd search & excution funcitons│  ├─ msh.h                // msh cmd search & excution funcitons API│  ├─ msh_file.c        // some os cmd define(cd/pwd/mkfs/mount/...)│  ├─ msh_parse.c        // msh cmd parse│  ├─ msh_parse.h        // msh cmd parse API│  ├─ shell.c            // shell context and cmd read│  ├─ shell.h            // struct define and API set│  ├─ Kconfig            // project config file for menuconfig│  └─ SConscript        // scons project file

初始化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1M5zlpzZ-1667636697535)(a1992662197db6b981a36dd150b62ae0.png)]

finSH的初始化放在rt_components_init()的applilication init functions部分。

调用关系:

rtthread_startup() -->

rt_system_scheduler_start() -->

main_thread_entry(void *parameter) -->

rt_components_init(void) -->

finsh_system_init(void) -->

分出另一个线程 -->

finsh_thread_entry(void *parameter).


finsh_system_init() 下finsh_system_function_init() 的作用是什么呢?

答:初始化两个指针,一个指向所有命令的最开始,一个指向命令的最结尾。

CMD define逻辑

macro call :FINSH_FUNCTION_EXPORT(name, desc) --> MSH_FUNCTION_EXPORT_CMD(name, cmd, desc)

MSH_FUNCTION_EXPORT_CMD逻辑
#define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc)        \     ​        const char __fsym_##cmd##_name[] = #cmd;       \    /* cmd name to str */​        const char __fsym_##cmd##_desc[] = #desc;      \    /* cmd description to str */​        __declspec(allocate("FSymTab$f"))              \    /* put next struct to this section */​        const struct finsh_syscall __fsym_##cmd =      \​        {                                              \​          __fsym_##cmd##_name,                           \​          __fsym_##cmd##_desc,                           \​          (syscall_func)&name                           \​        };

FinSH CMD 处理逻辑

finsh_thread_entry函数用于处理来自用户的输入,大概有以下几个功能:

  • 鉴权
  • 循环读取一个字符串并处理:
    • 特殊字符的处理: 上下左右、制表符、回退、回车。对应历史命令读取、光标移动、命令和路径补全、删除当前命令、执行命令功能。
    • 普通字符,放入字符串存储等待处理。
流程图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PsFWhmpP-1667636697536)(6fc6a5a21447eeb3ce2ceeedebc41719.png)]

FinSH shell 状态机

初步阅读代码,我的理解是这个是为了处理上下左右四个键的输入方式而设计的。

WAIT_NORMAL // shell 处于等待接收正常字符的状态

WAIT_SPEC_KEY // shell 处于等待接收方向键的特殊字符的状态

WAIT_FUNC_KEY // shell 处于等待接收功能键的状态

相关的特殊按键的获取方式:

ps:在Win的env工具下仿真模拟msh读取不到上下左右的按键,猜测和windows 和 linux 下的按键的输入值不同有关。

KeyLinuxKeyWindows
Up0x1B 0x5B 0x41Up0xE0 0x48
Down0x1B 0x5B 0x42Down0xE0 0x50
Left0x1B 0x5B 0x44Left0xE0 0x4B
Right0x1B 0x5B 0x43Right0xE0 0x4D

FinSH context

struct finsh_shell
{struct rt_semaphore rx_sem;​    enum input_stat stat;​    rt_uint8_t echo_mode: 1;
​    rt_uint8_t prompt_mode: 1;#ifdef FINSH_USING_HISTORYrt_uint16_t current_history;rt_uint16_t history_count;​    char cmd_history[FINSH_HISTORY_LINES][FINSH_CMD_SIZE];
#endif​    char line[FINSH_CMD_SIZE + 1];
​    rt_uint16_t line_position;
​    rt_uint16_t line_curpos;#if !defined(RT_USING_POSIX_STDIO) && defined(RT_USING_DEVICE)rt_device_t device;
#endif#ifdef FINSH_USING_AUTHchar password[FINSH_PASSWORD_MAX];
#endif
};

FinSH input信息读取

rt_hw_board_init()中调用rt_device_t rt_console_set_device(const char *name)注册了console device。

请添加图片描述


http://chatgpt.dhexx.cn/article/0P3M7NRE.shtml

相关文章

从统一视角看各类高效finetune方法

每天给你送来NLP技术干货! 来自:圆圆的算法笔记 随着预训练模型参数量越来越大,迁移学习的成本越来越高,parameter-efficient tuning成为一个热点研究方向。在以前我们在下游任务使用预训练大模型,一般需要finetune模型…

finetune

finetune的含义是获取预训练好的网络的部分结构和权重,与自己新增的网络部分一起训练。下面介绍几种finetune的方法。 完整代码:https://github.com/toyow/learn_tensorflow/tree/master/finetune 一,如何恢复预训练的网络 方法一&#xf…

11.2 模型finetune

一、Transform Learning 与 Model Finetune 二、pytorch中的Finetune 一、Transfer Learning 与 Model Finetune 1. 什么是Transfer Learning? 迁移学习是机器学习的一个分支,主要研究源域的知识如何应用到目标域当中。迁移学习是一个很大的概念。 怎么理解源域…

飞桨深度学习学院零基础深度学习7日入门-CV疫情特辑学习笔记(四)DAY03 车牌识别

本课分为理论和实战两个部分 理论:卷积神经网络 1.思考全连接神经网络的问题 一般来收机器学习模型实践分为三个步骤,(1)建立模型 (2)选择损失函数 (3)参数调整学习 1.1 模型结构不…

unity sdk(android)-友盟推送SDK接入

注意:一开始想接友盟Unity的SDk,但是导入后缺少各种jar,所以最后还是接了android的,demo文档齐全 官方文档:开发者中心 按照官方文档对接即可, 接入流程 1、项目中com.android.tools.build:gradle配置&…

友盟推送学习

一、首次使用U_Push 1、首先注册友盟账号,进入工作台,选择产品U_Push。 2、创建应用 3、在自己的项目中自动集成SDK 开发环境要求: Android Studio 3.0以上 Android minSdkVersion: 14 Cradle: 4.4以上 在根目录build.gradle中添加mav…

Android 学习之如何集成友盟推送

我是利用Android studio 新建一个空的Android项目。 步骤一 导入第三方库 1.切换Android项目状态为Project状态 2.在main文件下新建 jniLibs文件夹(用来导入PushSDK项目下lib文件中的so文件) 3.在libs文件夹下添加友盟PuskSDK中的 jar 文件&#xff…

用PaddlePaddle(飞浆)实现车牌识别

项目描述:本次实践是一个多分类任务,需要将照片中的每个字符分别进行识别,完成车牌的识别 实践平台:百度AI实训平台-AI Studio、PaddlePaddle1.8.0 动态图 数据集介绍(自己去网上下载车牌识别数据集) 数据…

深度学习(五) CNN卷积神经网络

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 CNN卷积神经网络 前言一、CNN是什么?二、为什么要使用CNN?三、CNN的结构1.图片的结构2.卷积层1.感受野(Receptive Field)2.卷积…

CNN网络实现手写数字(MNIST)识别 代码分析

CNN网络实现手写数字(MNIST)识别 代码分析(自学用) Github代码源文件 本文是学习了使用Pytorch框架的CNN网络实现手写数字(MNIST)识别 #导入需要的包 import numpy as np //第三方库,用于进行科学计算 import torc…

Android删除chartty证书,C/C++知识点之android应用安全分析

本文主要向大家介绍了C/C知识点之android应用安全分析,通过具体的内容向大家展示,希望对大家学习C/C知识点有所帮助。 应用名 :OKEx(OKEx-android.apk) 包名 :com.okinc.okex MD5 :1ffbd328d13e91b661592cdf58516bd2 版…

代码编写过程 - 正确率折线图

获取绘图函数 首先,看到需要画acc和loss图。先去参考现成的,于是打开猫12分类,找到生成折线图的地方。 发现框内的两个函数绘制了折线图。既然是作为函数出现,说明已经有一定的封装,考虑能不能把整个函数搬走用。 由…

李宏毅机器学习课程HW03代码解释

作业3任务是将图片进行分类 从官网上下载数据到data文件里面。此外,将代码分为三个模块,分别是dataset,model以及main。 一、dataset模块 此模块作用是读取图片数据。 重要函数:os.path.join(path,x) 将path和x路径组合在一起 #导入库…

接入友盟厂商push通道遇到的坑

目录 调试友盟Push问题的检查清单 客户端、服务端数据协议 客户端接入方式 小米厂商通道 华为厂商通道 魅族厂商通道 VIVO厂商通道 OPPO厂商通道 支持桌面角标的厂商 吐槽一下集成友盟厂商通道时发现的问题 调试友盟Push问题的检查清单 过滤UmengPushAgent开头的日志…

Android集成友盟消息推送SDK

消息推送SDK快速集成: 申请AppKey ——> 接入Push SDK ——> 基础接口引入 ——> 消息推送测试 ——> 接入完成 1.申请AppKey 2.接入Push SDK 1)、加入依赖 //友盟push相关依赖(必须)implementationcom.umeng.umsdk:push:6.1.0impleme…

机器学习之手写决策树以及sklearn中的决策树及其可视化

文章目录 决策树理论部分基本算法划分选择信息熵 信息增益信息增益率基尼系数基尼指数 决策树代码实现参考 决策树理论部分 决策树的思路很简单,就是从数据集中挑选一个特征,然后进行分类。 基本算法 从伪代码中可以看出,分三种情况考虑&…

android使用友盟推送注册失败获取不到token accs bindapp error!

使用友盟推送注册失败获取不到token public void onFailure(String s, String s1)的值分别是“-9”和“accs bindapp error!”或者s的值为-11.都是同一个问题 就是主工程(除友盟PushSDK 其他的module均看成为主工程)so目录与PushSDK下的so目录不一致…

同时集成阿里云旺与友盟推送,初始化失败s:-11,s1:accs bindapp error!的解决办法

在应用中需要同时集成聊天和推送功能,聊天选用阿里的sdk(百川云旺),推送选用友盟的pushSDK。 这时候悲剧就出现了,注册友盟的时候报错。 I/com.umeng.message.PushAgent: register-->onFailure-->s:-11,s1:accs …

关于友盟s=-11;s1=accs bindapp error!的解决处理

项目使用了友盟推送之后,在部分手机上出现accs bindapp error,错误码-11的问题,为什么会出现这个问题呢,网上查找了很久,友盟给出的解释是so文件不正确。 具体链接:http://bbs.umeng.com/thread-23018-1-1…

友盟register failed: -11 accs bindapp error!

下载官方Demo后,替换自己的id包名后出现 register failed: -11 accs bindapp error! 经过一番搜索之后,都是说这二种原因 1、检查appkey和secret key是否配置正确,如果正确无误,请看步骤2。2、so文件配置有误,需重新配置: Pus…