rtthread学习笔记系列(3) -- FINSH模块

文章目录

  • 3. FINSH模块
    • 3.1MSH
      • 3.1.1初始化
        • 3.1.1.1FSymtab段
        • 3.1.1.2 宏
      • 3.1.2遍历FINSH命令
      • 3.1.3TAB补全实现
        • 3.1.3.1 `msh_auto_complete`
        • 3.1.3.2 `msh_opt_auto_complete`
      • 3.1.4 TAB 子选项自动补全
    • 3.2 SHELL
      • 3.2.1 `finsh_system_init`分配finsh结构体使用内存
      • 3.2.2 `finsh_thread_entry`
      • 3.2.3 历史命令显示
      • 3.2.4 MSH命令执行
    • 3.3 cmd&msh_parse&&msh_file

3. FINSH模块

https://github.com/wdfk-prog/RT-Thread-Study

3.1MSH

3.1.1初始化

  1. 根据链接脚本指明FINSH使用内存空间 _syscall_table_begin _syscall_table_end的地址
3.1.1.1FSymtab段
        . = ALIGN(4);__fsymtab_start = .;KEEP(*(FSymTab))__fsymtab_end = .;
  • __fsymtab_start__fsymtab_end用于指明finsh使用内存
  • FSymTab用于存放所有注册命令的结构体 struct finsh_syscall,包括命令名称,命令选项,命令描述,命令函数执行地址信息
3.1.1.2 宏
/*** @ingroup msh** This macro exports a command to module shell.** @param command is the name of the command.* @param desc is the description of the command, which will show in help list.* @param opt This is an option, enter any content to enable option completion*/
/* MSH_CMD_EXPORT(command, desc) or MSH_CMD_EXPORT(command, desc, opt) */
#define MSH_CMD_EXPORT(...)                                 \__MSH_GET_MACRO(__VA_ARGS__, _MSH_FUNCTION_CMD2_OPT,    \_MSH_FUNCTION_CMD2)(__VA_ARGS__)#define __MSH_GET_MACRO(_1, _2, _3, _FUN, ...)  _FUN#define _MSH_FUNCTION_CMD2(a0, a1)       \MSH_FUNCTION_EXPORT_CMD(a0, a0, a1, 0)#define _MSH_FUNCTION_CMD2_OPT(a0, a1, a2)       \MSH_FUNCTION_EXPORT_CMD(a0, a0, a1, a0##_msh_options)#define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc)                      \const char __fsym_##cmd##_name[] rt_section(".rodata.name") = #cmd;    \const char __fsym_##cmd##_desc[] rt_section(".rodata.name") = #desc;   \rt_used const struct finsh_syscall __fsym_##cmd rt_section("FSymTab")= \{                           \__fsym_##cmd##_name,    \__fsym_##cmd##_desc,    \(syscall_func)&name     \};
  1. 宏过载语法,选择2个参数使用 MSH_FUNCTION_CMD2,_MSH_FUNCTION_CMD2的desc为0;3个参数使用 MSH_FUNCTION_CMD2_OPT
  2. 定义字符串成员,地址定义为.rodata.name;内容为#cmd;
const char __fsym_##cmd##_name[] rt_section(".rodata.name") = #cmd;    \
const char __fsym_##cmd##_desc[] rt_section(".rodata.name") = #desc;   \
  1. __fsym_##cmd存储名称,细节,挂钩的函数指针地址

3.1.2遍历FINSH命令

    for (index = _syscall_table_begin;index < _syscall_table_end;FINSH_NEXT_SYSCALL(index)){}

3.1.3TAB补全实现

  1. 判断输入为 /t
  2. 将光标移动到行首;使用 /b退格,一个个退回删除之前的显示字符
  3. 将命令首地址传入 shell_auto_complete
  4. 计算偏移地址
  • shell_auto_complete
