u-boot是嵌入式系統中廣泛使用的1種bootloader。
它不但支持眾多的平臺和參考板,而且支持豐富的命令,可讓用戶對開發板進行各種操作。
關于u-boot使用和移植的資料很多,下面用問答的方式介紹u-boot中命令的實現機制。
Q1: u-boot中命令的實現代碼在甚么地方?
A1: 在u-boot源碼的common目錄下。通常1個或多個命令在對應的某個C文件中實現。如果用戶要增加1個新命令的話,要在common目錄下添加對應的C文件,并在Makefile中指定編譯該文件。
Q2: 能不能給個命令的實現模板先?
A2: #include <common.h>
#include <command.h>
int do_hello(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
printf(“hello world
”);
return 0;
}
U_BOOT_CMD(hello, CONFIG_SYS_MAXARGS, 1, do_hello, “usage info”, “help info”);
以下是上面代碼的解釋:
U_BOOT_CMD是u-boot中定義的宏,上面的宏定義展開后以下:
cmd_tbl_t __u_boot_cmd_hello Struct_Section = {“hello”, CONFIG_SYS_MAXARGS, 1, do_hello, “usage info”, “help info”};
這下清楚了,實際上就是定義1個類型為cmd_tbl_t的結構體并對其賦值。
u-boot中每一個命令都用這樣的1個結構體來描寫,類型定義以下:
typedef struct cmd_tbl_s cmd_tbl_t;
struct cmd_tbl_s {
char *name; // 命令的名稱
int maxargs; // 最多支持的參數的個數
int repeatable; // 是不是可重復履行
int (*cmd)(struct cmd_tbl_s *, int, int, char *const[]); // 命令對應的處理函數
char *usage; // 命令扼要使用信息
char *help; // 命令詳細幫助信息
}
成員cmd是個函數指針,需要指向該命令對應的處理函數。這也是在前面的模板中先定義1個處理函數的緣由。所有命令的處理函數的接口都是1致的:參數cmdtp指向命令對應的cmt_tbl_t結構體;參數flag可以疏忽不處理;參數argc和參數argv的作用和它們在main函數中是1樣的。
Q3: 當用戶輸入命令后,u-boot是如何履行的?
A3: 前面用U_BOOT_CMD定義結構體時用到了另外1個宏Struct_Section,它表示把該結構體放到1個專門的段。u_boot_cmd,沒錯,u-boot中所有命令對應的結構體都集中放在這個段里,該段里的內容會被包括在編譯好的u-boot里。
這下就容易理解了:u-boot接收到用戶的命令后在.u_boot_cmd段中順次查找每一個cmd_tbl_t,根據成員name比較是不是和用戶命令匹配。若成功則履行第3個成員cmd指向的函數,否則查找下個cmd_tbl_t。具體的實現請參考u-boot中的函數find_cmd的代碼。
u-boot不但是1個功能強大的bootloader,而且是1個很好的嵌入式編程的學習對象,其中很多編程的思想和實現的方法都值得大家鑒戒與學習。
點擊打開鏈接
下一篇 IOS開發之NSURL