RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一個(gè)小而美的嵌入式shell - letter shell

嵌入式大雜燴 ? 來(lái)源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2023-06-10 15:11 ? 次閱讀

源碼地址:https://github.com/NevermindZZT/letter-shell

1 Letter shell簡(jiǎn)介

熟悉Linux的朋友的都知道,shell包裹在內(nèi)核之外的人機(jī)交互界面,用于用戶和內(nèi)核之間打交道的功能,類似于windows CMD。 通過(guò)Shell將輸入的命令與內(nèi)核通訊,好讓內(nèi)核可以控制硬件開(kāi)正確無(wú)誤的操作工作。Shell有著不同的分類,比如Bourne shell(sh),Korn shell(ksh)、C shell (csh)、Bourne-again shell(bash)、tcsh。其中最常用的有csh和bash。Shell本身是一個(gè)用C語(yǔ)言編寫(xiě)的程序,它是用戶使用Unix/Linux的橋梁,用戶的大部分工作都是通過(guò)Shell完成的。

然而在嵌入式中,由于資源有限,自然很少使用shell,但隨著MCU的資源越來(lái)越豐富,一些適用于嵌入式的shell工具也就問(wèn)世了,本問(wèn)將要介紹的是Letter shell,Letter shell是一個(gè)體積極小的嵌入式shell,當(dāng)前最新版本是3.X。

F:\\File\\嵌入式項(xiàng)目\\1 工具\(yùn)\一個(gè)小而美的嵌入式shell - letter shell\\源碼\\letter-shell\\doc\\img\\shell_info.png

Letter shell有如下功能:

  • 命令自動(dòng)補(bǔ)全,使用TAB鍵補(bǔ)全命令
  • 命令幫助,使用help [command]顯示命令幫助
  • 幫助補(bǔ)全,輸入命令后雙擊TAB鍵補(bǔ)全命令幫助指令
  • 快捷鍵,支持使用CTRL+A~Z組合按鍵直接調(diào)用函數(shù)
  • shell變量,支持在shell中查看和修改變量值,支持變量作為命令參數(shù)
  • 登錄密碼,支持在shell中使用登錄密碼,支持超時(shí)自動(dòng)鎖定

2 Letter shell移植

Shell是一個(gè)命令行交互式形式存在,那最常規(guī)的就是使用MCU的串口資源了,當(dāng)然也可使用USB模擬的虛擬串口。

Letter shell的移植比較簡(jiǎn)單,既然需要占用串口資源,那么首先要準(zhǔn)備一個(gè)裸機(jī)工程,該工程需要事先串口的收發(fā),關(guān)于串口的實(shí)現(xiàn)請(qǐng)參看逼著文章:

標(biāo)準(zhǔn)庫(kù):https://bruceou.blog.csdn.net/article/details/79341769

HAL庫(kù):https://bruceou.blog.csdn.net/article/details/109190370

筆者本文以標(biāo)準(zhǔn)庫(kù)為例講解。

1.復(fù)制源碼

首先下載letter-shell,然后在工程中新建Letter_shell目錄,將letter-shell目錄下的src的文件復(fù)制到工程目錄Middlewares/Letter_shell中。

C:\\Users\\BruceOu\\Desktop\\1.png

2.新建接口文件

在工程用戶目錄下新建shell_port.c和shell_port.h文件,當(dāng)然也可以放在User目錄。

3.配置工程

打開(kāi)Keil,添加相應(yīng)的文件。

1686380797023qlrrgj4bab

然后添加相應(yīng)的頭文件路徑。

168638079732110406rx2s2

接下來(lái)就是實(shí)現(xiàn)Letter shell的收發(fā)。

發(fā)送代碼如下:

/**
 * @brief 用戶shell寫(xiě)
 * 
 * @param data 數(shù)據(jù)
 */
void userShellWrite(char data)
{
    USART_SendData(USART1, (uint8_t) data);
    /* 等待發(fā)送完畢 */
    while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);		
}

接收采用中斷的方式,代碼如下:

/**
  * @brief  This function handles USART1 Handler.
  * @param  None
  * @retval None
  */
void USART1_IRQHandler(void)
{
    uint8_t ch;  //接收中斷緩沖

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
      ch = USART_ReceiveData(USART1);

      //ch = USART1- >DR;
      //調(diào)用shell處理數(shù)據(jù)的接口
      shellHandler(&shell, ch);
    } 
}

還需要實(shí)現(xiàn)Letter shell初始化接口。

/**
 * @brief 用戶shell初始化
 * 
 */
