在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            博客專欄

            EEPW首頁(yè) > 博客 > 萬(wàn)字干貨:?jiǎn)纹瑱C(jī)實(shí)現(xiàn)Shell控制臺(tái)保姆級(jí)教程

            萬(wàn)字干貨:?jiǎn)纹瑱C(jī)實(shí)現(xiàn)Shell控制臺(tái)保姆級(jí)教程

            發(fā)布人:xiaomaidashu 時(shí)間:2023-11-10 來(lái)源:工程師 發(fā)布文章
            萬(wàn)字干貨:?jiǎn)纹瑱C(jī)實(shí)現(xiàn)Shell控制臺(tái)保姆級(jí)教程
            小麥大叔 2023-11-08 12:34 發(fā)表于浙江


            1前言

            玩過(guò)Linux的朋友, 是不是對(duì)Linux無(wú)所不能的串口Shell命令控制臺(tái)羨慕不已, 要是自己做的STM32F系列低檔次的MCU也有這種控制交互能力。

            會(huì)給調(diào)試/維護(hù)和配置省下多少麻煩事呀, 比如啟動(dòng)/關(guān)閉調(diào)試或自檢模式, 打印調(diào)試信息, 配置系統(tǒng)參數(shù), 傳輸文件等等, 也有相當(dāng)多的朋友憑借自己出色的編程能力可以實(shí)現(xiàn)這些功能, 這里提出我的這個(gè)解決方案, 以作交流.

            本平臺(tái)(xc_shell)具備以下性能特點(diǎn):

            1. 大量主要代碼, 和具體硬件無(wú)關(guān), 移植性強(qiáng),代碼文件少.

            2. 只有在處理用戶的輸入命令時(shí), 才占用CPU資源, 且代碼可裁剪到1KB SRAM和4KB Flash;

            3. 用戶可以非常靈活的添加按模板編寫(xiě)的命令腳本文件, 自定義擴(kuò)張能力強(qiáng).

            4. 支持操作系統(tǒng)和非操作系統(tǒng)兩種場(chǎng)景應(yīng)用.

            5. 支持Ymodem文件傳輸協(xié)議

            6. 支持將Flash的扇區(qū)開(kāi)辟為參數(shù)區(qū), 可實(shí)現(xiàn)本地/遠(yuǎn)程升級(jí)。

            7. 實(shí)用Led燈信號(hào)管理, 可將65535虛擬信號(hào)燈選擇輸出到1個(gè)實(shí)體LED燈上, 調(diào)試時(shí)序和狀態(tài)非常有用

            8. 擁有基礎(chǔ)的LED管理, 調(diào)試模式設(shè)置, 命令幫助指令, 復(fù)位指令等基礎(chǔ)功能

            功能越多設(shè)計(jì)會(huì)越復(fù)雜, 為了解釋清楚代碼, 先向大家解釋一下以上功能的基礎(chǔ)實(shí)現(xiàn)原理, 并提供一個(gè)最小的的源碼工程。


            2xc_shell平臺(tái)介紹2.1 如何與硬件無(wú)關(guān)

            類比Linux會(huì)發(fā)現(xiàn), 設(shè)備的硬件接口往往會(huì)被虛擬成一個(gè)文件(驅(qū)動(dòng)), 而Linux內(nèi)核完全與硬件系統(tǒng)無(wú)任何字節(jié)關(guān)聯(lián), 不同平臺(tái)驅(qū)動(dòng)不同而已, 故而本xc_shell的串口驅(qū)動(dòng)也采用了相似的思路:

            1) 串口驅(qū)動(dòng)用一個(gè)結(jié)構(gòu)體描述, 這樣只需在xc_shell.c中用指針指向這個(gè)TTYx_HANDLE結(jié)構(gòu)體對(duì)象就可以將串口(tty)硬件與內(nèi)核聯(lián)系在一起, 聰明的朋友可能會(huì)想到, 假如我將帶網(wǎng)絡(luò)的開(kāi)發(fā)板按此結(jié)構(gòu)體,虛擬一個(gè)TTY對(duì)象, 豈不是就可以實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)遠(yuǎn)程控制臺(tái)了!  這點(diǎn)確實(shí)是可以的!

            2) 當(dāng)然諸如多TTY串口實(shí)現(xiàn)接口互換等, 都是一個(gè)指針和step2中的注入回調(diào)處理交換的問(wèn)題。

            3)用戶在使用api_TxdFrame或api_TxdByte時(shí)”bsp_ttyX.c“,會(huì)驅(qū)動(dòng)具體MCU的串口將數(shù)據(jù)發(fā)送出去, 收到一幀數(shù)據(jù)后,若用戶設(shè)置了inj_RcvFrame回調(diào)處理方法,則會(huì)在中斷中執(zhí)行用戶的回調(diào)處理。

            /*---------------------* 
            *     指正函數(shù)定義
            *----------------------*/
            typedef void    (*pvFunDummy)(void);
             
            //輸入整行,輸出邏輯
            typedef void    (*pvFunVoid) (void);
            typedef void    (*pvFunBool) (bool     bVal);
            typedef void    (*pvFunChar) (uint8_t  cVal);
            typedef void    (*pvFunShort)(uint16_t sVal);
            typedef void    (*pvFunWord) (uint32_t wVal);
             
            //輸入整行,輸出邏輯
            typedef bool    (*pbFunVoid) (void);
            typedef bool    (*pbFunBool) (bool     bVal);
            typedef bool    (*pbFunChar) (uint8_t  cVal);
            typedef bool    (*pbFunShort)(uint16_t sVal);
            typedef bool    (*pbFunWord) (uint32_t wVal);
             
            //輸入整形指針,輸出邏輯
            typedef bool    (*pbFun_pVoid) (void * pVoid);
            typedef bool    (*pbFun_pChar) (uint8_t  * pStr);
            typedef bool    (*pbFun_pShort)(uint16_t * pShor);
            typedef bool    (*pbFun_pWord) (uint32_t * pWord);
             
            //輸入數(shù)據(jù)幀,輸出邏輯
            typedef bool    (*pbFun_Buffx)(void * pcBuff, uint16_t len );
            typedef bool    (*pbFun_Bytex)(uint8_t * pcByte, uint16_t len );
            /*---------------------* 
            *    TTYx 句柄結(jié)構(gòu)
            *----------------------*/
            typedef struct TTYx_HANDLE_STRUCT 
            {
                const char  * const name;       //驅(qū)動(dòng)器名
                const uint16_t      rxSize;     //接收大小
                const uint16_t      txSize;     //發(fā)送大小
                
                //------------------------------------------------------
                //step1: 用戶可用API
                const pvFunWord     init;           //初始化.
                const pbFun_Bytex   api_TxdFrame;   //發(fā)送數(shù)據(jù)幀. (發(fā)送幀)
                const pbFunChar     api_TxdByte;    //發(fā)送數(shù)據(jù)字節(jié)
                
                //------------------------------------------------------
                //step2: 注入回調(diào)函數(shù)
                pbFun_Bytex         inj_RcvFrame;   //(ISR)接收數(shù)據(jù)幀. (接收幀)
                pvFunDummy          inj_TxdReady;   //(ISR)發(fā)送完畢回調(diào)
                
                //------------------------------------------------------
                //step3: 接收回調(diào)函數(shù)
                struct TTYx_HANDLE_STRUCT * pvNext; //連接到下一個(gè)指令 
            }TTYx_HANDLE;
            1. 可注入的命令腳本(CLI)實(shí)現(xiàn)

            命令CLI也是一個(gè)結(jié)構(gòu)體對(duì)象:

            /*---------------------* 
            *       CLI指令
            *----------------------*/
            typedef struct
            {
             const char * const  pcCmdStr;     //指令字符串(只能為小寫(xiě)字母)
             const char * const  pcHelpStr;     //指令描述,必須以:"rn結(jié)束". 比如:"help: Returns a listrn".
             const pFunHook      pxCmdHook;     //指向回調(diào)函數(shù)的指針,處理成功返回真否者返回0;
             uint8_t             ucExpParam;     //指令期望的參數(shù)個(gè)數(shù)
             const MEDIA_HANDLE *phStorage;      //指向存儲(chǔ)介質(zhì),沒(méi)有的話填充NULL  
            }Cmd_Typedef_t;


            各位朋友可能會(huì)使用到非常多的自定義CLI命令, 格式諸如這個(gè)網(wǎng)卡的命令:

            const Cmd_Typedef_t CLI_WizMsg=
            {
                //識(shí)別關(guān)鍵字
                .pcCmdStr   = "wiz",
                //幫助內(nèi)容
                .pcHelpStr  =
                "[WIZ contorls]rn"
             " wiz helprn"
             " wiz rd inforn"
             " wiz resetrn"
             " wiz wr ip <D0>.<D1>.<D2>.<D3>rn"
             " wiz wr mask <D0>.<D1>.<D2>.<D3>rn"
             " wiz wr way <D0>.<D1>.<D2>.<D3>rn"
             " wiz wr mac <H0>-<H1>-<H2>-<H3>-<H4>-<H5>rn"
             " wiz wr port <udp> <bak> <vol> <pic>rn"
             " wiz wr sip <D0>.<D1>.<D2>.<D3> <port>rn"
             " wiz wr cip <D0>.<D1>.<D2>.<D3> <port>rn"
             " wiz load defaultrn"
             "[WIZ Test mode]rn"
             " wiz loop openrn"
             " wiz loop closern"
             "rn",
             
             //處理函數(shù)
             .pxCmdHook  = &Shell_WIZ_Service,        //見(jiàn)實(shí)體函數(shù)
             
             //附帶數(shù)據(jù)
             .ucExpParam = 0,
             
              #ifdef SHELL_USE_YMODEM  
                //存儲(chǔ)介質(zhì)
                .phStorage  = NULL,
              #endif
            };
            /*---------------------* 
            *       CLI 鏈表節(jié)
            *----------------------*/
            Cmd_List_t  WizList   = { &CLI_WizMsg,   NULL,}; //Shell指令的頭

            如配置IP地址輸入“wiz wr ip 192.168.1.25


            3環(huán)境準(zhǔn)備
            3.1 硬件開(kāi)發(fā)環(huán)境
            • STM32F103系列開(kāi)發(fā)板一塊, 帶USART1接口。
            • USB轉(zhuǎn)串口線一根。
            3.2 軟件開(kāi)發(fā)環(huán)境
            • MDK4.72或以上
            • SecureCRT串口超級(jí)終端
            3.3 軟件配置

            在xc_shell使用“/r/n”作為命令的結(jié)束符, 而SecureCRT按下Enter不是輸入“/r/n”故而需要按下圖設(shè)置:此外在《終端》/仿真/高級(jí)中選取【本地回顯】 


            4代碼介紹
            4.1 目錄結(jié)構(gòu)


            □ XC_SHELL
            ├──┬── BSP_LIB    BSP庫(kù),硬件相關(guān)驅(qū)動(dòng)代買
            │  ├──── bsp_ledx.c   基礎(chǔ)LED驅(qū)動(dòng)      
            │  └──── bsp_tty0.c   調(diào)試串口驅(qū)動(dòng)
            │
            ├──┬──MDK-ARM     工程文件
            │  └──── Project.uvproj
            │
            ├──┬──SHELL_CFG   SHELL配置頭文件
            │  └──── user_eval.h
            │
            ├──┬──SHELL_CORE  SHELL內(nèi)核文件
            │  ├──── xc_shell.c   SHELL內(nèi)核文件
            │  ├──── xc_ymodem.c  Ymodem傳輸協(xié)議(默認(rèn)關(guān)閉,在xc_shell.h中啟動(dòng))
            │  ├──── xc_iap.c     Flash的IAP操作,需要bsp_flash.c驅(qū)動(dòng)支持
            │  └──── shell_iap.c  shell的用戶腳本模板
            │
            ├──┬──SHELL_INC   SHELL頭文件
            │  ├──── bsp_type.h   驅(qū)動(dòng)結(jié)構(gòu)定義
            │  ├──── xc_shell.h   SHELL頭文件
            │  └──── xconfig.h    硬件無(wú)關(guān)配置文件
            │
            ├──┬──STM32F10x_StdPeriph_Lib_V3.5.0  STM32的標(biāo)準(zhǔn)外設(shè)庫(kù)
            │  └──── ......
            │
            └──┬──USER        用戶文件    
               ├─ .....       
               └──── main.c        main文件
            4.2 工程設(shè)置要點(diǎn)

            1) 設(shè)置使用微庫(kù):

            圖片

            2)配置包含和路徑,注意使用了“--c99”標(biāo)準(zhǔn),如圖

            圖片

            3) 編譯工程,無(wú)錯(cuò)誤警告后燒寫(xiě)程序到開(kāi)發(fā)板運(yùn)行。

            4.3 最終效果

            按圖輸入一下指令,SHELL平臺(tái)會(huì)回復(fù)相關(guān)信息。其中輸入“l(fā)ed set 0=1”會(huì)將信號(hào)1分配到物理LED0上;輸入“l(fā)ed set 0=2”會(huì)將信號(hào)2分配到物理LED0上。這樣用戶編寫(xiě)程序代碼時(shí)相當(dāng)于擁有了超級(jí)多的LED信號(hào)可用,調(diào)試時(shí)序非常有用。 

            圖片


            5添加自己的腳本
            5.1 源代碼示例

            假設(shè)我要編寫(xiě)一個(gè)自己的指令腳本, 來(lái)讀取MCU的關(guān)鍵信息,關(guān)鍵字為mcu, 文件命名為shell_mcu.c;當(dāng)輸入“mcu rd 0”時(shí)顯示MCU的FLASH大小,輸入“mcu rd 1”時(shí)讀取MCU的唯一ID信息。shell_mcu.c源代碼:

            /*********************************Copyright (c)*********************************
            **                               
            **                                 FIVE工作組
            **
            **---------------------------------File Info------------------------------------
            ** File Name:               shell_mcu.c
            ** Last modified Date:      2017/9/17 15:13:57
            ** Last Version:            V1.0
            ** Description:             shell測(cè)試
            **
            **------------------------------------------------------------------------------
            ** Created By:              wanxuncpx
            ** Created date:            2017/9/17 15:14:08
            ** Version:                 V1.0
            ** Descriptions:            none
            **------------------------------------------------------------------------------
            ** HW_CMU:                  STM32F103
            ** Libraries:               STM32F10x_StdPeriph_Lib_V3.5.0
            ** version                  V3.5
            *******************************************************************************/
             
            /******************************************************************************
            更新說(shuō)明:
            ******************************************************************************/
             
            /******************************************************************************
            *********************************  編 譯 控 制 ********************************
            ******************************************************************************/
            #define MCU_SHELL               //注釋掉時(shí)屏蔽iap shell功能
             
            #include "xc_shell.h"       //Shell支持文件,含bool,uint8_t..以及串口數(shù)據(jù)收發(fā)操作
            /******************************************************************************
            ********************************* 文件引用部分 ********************************
            ******************************************************************************/
            /*---------------------* 
            *     模塊驅(qū)動(dòng)引用
            *----------------------*/
            //#include "net_w5500.h"
             
            #ifdef MCU_SHELL
            /******************************************************************************
            ********************************** Shell實(shí)例 **********************************
            ******************************************************************************/
            /*---------------------* 
            *      CLI指令服務(wù)
            *----------------------*/
            extern bool Shell_MCU_Service(void * pcBuff, uint16_t len );
             
            /*---------------------* 
            *       CLI 結(jié)構(gòu)
            *----------------------*/
            const Cmd_Typedef_t CLI_McuMsg=
            {
                //識(shí)別關(guān)鍵字
                "mcu",
                
                //幫助內(nèi)容
             "[mcu contorls]rn"
             " mcu rd <d>tt- Read FLASH information.rn"
             "rn",
             
             //處理函數(shù)
             &Shell_MCU_Service,
             
             //附帶數(shù)據(jù)
             0,
              #ifdef SHELL_USE_YMODEM  
                //存儲(chǔ)介質(zhì)
                NULL,
              #endif
            };
             
            /*---------------------* 
            *     CLI鏈表節(jié)(輸出)
            *----------------------*/
            Cmd_List_t  McuList  = {&CLI_McuMsg      ,NULL}; //IAP指令鏈表
             
            /******************************************************************************
            ********************************* 函 數(shù) 聲 明 *********************************
            ******************************************************************************/
            /******************************************************************************
            / 函數(shù)功能:STM32F103控制函數(shù)
            / 修改日期:2015/7/14 20:22:02
            / 輸入?yún)?shù):none
            / 輸出參數(shù):none
            / 使用說(shuō)明:需要執(zhí)行約10s
            ******************************************************************************/
            static bool FLASH_ioctl(uint8_t cmd,void * param)
            {
                #define UID_ADDR            0x1FFFF7E0  //閃存容量寄存器,值對(duì)應(yīng)KB單位
                #define MAC_ADDR            0x1FFFF7E8  //MCU的唯一ID號(hào),共12個(gè)字節(jié)
                #define UID_SIZE            2           //UID的字節(jié)數(shù)
                #define MAC_SIZE            12          //MAC的字節(jié)數(shù)
             
                //step1: 檢查參數(shù)
                if(!param)return false;
                    
                //step2: 處理數(shù)據(jù)
                switch(cmd){
                  case 0 : {       //獲取FLASH的的UID
                    uint16_t * ptDst = (uint16_t *)((uint32_t)param+1);
                    
                    *ptDst = *(uint16_t *)UID_ADDR;
                    *(uint8_t  *)param =  UID_SIZE;
                    return true;
                  }
                  case 1 : {       //獲取芯片的MAC地址
                    uint32_t * ptDst = (uint32_t *)((uint32_t)param+1);
                    uint32_t * ptSrc = (uint32_t *)MAC_ADDR;
                
                    *ptDst++ = *ptSrc++;
                    *ptDst++ = *ptSrc++;
                    *ptDst++ = *ptSrc++;
                    *(uint8_t  *)param = MAC_SIZE;
                    return true;
                  }
                  default:return false;
                }
            }
             
            /******************************************************************************
            / 函數(shù)功能:文件系統(tǒng)Shel指令處理
            / 修改日期:2013/9/10 19:04:15
            / 輸入?yún)?shù):輸入當(dāng)前的程序版本
            / 輸出參數(shù):none
            / 使用說(shuō)明:none
            ******************************************************************************/
            bool Shell_MCU_Service(void * pcBuff, uint16_t len )
            {
                uint8_t    *ptRxd;          //用于接收指令處理
                int         i;
                uint16_t    retval;
                uint8_t     buff[32];
                
                //處理指令
                //--------------------------------------------------------------------------
                ptRxd = (uint8_t *)pcBuff;
                
                if(StrComp(ptRxd,"rd ")) //讀取FLASH信息
                {
                    int wval;
                    
                    if(1 != sscanf((void *)ptRxd,"%*s%d",&wval) )return false;
                    if( wval>2 )return false;
                    if(0==wval) {
                        FLASH_ioctl(0,buff);
                        retval = *(uint16_t *)(buff+1) ;
                        printf("->Flash:t%dKBrn",retval);
                        return true;
                    }
                    else if(1==wval) {
                        FLASH_ioctl(1,buff);
                        printf("->MAC:t ");
                        for(i=0; i<buff[0]-1; i++){printf("%02X-",buff[i+1]);}
                        printf("%02Xrn",buff[i+1]);
                        return true;
                    }
                    else return false;
                }
                else if(StrComp(ptRxd,"helprn"))      //指令幫助
                {
                    shell_SendStr((void *)CLI_McuMsg.pcHelpStr);
                    return true;
                }
                else return false;
            }
             
            /******************************************************************************
            ***********************************   END  ************************************
            ******************************************************************************/
            #endif
            5.2 實(shí)現(xiàn)步驟

            1) 將該文件添加到工程下。

            2) 在main.c中用extern 引用McuList,源代碼為:

            /*---------------------* 
            *     Shell指令鏈表
            *----------------------*/
            extern Cmd_List_t  McuList;

            3)在main.c初始化時(shí)添加:

            //----------------------------------------------------------
            //step1: shell初始化
            shell_Init(115200,ledx_cfg);        //初始化shell接口
            CLI_AddCmd(&McuList);     //添加模塊指令到鏈表

            4)編譯工程文件。

            5)下載到開(kāi)發(fā)板運(yùn)行即可在終端下看到新支持的CLI指令:

            圖片

            來(lái)源:https://dablelv.blog.csdn.net/article

            *博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。



            關(guān)鍵詞: 單片機(jī) Shell

            相關(guān)推薦

            技術(shù)專區(qū)

            關(guān)閉