3.1.3.1 msh_auto_complete
  1. 首地址为 /0,即无输入任何字符串,直接TAB /t,则调用 msh_cmd输出所有支持的命令
  2. 匹配命令名字,并输出命令
        for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index)){/* skip finsh shell function */cmd_name = (const char *) index->name;if (strncmp(prefix, cmd_name, strlen(prefix)) == 0){if (min_length == 0){/* set name_ptr */name_ptr = cmd_name;/* set initial length */min_length = strlen(name_ptr);}length = str_common(name_ptr, cmd_name);if (length < min_length)min_length = length;rt_kprintf("%s\n", cmd_name);}}
  1. 输出提示字符 msh />与命令输入的字符串
 rt_kprintf("%s%s", FINSH_PROMPT, prefix);
  • finsh_get_prompt输出提示
#define FINSH_PROMPT        finsh_get_prompt()finsh_prompt_custom 用于自定义替换默认提示
finsh_set_prompt("artpi@root");
3.1.3.2 msh_opt_auto_complete
   argc = msh_get_argc(prefix, &opt_str);if (argc){opt = msh_get_cmd_opt(prefix);}else if (!msh_get_cmd(prefix, strlen(prefix)) && (' ' == prefix[strlen(prefix) - 1])){opt = msh_get_cmd_opt(prefix);}
  1. msh_get_argc 获取命令空格之后参数
  2. 没获取到参数时,判断 prefix不是一个已知的命令,并且命令行字符串的最后一个字符是空格
  3. msh_get_cmd_opt获取 syscall_table中是否有匹配的命令
  4. argc为0,输出 msh_opt_help所有的命令?
  5. msh_opt_completemsh_auto_complete作用相同

3.1.4 TAB 子选项自动补全

  1. msh_opt_auto_complete
  2. 使用完成命令注册
#define CMD_OPTIONS_STATEMENT(command) static struct msh_cmd_opt command##_msh_options[];
#define CMD_OPTIONS_NODE_START(command) static struct msh_cmd_opt command##_msh_options[] = {
#define CMD_OPTIONS_NODE(_id, _name, _des) {.id = _id, .name = #_name, .des = #_des},
#define CMD_OPTIONS_NODE_END    {0},};CMD_OPTIONS_NODE_START(vref_temp_get)
CMD_OPTIONS_NODE(1, write, tx data)
CMD_OPTIONS_NODE(2, irq, irq list)
CMD_OPTIONS_NODE(3, speed-test, eth physical speed test)
CMD_OPTIONS_NODE_END

3.2 SHELL

3.2.1 finsh_system_init分配finsh结构体使用内存

  1. 创建 finsh_thread_entry线程
  2. 创建信号量,用于阻塞接字符串;信号量由控制台设备对象解除
  3. 设置提示模式
  4. INIT_APP_EXPORT中调用

3.2.2 finsh_thread_entry

  1. 获取控制台设备对象

  2. 获取控制台密码用于密码确认

    • finsh_wait_auth
      • 阻塞等待获取密码;密码输入显示 *
      • 敲入回车认为密码输入完成
      • 进入密码验证判断;失败线程阻塞等待2S再次获取输入字符
  3. 进入控制台线程

    1. finsh_getchar
    • rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER);等待信号量释放
      • finsh_rx_ind函数中释放信号量
    1. handle control key判断
         /** handle control key* up key  : 0x1b 0x5b 0x41* down key: 0x1b 0x5b 0x42* right key:0x1b 0x5b 0x43* left key: 0x1b 0x5b 0x44*/
    
    • 上下键:历史命令显示
    • 左右键:移动当前光标
    • tab键 补全命令
    • 删除键:删除
    • 回车键:执行msh命令
  4. 设置控制台设备模式

/*** @ingroup finsh** This function sets the input device of finsh shell.** @param device_name the name of new input device.*/
void finsh_set_device(const char *device_name)
{rt_device_t dev = RT_NULL;RT_ASSERT(shell != RT_NULL);dev = rt_device_find(device_name);if (dev == RT_NULL){rt_kprintf("finsh: can not find device: %s\n", device_name);return;}/* check whether it's a same device */if (dev == shell->device) return;/* open this device and set the new device in finsh shell */if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | \RT_DEVICE_FLAG_STREAM) == RT_EOK){if (shell->device != RT_NULL){/* close old finsh device */rt_device_close(shell->device);rt_device_set_rx_indicate(shell->device, RT_NULL);}/* clear line buffer before switch to new device */rt_memset(shell->line, 0, sizeof(shell->line));shell->line_curpos = shell->line_position = 0;shell->device = dev;rt_device_set_rx_indicate(dev, finsh_rx_ind);}
}