void userShellInit(void)
{
    shell.write = userShellWrite;
    shellInit(&shell, shellBuffer, 512);
}

最后在主函數(shù)中初始化即可。

/**
  * @brief  mian
  * @param  None
  * @retval int
  */
int main(void)
{
    /* 配置SysTick 為10us中斷一次 */
    SysTick_Init();

    /* USART1 配置模式為 115200 8-N-1,中斷接收 */
    USART1_Config();

    userShellInit();

    for(;;)
    {
        Delay_ms(50);
    }
}

好了,這就移植完成了,編譯、下載,連接串口1,使用xshell等工具,打印信息如下:

1686380797656v36x5l4oy3

很簡(jiǎn)單吧。

3 Letter shell應(yīng)用

3.1 Letter shell宏定義

在開(kāi)發(fā)Letter shell應(yīng)用前,需要知道Letter shell的宏定義,其宏定義在shell_cfg.h文件。

#ifndef __SHELL_CFG_H__
#define __SHELL_CFG_H__


/**
 * @brief 是否使用默認(rèn)shell任務(wù)while循環(huán),使能宏`SHELL_USING_TASK`后此宏有意義
 *        使能此宏,則`shellTask()`函數(shù)會(huì)一直循環(huán)讀取輸入,一般使用操作系統(tǒng)建立shell
 *        任務(wù)時(shí)使能此宏,關(guān)閉此宏的情況下,一般適用于無(wú)操作系統(tǒng),在主循環(huán)中調(diào)用`shellTask()`
 */
#define     SHELL_TASK_WHILE            1

/**
 * @brief 是否使用命令導(dǎo)出方式
 *        使能此宏后,可以使用`SHELL_EXPORT_CMD()`等導(dǎo)出命令
 *        定義shell命令,關(guān)閉此宏的情況下,需要使用命令表的方式
 */
#define     SHELL_USING_CMD_EXPORT      1

/**
 * @brief 是否使用shell伴生對(duì)象
 *        一些擴(kuò)展的組件(文件系統(tǒng)支持,日志工具等)需要使用伴生對(duì)象
 */
#define     SHELL_USING_COMPANION       0

/**
 * @brief 支持shell尾行模式
 */
#define     SHELL_SUPPORT_END_LINE      0

/**
 * @brief 是否在輸出命令列表中列出用戶
 */
#define     SHELL_HELP_LIST_USER        0

/**
 * @brief 是否在輸出命令列表中列出變量
 */
#define     SHELL_HELP_LIST_VAR         0

/**
 * @brief 是否在輸出命令列表中列出按鍵
 */
#define     SHELL_HELP_LIST_KEY         0

/**
 * @brief 是否在輸出命令列表中展示命令權(quán)限
 */
#define     SHELL_HELP_SHOW_PERMISSION  1

/**
 * @brief 使用LF作為命令行回車觸發(fā)
 *        可以和SHELL_ENTER_CR同時(shí)開(kāi)啟
 */
#define     SHELL_ENTER_LF              1

/**
 * @brief 使用CR作為命令行回車觸發(fā)
 *        可以和SHELL_ENTER_LF同時(shí)開(kāi)啟
 */
#define     SHELL_ENTER_CR              1

/**
 * @brief 使用CRLF作為命令行回車觸發(fā)
 *        不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同時(shí)開(kāi)啟
 */
#define     SHELL_ENTER_CRLF            0

/**
 * @brief 使用執(zhí)行未導(dǎo)出函數(shù)的功能
 *        啟用后,可以通過(guò)`exec [addr] [args]`直接執(zhí)行對(duì)應(yīng)地址的函數(shù)
 * @attention 如果地址錯(cuò)誤,可能會(huì)直接引起程序崩潰
 */
#define     SHELL_EXEC_UNDEF_FUNC       0

/**
 * @brief shell命令參數(shù)最大數(shù)量
 *        包含命令名在內(nèi),超過(guò)8個(gè)參數(shù)并且使用了參數(shù)自動(dòng)轉(zhuǎn)換的情況下,需要修改源碼
 */
#define     SHELL_PARAMETER_MAX_NUMBER  8

/**
 * @brief 歷史命令記錄數(shù)量
 */
#define     SHELL_HISTORY_MAX_NUMBER    5

/**
 * @brief 雙擊間隔(ms)
 *        使能宏`SHELL_LONG_HELP`后此宏生效,定義雙擊tab補(bǔ)全help的時(shí)間間隔
 */
#define     SHELL_DOUBLE_CLICK_TIME     200

/**
 * @brief 管理的最大shell數(shù)量
 */
