uboot源码——命令体系
以下內容源于朱有鵬嵌入式課程的學習,如有侵權,請告知刪除。
參考資料:http://www.cnblogs.com/biaohc/p/6394710.html
一、uboot命令體系基礎
1、使用uboot命令
- uboot啟動后進入命令行環境,在此輸入命令按回車結束,uboot會接收此命令,然后解析、執行。
2、uboot命令體系實現代碼在哪里?
- 實現代碼在uboot/common/cmd_xxx.c中。
- command.c、main.c也和命令有關。
3、每個uboot命令對應一個函數
- 這是uboot實現命令體系的一種思路和方法。
4、argc&argv傳給對應的函數,作為命令參數
(1)有些uboot的命令支持傳遞參數
- 命令對應的函數接收的參數列表中一般有argc和argv;
- 命令體系會把執行命令時的命令+參數(比如 md 30000000 10),以argc(這里為3)和argv(這里argv[0]=md,argv[1]=30000000,argv[2]=10)的方式傳遞給執行命令的函數。
- help命令背后對應的函數名叫:do_help,在uboot/common/command.c的236行。
- int do_help (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
二、uboot命令解析和執行過程分析
1、uboot啟動的第二階段即start_armboot()函數,最后進入一個死循環,循環體就是main_loop。
2、main_loop函數執行一遍,就是一個獲取命令、解析命令、執行命令的過程。
(1)readline函數作用
- 輸出x210 #;
- 內部調用cread_line函數,此函數從securecrt中命令行中讀取命令,并進行初步的處理;
- ichar = getcmd_getch();這個函數是從串口中讀取信息;如果讀取到'\n'或者'\r'的話表示輸入完成;
- 之后的代碼是處理鍵盤的特殊字符,詳細解釋見博客:http://blog.chinaunix.net/uid-30031530-id-5152127.html
(2)rc = run_command (lastcommand, flag)函數
- 此函數進一步處理lastcommand中的字符串;
- 調用process_macros函數,處理字符串中的轉義字符;
- 調用parse_line函數,統計argc、賦值argv;
- 調用find_cmd命令查找相應命令返回命令的結構體指針;
- (cmdtp->cmd) (cmdtp, flag, argc, argv)以函數指針的方式來執行命令函數;
命令的結構體
run_command函數
命令解釋函數
- 如parse_line函數把"md 30000000 10"解析成argv[0]=md,argv[1]=30000000,argv[2]=10;
命令查找函數
- 本來可以把所有命令的結構體放在一個數組里或者一個鏈表里;
- 但是uboot中用了一個新的方法,就是定義了一個專門的段來存放所有的命令結構體,這個段的起始地址和結束地址都放在連接腳本里。見下圖:
- 詳細分析見博文http://blog.csdn.net/oqqhutu12345678/article/details/73251739
總結:uboot實現命令管理的思路
(1)填充1個結構體實例構成一個命令;
(2)給命令結構體實例附加特定段屬性(用戶自定義段),鏈接時將帶有該段屬性的內容鏈接在一起排列
- 命令結構體彼此緊挨著,不會夾雜其他東西,也不會遺漏帶有這種段屬性的實例,但它們是亂序的;
- 其實就是命令結構體的集合,有點像一個命令結構體數組。
(4)段起始地址和結束地址(定義在u-boot.lds中)決定了這些命令集的開始和結束地址。
附:
一、uboot中增加自定義命令
1、在已有的c文件中直接添加命令
(1)比如在uboot/common/command.c中添加一個命令,叫:mycmd。
(2)在已有的.c文件中添加命令比較簡單,直接使用U_BOOT_CMD宏即可添加命令,給命令提供一個do_xxx的對應的函數。
(3)添加完成后要重新編譯工程(make distclean; make x210_sd_config; make),然后燒錄新的uboot去運行即可體驗新命令。
(4)還可以在函數中使用argc和argv來驗證傳參。
2、自建一個c文件并添加命令
(1)在uboot/common目錄下新建一個命令文件,叫cmd_xjh.c(對應的命令名就叫xjh,對應的函數就叫do_xjh函數),然后在c文件中使用U_BOOT_CMD宏,定義命令對應的函數。注意頭文件包含不要漏掉。
(2)在uboot/common/Makefile中添加上xjh.o,目的是讓Make在編譯時把cmd_xjh.c編譯鏈接進去。
(3)重新編譯燒錄。重新編譯步驟是:make distclean; make x210_sd_config; make
二、creat_line函數
static int cread_line(const char *const prompt, char *buf, unsigned int *len) {unsigned long num = 0;unsigned long eol_num = 0;unsigned long rlen;unsigned long wlen;char ichar;int insert = 1;int esc_len = 0;int rc = 0;char esc_save[8];while (1) {rlen = 1; #ifdef CONFIG_BOOT_RETRY_TIMEwhile (!tstc()) { /* while no incoming data */if (retry_time >= 0 && get_ticks() > endtime)return (-2); /* timed out */} #endifichar = getcmd_getch();if ((ichar == '\n') || (ichar == '\r')) {putc('\n');break;}/** handle standard linux xterm esc sequences for arrow key, etc.*/if (esc_len != 0) {if (esc_len == 1) {if (ichar == '[') {esc_save[esc_len] = ichar;esc_len = 2;} else {cread_add_str(esc_save, esc_len, insert,&num, &eol_num, buf, *len);esc_len = 0;}continue;}switch (ichar) {case 'D': /* <- key */ichar = CTL_CH('b');esc_len = 0;break;case 'C': /* -> key */ichar = CTL_CH('f');esc_len = 0;break; /* pass off to ^F handler */case 'H': /* Home key */ichar = CTL_CH('a');esc_len = 0;break; /* pass off to ^A handler */case 'A': /* up arrow */ichar = CTL_CH('p');esc_len = 0;break; /* pass off to ^P handler */case 'B': /* down arrow */ichar = CTL_CH('n');esc_len = 0;break; /* pass off to ^N handler */default:esc_save[esc_len++] = ichar;cread_add_str(esc_save, esc_len, insert,&num, &eol_num, buf, *len);esc_len = 0;continue;}}switch (ichar) {case 0x1b:if (esc_len == 0) {esc_save[esc_len] = ichar;esc_len = 1;} else {puts("impossible condition #876\n");esc_len = 0;}break;case CTL_CH('a'):BEGINNING_OF_LINE();break;case CTL_CH('c'): /* ^C - break */*buf = '\0'; /* discard input */return (-1);case CTL_CH('f'):if (num < eol_num) {getcmd_putch(buf[num]);num++;}break;case CTL_CH('b'):if (num) {getcmd_putch(CTL_BACKSPACE);num--;}break;case CTL_CH('d'):if (num < eol_num) {wlen = eol_num - num - 1;if (wlen) {memmove(&buf[num], &buf[num+1], wlen);putnstr(buf + num, wlen);}getcmd_putch(' ');do {getcmd_putch(CTL_BACKSPACE);} while (wlen--);eol_num--;}break;case CTL_CH('k'):ERASE_TO_EOL();break;case CTL_CH('e'):REFRESH_TO_EOL();break;case CTL_CH('o'):insert = !insert;break;case CTL_CH('x'):case CTL_CH('u'):BEGINNING_OF_LINE();ERASE_TO_EOL();break;case DEL:case DEL7:case 8:if (num) {wlen = eol_num - num;num--;memmove(&buf[num], &buf[num+1], wlen);getcmd_putch(CTL_BACKSPACE);putnstr(buf + num, wlen);getcmd_putch(' ');do {getcmd_putch(CTL_BACKSPACE);} while (wlen--);eol_num--;}break;case CTL_CH('p'):case CTL_CH('n'):{char * hline;esc_len = 0;if (ichar == CTL_CH('p'))hline = hist_prev();elsehline = hist_next();if (!hline) {getcmd_cbeep();continue;}/* nuke the current line *//* first, go home */BEGINNING_OF_LINE();/* erase to end of line */ERASE_TO_EOL();/* copy new line into place and display */strcpy(buf, hline);eol_num = strlen(buf);REFRESH_TO_EOL();continue;} #ifdef CONFIG_AUTO_COMPLETEcase '\t': {int num2, col;/* do not autocomplete when in the middle */if (num < eol_num) {getcmd_cbeep();break;}buf[num] = '\0';col = strlen(prompt) + eol_num;num2 = num;if (cmd_auto_complete(prompt, buf, &num2, &col)) {col = num2 - num;num += col;eol_num += col;}break;} #endifdefault:cread_add_char(ichar, insert, &num, &eol_num, buf, *len);break;}}*len = eol_num;buf[eol_num] = '\0'; /* lose the newline */if (buf[0] && buf[0] != CREAD_HIST_CHAR)cread_add_to_hist(buf);hist_cur = hist_add_idx;return (rc); }總結
以上是生活随笔為你收集整理的uboot源码——命令体系的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: s5pv210——串口通信的基础概念
- 下一篇: linux获取weblogic版本,LI