3.2.3 历史命令显示

  1. 回车存入历史命令 shell_push_history
  2. 上下键显示历史命令 shell_handle_history

3.2.4 MSH命令执行

3.3 cmd&msh_parse&&msh_file

  • 一些系统命令的输出
  • 一些共用的解析
  • 文件系统的命令支持

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

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

相关文章

Java 面试中的高频算法题详解

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

【Python项目】手写数字识别系统

【Python项目】手写数字识别系统 技术简介&#xff1a;采用Python技术、Django框架、MYSQL数据库等实现。 系统简介&#xff1a;手写数字识别系统主要的功能有手写字识别、手写字管理、修改密码、个人信息和用户管理。 背景&#xff1a; 在当今这个飞速发展的时代&#xff0c;…

Springboot + vue 小区物业管理系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

空指针:HttpSession异常,SpringBoot集成WebSocket

异常可能性&#xff1a; 404 &#xff1a; 请检查拦截器是否将请求拦截WebSocket握手期间HttpSession为空 HttpSession为空 方法一 &#xff1a; 网上参考大量的文档&#xff0c;有说跟前端请求域名有关系的。 反正对我来说&#xff0c;没啥用无法连接。 需使用 localhost&a…

什么是视频孪生智慧能源?视频孪生智慧能源的应用案例

‌视频孪生智慧能源是集三维地理信息系统、视频虚实融合、数字孪生、人工智能等多技术于一体的综合应用&#xff0c;旨在实现对能源系统的实时、动态、全方位监控和管理‌。 具体来说&#xff0c;视频孪生智慧能源通过以下方式实现其功能&#xff1a; ‌技术融合‌&#xff1a;…

【update 更新数据语法合集】.NET开源ORM框架 SqlSugar 系列

系列文章目录 &#x1f380;&#x1f380;&#x1f380; .NET开源 ORM 框架 SqlSugar 系列 &#x1f380;&#x1f380;&#x1f380; 文章目录 系列文章目录前言 &#x1f343;一、实体对象更新1.1 单条与批量1.2 不更新某列1.3 只更新某列1.4 NULL列不更新1.5 无主键/指定列…

006-excel数据输出insert语句

一、在空白列插入&#xff0c;选择需要的列 "INSERT INTO tab_name1 (code, name) VALUES ("&A1&", "&B1&");"二、 拖动填充块&#xff0c;或者双击填充块&#xff08;可以快速填充整列&#xff09; 三、直接把生成的 insert 语…

前端组件开发:组件开发 / 定义配置 / 配置驱动开发 / 爬虫配置 / 组件V2.0 / form表单 / table表单

一、最早的灵感 最早的灵感来自sprider / 网络爬虫 / 爬虫配置&#xff0c;在爬虫爬取网站文章时候&#xff0c;会输入给爬虫一个配置文件&#xff0c;里边的内容是一个json对象。里边包含了所有想要抓取的页面的信息。爬虫通过这个配置就可以抓取目标网站的数据。其实本文要引…

43.Textbox的数据绑定 C#例子 WPF例子

固定最简步骤&#xff0c;包括 XAML&#xff1a; 题头里引入命名空间 标题下面引入类 box和block绑定属性 C#&#xff1a; 通知的类&#xff0c;及对应固定的任务 引入字段 引入属性 属性双触发&#xff0c;其中一个更新block的属性 block>指向box的属性 从Textbo…

excel按行检索(index+match)

假设你的数据表如下&#xff1a; 假设 数据区域是 A1:D4。 你想查询某人在某个日期的数据。 实现步骤 公式 在某个单元格中使用以下公式&#xff1a; excel 复制代码 INDEX(A2:D4, MATCH(“张三”, A2:A4, 0), MATCH(“2025/01/02”, A1:D1, 0)) 2. 公式拆解 MATCH(“张三”,…

信创改造-龙蜥操作系统搭载MySql、Tomcat等服务