#define     SHELL_MAX_NUMBER            5

/**
 * @brief shell格式化輸出的緩沖大小
 *        為0時(shí)不使用shell格式化輸出
 */
#define     SHELL_PRINT_BUFFER          128

/**
 * @brief shell格式化輸入的緩沖大小
 *        為0時(shí)不使用shell格式化輸入
 * @note shell格式化輸入會(huì)阻塞shellTask, 僅適用于在有操作系統(tǒng)的情況下使用
 */
#define     SHELL_SCAN_BUFFER          0

/**
 * @brief 獲取系統(tǒng)時(shí)間(ms)
 *        定義此宏為獲取系統(tǒng)Tick,如`HAL_GetTick()`
 * @note 此宏不定義時(shí)無(wú)法使用雙擊tab補(bǔ)全命令help,無(wú)法使用shell超時(shí)鎖定
 */
#define     SHELL_GET_TICK()            0

/**
 * @brief shell內(nèi)存分配
 *        shell本身不需要此接口,若使用shell伴生對(duì)象,需要進(jìn)行定義
 */
#define     SHELL_MALLOC(size)          0

/**
 * @brief shell內(nèi)存釋放
 *        shell本身不需要此接口,若使用shell伴生對(duì)象,需要進(jìn)行定義
 */
#define     SHELL_FREE(obj)             0

/**
 * @brief 是否顯示shell信息
 */
#define     SHELL_SHOW_INFO             1

/**
 * @brief 是否在登錄后清除命令行
 */
#define     SHELL_CLS_WHEN_LOGIN        1

/**
 * @brief shell默認(rèn)用戶
 */
#define     SHELL_DEFAULT_USER          "letter"

/**
 * @brief shell默認(rèn)用戶密碼
 *        若默認(rèn)用戶不需要密碼,設(shè)為""
 */
#define     SHELL_DEFAULT_USER_PASSWORD ""

/**
 * @brief shell自動(dòng)鎖定超時(shí)
 *        shell當(dāng)前用戶密碼有效的時(shí)候生效,超時(shí)后會(huì)自動(dòng)重新鎖定shell
 *        設(shè)置為0時(shí)關(guān)閉自動(dòng)鎖定功能,時(shí)間單位為`SHELL_GET_TICK()`單位
 * @note 使用超時(shí)鎖定必須保證`SHELL_GET_TICK()`有效
 */
#define     SHELL_LOCK_TIMEOUT          0 * 60 * 1000

#endif

shell_cfg.h文件已經(jīng)注釋了,筆者就不再贅述了。

3.2 Letter shell內(nèi)置命令

在 Letter shell中默認(rèn)內(nèi)置了一些 shell命令,在 shell中輸入 help 后回車或者直接按下 Tab 鍵,就可以打印當(dāng)前系統(tǒng)支持的所有命令。

按下 Tab 鍵后可以列出當(dāng)前支持的所有命令。以下為按下 Tab 鍵后打印出來(lái)的當(dāng)前支持的所有顯示Letter shell中的命令,左邊是命令名稱,右邊是關(guān)于命令的描述:

168638079794723wdssedte

  • 自定義 shell命令

自定義的 shell命令,可以在 shell模式下被運(yùn)行,將一個(gè)命令導(dǎo)出到 shell模式可以使用如下宏接口:

SHELL_EXPORT_CMD(_attr, _name, _func, _desc)

參數(shù) 描述
_attr 命令屬性
_name 命令名
_func 命令函數(shù)
_desc 命令描述

原型如下:

#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \\
				const char shellCmd##_name[] = #_name; \\
				const char shellDesc##_name[] = #_desc; \\
				const ShellCommand \\
				shellCommand##_name SECTION("shellCommand") =  \\
				{ \\
						.attr.value = _attr, \\
						.data.cmd.name = shellCmd##_name, \\
						.data.cmd.function = (int (*)())_func, \\
						.data.cmd.desc = shellDesc##_name \\
				}

導(dǎo)出無(wú)參數(shù)命令時(shí),函數(shù)的入?yún)?void,示例如下:

