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.pswp.cn/web/66071.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66071.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66071.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Redis 知識速覽

文章目錄 1. Redis 簡介2. Redis 優缺點3. Redis 高性能4. Redis VM 機制5. Redis 數據類型6. 應用場景7. 持久化8. 過期策略9. 內存相關10. 線程模型11. 事務12. 集群 1. Redis 簡介 定義&#xff1a;Redis 是一個用 C 語言編寫的高性能非關系型&#xff08;NoSQL&#xff09…

nginx-lua緩存機制

一. 簡述&#xff1a; 緩存是一個大型系統中非常重要的一個組成部分。在硬件層面&#xff0c;大部分的計算機硬件都會用緩存來提高速度&#xff0c;比如CPU會有多級緩存、RAID卡也有讀寫緩存。在軟件層面&#xff0c;我們用的數據庫就是一個緩存設計非常好的例子&#xff0c;在…

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;都是問題。 我們先整體的…

px、em 和 rem 的區別:深入理解 CSS 中的單位

文章目錄 前言一、px - 像素 (Pixel)二、em - 相對父元素字體大小 (Ems)三、rem - 相對于根元素字體大小 (Root Ems)四、綜合比較結語 前言 在CSS中&#xff0c;px、em和rem是三種用于定義尺寸&#xff08;如寬度、高度、邊距、填充等&#xff09;的長度單位。它們各自有不同的…

【CI/CD構建】關于不小心將springMVC注解寫在service層

背景 之前寫一個接口的時候沒有察覺到將RequestBody這個注解帶到service層了。 今天提交代碼的時候&#xff0c;插件沒有檢測到這個低級錯誤&#xff0c;導致試飛構建連maven編譯都過不了&#xff0c;maven找不到程序包org.springframework.web.bind.annotation這個包 結果…

Oracle Dataguard(主庫為雙節點集群)配置詳解(4):配置備庫

Oracle Dataguard&#xff08;主庫為雙節點集群&#xff09;配置詳解&#xff08;4&#xff09;&#xff1a;配置備庫 目錄 Oracle Dataguard&#xff08;主庫為雙節點集群&#xff09;配置詳解&#xff08;4&#xff09;&#xff1a;配置備庫一、為備庫配置靜態監聽1、配置 li…

《深入理解Mybatis原理》Mybatis中的緩存實現原理

一級緩存實現 什么是一級緩存&#xff1f; 為什么使用一級緩存&#xff1f; 每當我們使用MyBatis開啟一次和數據庫的會話&#xff0c;MyBatis會創建出一個SqlSession對象表示一次數據庫會話。 在對數據庫的一次會話中&#xff0c;我們有可能會反復地執行完全相同的查詢語句&…

win32匯編環境,窗口程序中單選框的一般操作示例

;運行效果 ;win32匯編環境,窗口程序中單選框的一般操作示例 ;比如在窗口程序中生成單選框&#xff0c;默認哪項選中&#xff0c;判斷當前選中哪一項&#xff0c;讓哪項選中&#xff0c;得到選中項的名稱等 ;直接抄進RadAsm可編譯運行。重點部分加備注。 ;以下是ASM文件 ;>&g…

從transformer到informer

Transformer和Informer都是深度學習領域中的模型架構&#xff0c;它們主要用于處理序列數據&#xff0c;如自然語言處理&#xff08;NLP&#xff09;和時間序列預測任務。 **Transformer**&#xff1a; Transformer模型最初在2017年由Google的研究者提出&#xff0c;它在NLP領…