龙蜥操作系统 Anolis OS 8 是 OpenAnolis 社区推出的完全开源、中立、开放的发行版&#xff0c;它支持多计算架构&#xff0c;也面向云端场景优化&#xff0c;兼容 CentOS 软件生态。Anolis OS 8 旨在为广大开发者和运维人员提供稳定、高性能、安全、可靠、开源的操作系统服务。…

FPGA EDA软件的位流验证

位流验证&#xff0c;对于芯片研发是一个非常重要的测试手段&#xff0c;对于纯软件开发人员&#xff0c;最难理解的就是位流验证。在FPGA芯片研发中&#xff0c;位流验证是在做什么&#xff0c;在哪些阶段需要做位流验证&#xff0c;如何做&#xff1f;都是问题。 我们先整体的…

【CI/CD构建】关于不小心将springMVC注解写在service层

背景 之前写一个接口的时候没有察觉到将RequestBody这个注解带到service层了。 今天提交代码的时候&#xff0c;插件没有检测到这个低级错误&#xff0c;导致试飞构建连maven编译都过不了&#xff0c;maven找不到程序包org.springframework.web.bind.annotation这个包 结果…

《深入理解Mybatis原理》Mybatis中的缓存实现原理

一级缓存实现 什么是一级缓存&#xff1f; 为什么使用一级缓存&#xff1f; 每当我们使用MyBatis开启一次和数据库的会话&#xff0c;MyBatis会创建出一个SqlSession对象表示一次数据库会话。 在对数据库的一次会话中&#xff0c;我们有可能会反复地执行完全相同的查询语句&…

win32汇编环境,窗口程序中单选框的一般操作示例

;运行效果 ;win32汇编环境,窗口程序中单选框的一般操作示例 ;比如在窗口程序中生成单选框&#xff0c;默认哪项选中&#xff0c;判断当前选中哪一项&#xff0c;让哪项选中&#xff0c;得到选中项的名称等 ;直接抄进RadAsm可编译运行。重点部分加备注。 ;以下是ASM文件 ;>&g…

个人主页搭建全流程(Nginx部署+SSL配置+DCDN加速)

前言 最近开始准备秋招&#xff0c;打算做一个个人主页&#xff0c;以便在秋招市场上更有竞争力。 目前&#xff0c;现有的一些搭建主页的博文教程存在以下一些问题&#xff1a; 使用Github Page进行部署&#xff0c;这在国内访问容易受阻使用宝塔面板等框架&#xff0c;功能…

Spring MVC简单数据绑定

【图书介绍】《SpringSpring MVCMyBatis从零开始学&#xff08;视频教学版&#xff09;&#xff08;第3版&#xff09;》_springspringmvcmybatis从零开始 代码、课件、教学视频与相关软件包下载-CSDN博客 《SpringSpring MVCMyBatis从零开始学(视频教学版)&#xff08;第3版&…

Mac上安装Label Studio

在Mac上安装Anaconda并随后安装Label Studio&#xff0c;可以按照以下步骤进行&#xff1a; 1. 在Mac上安装Anaconda 首先&#xff0c;你需要从Anaconda的官方网站下载适用于Mac的安装程序。访问Anaconda官网&#xff0c;点击“Download Anaconda”按钮&#xff0c;选择适合M…

vscode开启调试模式,结合Delve调试器调试golang项目详细步骤

1.前期准备 (1).在vs code中的扩展程序中搜索并安装Go扩展程序 (2).安装 Delve 调试器 go install github.com/go-delve/delve/cmd/dlvlatest (3).打开vs code的命令面板&#xff0c;输入Go: Install/Update Tools&#xff0c;并单击该命令执行&#xff0c;安装或更新Go语…

SQL面试题1:连续登陆问题

引言 场景介绍&#xff1a; 许多互联网平台为了提高用户的参与度和忠诚度&#xff0c;会推出各种连续登录奖励机制。例如&#xff0c;游戏平台会给连续登录的玩家发放游戏道具、金币等奖励&#xff1b;学习类 APP 会为连续登录学习的用户提供积分&#xff0c;积分可兑换课程或…