您好,登錄后才能下訂單哦!
8、1、uboot的命令體系
1、使用uboot命令
2、uboot實現(xiàn)命令體系的代碼uboot/commond/cmd_xxx.c中,有若干個.c文件和命令體系有關(guān)。還有個main.c也是跟命令體系有關(guān)的。
3、每個命令對應(yīng)一個函數(shù)
(1)uboot中的每一個命令都對應(yīng)了一個函數(shù)在背后,這就是uboot來實現(xiàn)命令體系的一種方法。和我們在裸機中寫的shell中實現(xiàn)的方法其實是一樣的。
(2)我們要找到每一個命令背后所對應(yīng)的那個函數(shù),而且要分析每一個函數(shù)和每一個命令是怎么對應(yīng)起來的。
4、命令的參數(shù)以argc&argv的方式來傳遞給函數(shù)
(1)有些uboot的命令還支持傳參,也就是說命令背后對應(yīng)的函數(shù)接受的參數(shù)列表中有argc和argv這兩個參數(shù)。然后命令體系會吧我們執(zhí)行命令時的命令加參數(shù),以argc和argv的方式傳遞給執(zhí)行命令的函數(shù)。
(2)run_command函數(shù)就是用來執(zhí)行命令的函數(shù)
8、2、uboot命令解析和執(zhí)行過程分析
1、從main_loop函數(shù)說起
(1)我們在uboot的第二階段,也就是start_armboot這個函數(shù)在初始化了一些板上的硬件后,最后進入到了死循環(huán),這個死循環(huán)不斷的執(zhí)行一個函數(shù)叫做main_loop,這個函數(shù)的其實就是在不斷獲取我們輸入到uboot命令行中的命令,解析這個命令,執(zhí)行這個命令。直到執(zhí)行了bootm 這個命令去啟動內(nèi)核。
8、3、run_command函數(shù)詳解
1、控制命令獲取
2、解析命令
(1)paser_line函數(shù)用來解析,如將(md 0x30001000 10)把argv[0] = "md" argv[1] = "0x30001000" argv[2] = "10"
3、命令集中查找命令
(1)find_cmd(argv[0])函數(shù)就是去命令集合找有沒有這個argv[0]中的那個命令。
4、執(zhí)行命令
(1)最后用函數(shù)指針的形式調(diào)用了這個命令所對應(yīng)的函數(shù)
總結(jié):在獲取命令和解析命令和執(zhí)行命令的過程中,最關(guān)鍵的部分就是find_cmd這個函數(shù)是如何通過我們輸入的命令找到這個在uboot命令體系中的命令的。同時,關(guān)鍵的還有,uboot是如何注冊一個命令的,存儲,管理,索引一個命令的,索引的過程就是find_cmd這個查找的過程。
8、4、uboot如何處理命令集1
1、可能的管理方式
(1)數(shù)組:比如可以用結(jié)構(gòu)體數(shù)組的方式,數(shù)組中的每一個元素都是一個結(jié)構(gòu)體,每一個結(jié)構(gòu)體表示一個命令的所有信息
(2)鏈表:比如也可以用鏈表,鏈表的每一個節(jié)點的data,就是一個命令的結(jié)構(gòu)體,這個結(jié)構(gòu)體中包含了命令的所有信息。壞處是內(nèi)存開銷變大了,因為需要存放頭指針和尾指針,并且代碼的復雜度變大了,程序運行的效率因此會有所降低,但是靈活性相當于數(shù)組來說,卻好了很多,因為數(shù)組的大小都是直接給定的,不靈活。
(3)有第三種嗎?uboot實際上沒有用前兩種的方式來實現(xiàn)這個命令體系。而是用了一種新的方式來實現(xiàn)了這個功能。
2、命令結(jié)構(gòu)體cmd_tpl_t
struct cmd_tbl_s {
char *name; /* Command Name */
int maxargs; /* maximum number of arguments */
int repeatable; /* autorepeat allowed? 1:OK 0:NO *///命令輸完后回車一遍后,在回車可以繼續(xù)上一次的命令
/* Implementation function */
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char *usage; /* Usage message (short) *///簡單說明
#ifdef CFG_LONGHELP
char *help; /* Help message (long) *///詳細說明
#endif
#ifdef CONFIG_AUTO_COMPLETE
/* do auto completion on the arguments */
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};
typedef struct cmd_tbl_s cmd_tbl_t;
(1)name:命令的名稱,字符串格式的
(2)maxargs:命令所能接收的參數(shù)的最大個數(shù)
(3)repeatable:命令是否能夠重復執(zhí)行,就是直接按回車能否執(zhí)行上一次輸入的命令
(4)cmd:函數(shù)指針,命令所對應(yīng)的那個函數(shù)的函數(shù)指針。
(5)usage:使用信息,簡單的使用信息說明
(6)help:使用信息,詳細的使用信息說明
(7)complete:函數(shù)指針,指向這個命令的自動補全函數(shù)
總結(jié):uboot的命令體系在工作的時候,一個命令對應(yīng)一個這個cmd_tbl_t結(jié)構(gòu)體的實例(實例化),uboot需要多少個命令就需要多少個cmd_tbl_t這個結(jié)構(gòu)體的實例。uboot的命令體系把這些結(jié)構(gòu)體實例管理起來,當用戶輸入一個命令的時候,uboot會去這些結(jié)構(gòu)體實例中查找(查找方法和管理方法有關(guān))。如果找到則執(zhí)行這個實例當中的cmd函數(shù)指針去執(zhí)行命令。如果沒有找到則提示命令未知。
3、uboot實現(xiàn)命令管理的思路
(1)填充一個結(jié)構(gòu)體實例構(gòu)成一個命令
(2)給命令結(jié)構(gòu)體附加一個特定的段屬性(用戶自定義段),鏈接時鏈接器就會將有該段屬性的內(nèi)容鏈接在一起排列(挨著的,不會夾雜著其他東西,也不會丟掉任何一個帶有這種段屬性的,但是順序是亂序的)。(鏈接完成后,最后都會在u-boot.bin這個鏡像中)。
(3)uboot在重定位的時候,將該段屬性整片加載到DDR中。(其實分析開來,加載到DDR中的uboot鏡像的帶有特定段屬性的這一段是一個命令結(jié)構(gòu)體的集合,有點像一個結(jié)構(gòu)體數(shù)組,不一樣的是,我們在寫完這些結(jié)構(gòu)體實例后,寫了多少個結(jié)構(gòu)體實例,鏈接器就會鏈接多少個,最后形成鏡像后,我們直接重定位到DDR中,這樣就彌補了數(shù)組的不靈活性)
(4)段起始地址和結(jié)束地址(鏈接地址,定義在u-boot.lds中)決定了這些命令的開始和結(jié)束地址。
8、5、uboot如何處理命令集2
1、1、uboot命令定義具體實現(xiàn)分析
1、1、1、U_BOOT_CMD宏基本分析
1、這個宏在uboot/common/commond.h中的93行到99行定義
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
(1)這個宏接接收六個參數(shù)。宏體cmd_tbl_t是命令的結(jié)構(gòu)體類型,用這個類型定義了一個變量叫__u_boot_cmd_##name
其中##name,是gcc支持的,##name將來會被宏傳遞進去的name這個參數(shù)替代,也就是##name就是name這個參數(shù)。
(2)Struct_Section 是由這個宏定義的
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
(2(1))_attribute__ ((unused,section (".u_boot_cmd")))是gcc中的一種擴展語法,給賦予屬性,目的就是給前面的變量賦予一個段屬性(.u_boot_cmd)就是把##name這個變量放在了這個.u_boot_cmd這個段上。
(3) = {#name, maxargs, rep, cmd, usage, help} 就是將這個被放在用戶自定義段(.u_boot_cmd)的結(jié)構(gòu)體變量##name進行初始化,值就是宏傳參過來的六個參數(shù)。
其中的參數(shù)有一個#name,這個參數(shù)前面有個#號的意思就是,將傳進來的東西轉(zhuǎn)換成字符串,因為結(jié)構(gòu)體成員的第一個是一個字符串。
(4)鏈接腳本:鏈接腳本中,有這個段的起始地址和結(jié)束地址。在u-boot.lds中
總結(jié):這個宏的最終實現(xiàn)的就是填充一個命令,并且將這個命令附加了一個段屬性。將來屬于這同一屬性的東西,鏈接器在鏈接的時候,就會鏈接在一起進行排列。
1、1、2、find_cmd函數(shù)詳解
(1)find_cmd函數(shù)的任務(wù)就是從uboot的命令集中,查找是否有這個命令。如果找到,就返回這個命令結(jié)構(gòu)體的指針,如果沒找到,返回NULL。
(2)函數(shù)中的,__u_boot_cmd_start,是在commond.h中聲明的,是在u-boot.lds中定義的。
cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start;
意思就是將命令集在DDR中的鏈接處的首地址給cmdtp_temp指針,讓這個指針指向這個地址。
(3)這個函數(shù)實現(xiàn)查找命令的思路就是,使用了一個for循環(huán)的方式,知道命令集的鏈接時的首地址,命令集鏈接時的結(jié)束地址是這個for循環(huán)的終止條件,這個命令結(jié)構(gòu)體++,來查詢這一段命令集的所有命令,看哪一個名字和長度是相同的。,找到后返回這個命令的結(jié)構(gòu)體指針。
8、6、uboot中自定義命令
1、在已有的c文件中直接添加命令
(1)在uboot/common/command.c中添加
在已有的.c文件中添加命令比較簡單,直接使用U_BOOT_CMD宏添加就行,相應(yīng)的我們也要為我們添加的命令,添加一個對應(yīng)的命令所以執(zhí)行的函數(shù)do_xxx。
(2)添加完了要重新make distclean,和配置編譯工程,在燒錄u-boot.bin,運行就可以了查找這個命令了
(3)也可以用argc和argv來驗證函數(shù)的傳參,你也可以根據(jù)這些傳參做一些應(yīng)該做的事情
2、uboot中自建c文件添加一個命令
(1)在uboot/common目錄下新建一個.c文件,名字以cmd_為開頭,如果你的文件的名字叫做cmd_why.c,那么將來對應(yīng)的命令名就叫做why,對應(yīng)的函數(shù)就叫do_why函數(shù)(這是一種命名規(guī)范,別人添加命令的時候,是這樣的,所以我們也要按照這樣的方式去添加),然后在c文件中添加U_BOOT_CMD宏和對應(yīng)的函數(shù)。注意:頭文件要包含。
(2)還要在uboot/common中的makefile中添加這個.o文件,目的是就是讓我們寫的文件能夠在makefile中編譯,能鏈接進去
(3)重新make distclean , make x210_sd_config , make
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。