掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯(lián)網(wǎng)交流
由于物聯(lián)網(wǎng)(IoT)的興起,對硬件進行編程變得越來越普遍。RT-Thread 可以讓你可以用 FinSH 從 Linux 命令行與設備進行溝通。
RT-Thread 是一個開源的實時操作系統(tǒng),用于對物聯(lián)網(wǎng)(IoT)設備進行編程。FinSH 是 RT-Thread 的命令行組件,它提供了一套操作界面,使用戶可以從命令行與設備進行溝通。它主要用于調(diào)試或查看系統(tǒng)信息。
通常情況下,開發(fā)調(diào)試使用硬件調(diào)試器和 printf 日志來顯示。但在某些情況下,這兩種方法并不是很有用,因為它是從運行的內(nèi)容中抽象出來的,而且它們可能很難解析。不過 RT-Thread 是一個多線程系統(tǒng),當你想知道一個正在運行的線程的狀態(tài),或者手動控制系統(tǒng)的當前狀態(tài)時,這很有幫助。因為它是多線程的,所以你能夠擁有一個交互式的 shell,你可以直接在設備上輸入命令、調(diào)用函數(shù)來獲取你需要的信息,或者控制程序的行為。如果你只習慣于 Linux 或 BSD 等現(xiàn)代操作系統(tǒng),這在你看來可能很普通,但對于硬件黑客來說,這是極其奢侈的,遠超將串行電纜直接連線到電路板上以獲取一絲錯誤的做法。
FinSH 有兩種模式。
在 C 語言解釋器模式下,F(xiàn)inSH 可以解析執(zhí)行大部分 C 語言的表達式,并使用函數(shù)調(diào)用訪問系統(tǒng)上的函數(shù)和全局變量。它還可以從命令行創(chuàng)建變量。
在 msh 模式下,F(xiàn)inSH 的操作與 Bash 等傳統(tǒng) shell 類似。
當我們在開發(fā) FinSH 時,我們了解到,在編寫命令行應用程序之前,你需要熟悉 GNU 命令行標準。這個標準實踐的框架有助于給界面帶入熟悉感,這有助于開發(fā)人員在使用時感到舒適和高效。
一個完整的 GNU 命令主要由四個部分組成。
你可以在任何命令中看到這一點。以 Git 為例:
git reset --hard HEAD~1
這一點可以分解為:
GNU command line standards
可執(zhí)行的命令是 git,子命令是 reset,使用的選項是 --head,參數(shù)是 HEAD~1。
再舉個例子:
systemctl enable --now firewalld
可執(zhí)行的命令是 systemctl,子命令是 enable,選項是 --now,參數(shù)是 firewalld。
想象一下,你想用 RT-Thread 編寫一個符合 GNU 標準的命令行程序。FinSH 擁有你所需要的一切,并且會按照預期運行你的代碼。更棒的是,你可以依靠這種合規(guī)性,讓你可以自信地移植你最喜歡的 Linux 程序。
下面是一個 RT-Thread 運行命令的例子,RT-Thread 開發(fā)人員每天都在使用這個命令:
usage: env.py package [-h] [--force-update] [--update] [--list] [--wizard][--upgrade] [--printenv]optional arguments:-h, --help show this help message and exit--force-update force update and clean packages, install or remove thepackages by your settings in menuconfig--update update packages, install or remove the packages by yoursettings in menuconfig--list list target packages--wizard create a new package with wizard--upgrade upgrade local packages list and ENV scripts from git repo--printenv print environmental variables to check
正如你所看到的那樣,它看起來很熟悉,行為就像你可能已經(jīng)在 Linux 或 BSD 上運行的大多數(shù) POSIX 應用程序一樣。當使用不正確或不充分的語法時,它會提供幫助,它支持長選項和短選項。這種通用的用戶界面對于任何使用過 Unix 終端的人來說都是熟悉的。
選項的種類很多,按長短可分為兩大類。
pkgs -h 中的 -h 選項。scons- --target-mdk5 中的 --target 選項。你可以把這些選項分為三類,由它們是否有參數(shù)來決定。
正如你對大多數(shù) Linux 命令的期望,F(xiàn)inSH 的選項解析非常靈活。它可以根據(jù)空格或等號作為定界符來區(qū)分一個選項和一個參數(shù),或者僅僅通過提取選項本身并假設后面的內(nèi)容是參數(shù)(換句話說,完全沒有定界符)。
wavplay -v 50wavplay -v50wavplay --vol=50如果你曾經(jīng)寫過命令行程序,你可能會知道,一般來說,你所選擇的語言有一個叫做 optparse 的庫或模塊。它是提供給程序員的,所以作為命令的一部分輸入的選項(比如 -v 或 --verbose)可以與命令的其他部分進行解析。這可以幫助你的代碼從一個子命令或參數(shù)中獲取一個選項。
當為 FinSH 編寫一個命令時,optparse 包希望使用這種格式:
MSH_CMD_EXPORT_ALIAS(pkgs, pkgs, this is test cmd.);
你可以使用長形式或短形式,或者同時使用兩種形式來實現(xiàn)選項。例如:
static struct optparse_long long_opts[] ={{"help" , 'h', OPTPARSE_NONE}, // Long command: help, corresponding to short command h, without arguments.{"force-update", 0 , OPTPARSE_NONE}, // Long comman: force-update, without arguments{"update" , 0 , OPTPARSE_NONE},{"list" , 0 , OPTPARSE_NONE},{"wizard" , 0 , OPTPARSE_NONE},{"upgrade" , 0 , OPTPARSE_NONE},{"printenv" , 0 , OPTPARSE_NONE},{ NULL , 0 , OPTPARSE_NONE}};
創(chuàng)建完選項后,寫出每個選項及其參數(shù)的命令和說明:
static void usage(void){rt_kprintf("usage: env.py package [-h] [--force-update] [--update] [--list] [--wizard]\n");rt_kprintf(" [--upgrade] [--printenv]\n\n");rt_kprintf("optional arguments:\n");rt_kprintf(" -h, --help show this help message and exit\n");rt_kprintf(" --force-update force update and clean packages, install or remove the\n");rt_kprintf(" packages by your settings in menuconfig\n");rt_kprintf(" --update update packages, install or remove the packages by your\n");rt_kprintf(" settings in menuconfig\n");rt_kprintf(" --list list target packages\n");rt_kprintf(" --wizard create a new package with wizard\n");rt_kprintf(" --upgrade upgrade local packages list and ENV scripts from git repo\n");rt_kprintf(" --printenv print environmental variables to check\n");}
下一步是解析。雖然你還沒有實現(xiàn)它的功能,但解析后的代碼框架是一樣的:
int pkgs(int argc, char **argv){int ch;int option_index;struct optparse options;if(argc == 1){usage();return RT_EOK;}optparse_init(&options, argv);while((ch = optparse_long(&options, long_opts, &option_index)) != -1){ch = ch;rt_kprintf("\n");rt_kprintf("optopt = %c\n", options.optopt);rt_kprintf("optarg = %s\n", options.optarg);rt_kprintf("optind = %d\n", options.optind);rt_kprintf("option_index = %d\n", option_index);}rt_kprintf("\n");return RT_EOK;}
這里是函數(shù)頭文件:
#include "optparse.h"#include "finsh.h"
然后,編譯并下載到設備上。
Output
對硬件進行編程似乎很嚇人,但隨著物聯(lián)網(wǎng)的發(fā)展,它變得越來越普遍。并不是所有的東西都可以或者應該在樹莓派上運行,但在 RT-Thread,F(xiàn)inSH 可以讓你保持熟悉的 Linux 感覺。
如果你對在裸機上編碼感到好奇,不妨試試 RT-Thread。

我們在微信上24小時期待你的聲音
解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯(lián)網(wǎng)交流