`

void hello(void)
{
    printf("hello letter shell!\\n");
}

//導(dǎo)出到命令列表里
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), hello, hello, hello);

系統(tǒng)運(yùn)行起來(lái)后,在 shell控制臺(tái)按 tab 鍵可以看到導(dǎo)出的命令,運(yùn)行 hello 命令,運(yùn)行結(jié)果如下所示:

1686380798207dxg57s5879

導(dǎo)出有參數(shù)的命令時(shí),還可傳入?yún)?shù)。導(dǎo)出有參數(shù)命令示例如下:

void parameter_test (int num, char *str)
{
    printf("parameter test: num = %d, str = %s !\\r\\n", num, str);

}
//導(dǎo)出到命令列表里
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), parameter_test, parameter_test, parameter test);

系統(tǒng)運(yùn)行起來(lái)后,在 shell控制臺(tái)按 tab 鍵可以看到導(dǎo)出的命令,運(yùn)行parameter_test命令,運(yùn)行結(jié)果如下所示:

1686380798488wepvp3mzc7

值得注意的是,命令參數(shù)的最大個(gè)數(shù)在中shell_cfg.h配置,默認(rèn)最大是8,但是命令占了一個(gè)參數(shù),因此用戶可用的應(yīng)該是7個(gè)。

/**
 * @brief shell命令參數(shù)最大數(shù)量
 *        包含命令名在內(nèi),超過(guò)8個(gè)參數(shù)并且使用了參數(shù)自動(dòng)轉(zhuǎn)換的情況下,需要修改源碼
 */
#define     SHELL_PARAMETER_MAX_NUMBER  8

Letter shell不僅可以使用命令的方式運(yùn)行程序,還可像Linux的終端一樣,還能通過(guò)上下鍵能選擇歷史命令,歷史命令的個(gè)數(shù)默認(rèn)最大為5個(gè)。

/**
 * @brief 歷史命令記錄數(shù)量
 */
#define     SHELL_HISTORY_MAX_NUMBER    5

非常的方便,Letter shell很強(qiáng)大,還有很多功能可玩,本文先講到這里,后面再深入講解Letter shell的設(shè)計(jì)思想。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5082

    文章

    19104

    瀏覽量

    304791
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11292

    瀏覽量

    209322
  • WINDOWS
    +關(guān)注

    關(guān)注

    3

    文章

    3541

    瀏覽量

    88619
  • Shell
    +關(guān)注

    關(guān)注

    1

    文章

    365

    瀏覽量

    23354
  • GitHub
    +關(guān)注

    關(guān)注

    3

    文章

    468

    瀏覽量

    16427
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    嵌入式Linux入門(三、Linux Shell及常用命令說(shuō)明)

    嵌入式 Linux入 門第三課,熟悉掌握 Linux 常用 Shell 命令 ...... 矜辰所致
    的頭像 發(fā)表于 06-21 10:50 ?1310次閱讀
    <b class='flag-5'>嵌入式</b>Linux入門(三、Linux <b class='flag-5'>Shell</b>及常用命令說(shuō)明)

    嵌入式Linux入門(五、Shell腳本編程上:認(rèn)識(shí)Shell腳本)

    大家好,是矜辰所致,嵌入式 Linux入 門第五課,本課開(kāi)始簡(jiǎn)單學(xué)習(xí)Shell 腳本編程。
    的頭像 發(fā)表于 07-13 16:10 ?1616次閱讀
    <b class='flag-5'>嵌入式</b>Linux入門(五、<b class='flag-5'>Shell</b>腳本編程上:認(rèn)識(shí)<b class='flag-5'>Shell</b>腳本)

    Linux shell函數(shù)簡(jiǎn)介和使用方法

    作為個(gè)嵌入式 Linux 工程師,肯定需要編寫(xiě) shell 腳本進(jìn)行些自動(dòng)化工作。剛好,我最近就有類似需求——
    發(fā)表于 08-25 16:21 ?1166次閱讀
    Linux <b class='flag-5'>shell</b>函數(shù)簡(jiǎn)介和使用方法

    基于APM32F4移植使用letter-shell命令行終端

    letter shell個(gè)C語(yǔ)言編寫(xiě)的,可以嵌入在程序中的嵌入式
    的頭像 發(fā)表于 11-03 17:23 ?1450次閱讀
    基于APM32F4移植使用<b class='flag-5'>letter-shell</b>命令行終端

    嵌入式Linux開(kāi)發(fā)入門普及課程之Shell編程基礎(chǔ)

    視頻主題:Shell編程基礎(chǔ)視頻主講:曾宏安,華清遠(yuǎn)見(jiàn)企業(yè)學(xué)院(www.farsight.com.cn)講師。視頻簡(jiǎn)介:嵌入式公益培訓(xùn)活動(dòng)是華清遠(yuǎn)見(jiàn)嵌入式普及推廣活動(dòng)之,主要面向
    發(fā)表于 08-13 15:08

    嵌入式Linux開(kāi)發(fā)工具-shell編程介紹

    嵌入式Linux系統(tǒng)開(kāi)發(fā)(文件、進(jìn)程、線程、網(wǎng)絡(luò))20嵌入式系統(tǒng)移植8h嵌入式驅(qū)動(dòng)開(kāi)發(fā)8h自動(dòng)生成: CMake autotool嵌入式Linux開(kāi)發(fā)工具-
    發(fā)表于 11-08 08:50

    Shell與變量的相關(guān)資料分享

    筆記系列嵌入式系統(tǒng)方向?qū)W習(xí)筆記1嵌入式系統(tǒng)方向?qū)W習(xí)筆記2嵌入式系統(tǒng)方向?qū)W習(xí)筆記3嵌入式系統(tǒng)方向?qū)W習(xí)筆記4文章目錄筆記系列前言、開(kāi)發(fā)工具的總
    發(fā)表于 12-22 08:11

    【CW32飯盒派開(kāi)發(fā)板試用體驗(yàn)】+ 串口letter-shell 移植

    本次主要移植letter-shell過(guò)程。 letter shell個(gè)C語(yǔ)言編寫(xiě)的,可以嵌入
    發(fā)表于 06-11 12:20

    嵌入式和物聯(lián)網(wǎng)的shell腳本學(xué)習(xí)指南之shell腳本入門免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)技術(shù)的是嵌入式和物聯(lián)網(wǎng)的shell腳本學(xué)習(xí)指南之shell腳本入門免費(fèi)下載。
    發(fā)表于 09-11 17:15 ?20次下載
    <b class='flag-5'>嵌入式</b>和物聯(lián)網(wǎng)的<b class='flag-5'>shell</b>腳本學(xué)習(xí)指南之<b class='flag-5'>shell</b>腳本入門免費(fèi)下載

    嵌入式linux對(duì)shell腳本的基本掌握

    對(duì)于嵌入式linux開(kāi)發(fā)者而言,shell腳本的要求基本上能看懂就可以。不用像運(yùn)維人員那樣寫(xiě)出非常強(qiáng)悍的shell腳本shell:在計(jì)算機(jī)科學(xué)中,
    發(fā)表于 04-02 14:46 ?495次閱讀

    嵌入式Linux開(kāi)發(fā)工具——shell編程

    shell(腳本:批處理)適合職業(yè):Linux系統(tǒng)運(yùn)維工程師1.命令解析器(將用戶輸入的命令解析,調(diào)用相應(yīng)的命令的可執(zhí)行文件)2.腳本語(yǔ)言我們需要了解的是shell編程的簡(jiǎn)單命令語(yǔ)句個(gè)
    發(fā)表于 11-01 17:20 ?13次下載
    <b class='flag-5'>嵌入式</b>Linux開(kāi)發(fā)工具——<b class='flag-5'>shell</b>編程

    【RT-Thread學(xué)習(xí)筆記】bash和dash-shell

    ? 最近在工作中遇到個(gè)很奇葩的問(wèn)題,就是個(gè)嵌入式的SDK編譯,它里面執(zhí)行shell命令的時(shí)候
    的頭像 發(fā)表于 07-30 13:49 ?1198次閱讀
    【RT-Thread學(xué)習(xí)筆記】bash和dash-<b class='flag-5'>shell</b>

    AN023 如何在GD平臺(tái)移植Letter shell

    AN023 如何在GD平臺(tái)移植Letter shell
    發(fā)表于 02-27 18:25 ?1次下載
    AN023 如何在GD平臺(tái)移植<b class='flag-5'>Letter</b> <b class='flag-5'>shell</b>

    剖析Linux shell 函數(shù)實(shí)現(xiàn)

    作為個(gè)嵌入式 Linux 工程師,肯定需要編寫(xiě) shell 腳本進(jìn)行些自動(dòng)化工作。剛好,我最近就有類似需求——
    的頭像 發(fā)表于 05-12 10:27 ?501次閱讀
    剖析Linux <b class='flag-5'>shell</b> 函數(shù)實(shí)現(xiàn)

    常見(jiàn)的shell script規(guī)則

    shell script對(duì)于硬件嵌入式行業(yè)從業(yè)者來(lái)說(shuō)應(yīng)該是個(gè)常用的工具,它是程序化腳本,是種自動(dòng)化管理linux的好工具了,所以對(duì)于
    的頭像 發(fā)表于 11-07 10:29 ?504次閱讀
    常見(jiàn)的<b class='flag-5'>一</b>些<b class='flag-5'>shell</b> script規(guī)則
    RM新时代网站-首页