(转)uboot命令增加过程

原文出处:http://blog.sina.com.cn/s/blog_54f82cc2010125um.html

uboot命令添加过程

    U-Boot的命令为用户提供了交互功能,并且已经实现了几十个常用的命令。如果开发板需要很特殊的操作,可以添加新的U-Boot命令。
    U-Boot的每一个命令都是通过U_Boot_CMD宏定义的。这个宏在<include/command.h>头文件中定义

#ifdef CFG_LONGHELP

#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}

#else    


#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}

#endif    



    每一个命令定义一个cmd_tbl_t结构体,cmd_tbl_t只不过是cmd_tbl_s的一个typedef,如下所示:

typedef struct cmd_tbl_s cmd_tbl_t;


    而cmd_tbl_s的定义则在同一文件<command.h>,如下所示:

struct cmd_tbl_s {
    char       *name;        
    int        maxargs;      
    int        repeatable;    
                    
    int        (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
    char       *usage;        
#ifdef    CFG_LONGHELP
    char       *help;        
#endif
#ifdef CONFIG_AUTO_COMPLETE
    
    int        (*complete)(int argc, char *argv[], char last_char,                            int maxv,char *cmdv[]);
#endif
};

  
    这样每一个U-Boot命令有一个结构体来描述。结构体包含的成员变量:命令名称、最大参数个数、重复数、命令执行函数、用法、帮助。
    从控制台输入的命令是由common/command.c中的程序解释执行的。find_cmd()负责匹配输入的命令,从列表中找出对应的命令结构体并返回指向这一结构体的指针。
   基于U-Boot命令的基本框架,来分析一下简单的ping操作命令,就可以知道添加新命令的方法。
  
  (1)定义PING命令
   在<config_cmd_all.h><config_cmd_default.h>中定义了所有UBOOT支持的命令的标志位

#define CONFIG_CMD_PING

  其中,<config_cmd_default.h>中定义的命令是由板子默认支持的,这是由于在板子的配置文件中包含进了该头文件,如果让板子支持<config_cmd_default.h>中没有而<config_cmd_all.h>中命令,还必须在板子的配置文件中进行相关的定义,如我的<config_cmd_default.h>并没有进行PING的相关定义,我要想板子支持ping,我只需要在我的板子配置文件<mypxa255.h>中加入上面那句就可。也可以直接把定义语句写在<config_cmd_default.h>中。
   (2)定义PING命令的操作函数。下面是ping命令的具体实现,在<common/cmd_net.c>中。

#if defined(CONFIG_CMD_PING)
int do_ping (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
    if (argc < 2)
        return -1;

    NetPingIP = string_to_ip(argv[1]);
    if (NetPingIP == 0) {
        printf ("Usage:\n%s\n", cmdtp->usage);
        return -1;
    }

    if (NetLoop(PING) < 0) {
        printf("ping failed; host %s is not alive\n", argv[1]);
        return 1;
    }

    printf("host %s is alive\n", argv[1]);

    return 0;
}

U_BOOT_CMD(//通过宏定义命令

    ping,    2,    1,    do_ping,// 命令为ping,对应的执行函数为do_ping

    "ping\t- send ICMP ECHO_REQUEST to network host\n",
    "pingAddress\n"
);
#endif


    U-Boot的命令都是通过结构体__u_boot_cmd_##name来描述的。根据U_Boot_CMD<include/command.h>中的两行定义可以明白。

#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))

#ifdef CFG_LONGHELP

#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}

#else    

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}

#endif    


    按照这2步就可以添加U-BOOT命令了。

 

1、 u-boot的命令格式:

U_BOOT_CMD(name,maxargs,repeatable,command,”usage”,"help")

name:命令的名字,不是一个字符串;

maxargs:最大的参数个数;

repeatable:命令是可重复的;

command:对应的函数指针

 

U-Boot的每一个命令都是通过U_Boot_CMD宏定义的。这个宏在头文件中定义
#ifdef  CFG_LONGHELP
#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}
#else   
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}
#endif   
    每一个命令定义一个cmd_tbl_t结构体,而cmd_tbl_t只不过是cmd_tbl_s的一个typedef,如下所示:
                typedef struct cmd_tbl_s    cmd_tbl_t;

 

从控制台输入的命令是由common/command.c中的程序解释执行的。find_cmd()负责匹配输入的命令,从列表中找出对应的命令结构体。

基于U-Boot命令的基本框架,来分析一下简单的icache操作命令,就可以知道添加新命令的方法。

(1)定义CACHE命令。在include/cmd_confdefs.h中定义了所有U-Boot命令的标志位。

 

#define CFG_CMD_CACHE       0x00000010ULL  

 

如果有更多的命令,也要在这里添加定义。

(2)实现CACHE命令的操作函数。下面是common/cmd_cache.c文件中icache命令部分的代码。

 

#if (CONFIG_COMMANDS & CFG_CMD_CACHE)

static int on_off (const char *s)

{       //这个函数解析参数,判断是打开cache,还是关闭cache

        if (strcmp(s, "on") == 0) {  //参数为“on”

               return (1);

        } else if (strcmp(s, "off") == 0) {  //参数为“off”

               return (0);

    }

    return (-1);

}

 

int do_icache ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])

{     //对指令cache的操作函数

      switch (argc) {

      case 2:              

             switch (on_off(argv[1])) {

             case 0:     icache_disable();        //打开指令cache

                   break;

             case 1:     icache_enable ();        //关闭指令cache

                   break;

             }

           

      case 1:            

            printf ("Instruction Cache is %s\n",

                    icache_status() ? "ON" : "OFF");

            return 0;

      default:  //其他缺省情况下,打印命令使用说明

            printf ("Usage:\n%s\n", cmdtp->usage);

            return 1;

      }

      return 0;

}

……

U_Boot_CMD( //通过宏定义命令

    icache,   2,   1,     do_icache,  //命令为icache,命令执行函数为do_icache()

    "icache  - enable or disable instruction cache\n",   //帮助信息

    "[on, off]\n"

    "    - enable or disable instruction cache\n"

);

……

#endif

 

U-Boot的命令都是通过结构体__U_Boot_cmd_##name来描述的。根据U_Boot_CMD在include/command.h中的两行定义可以明白。

 

#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}

 

还有,不要忘了在common/Makefile中添加编译的目标文件。

(3)打开CONFIG_COMMANDS选项的命令标志位。这个程序文件开头有#if语句需要预处理是否包含这个命令函数。CONFIG_COMMANDS选项在开发板的配置文件中定义。例如:SMDK2410平台在include/configs/smdk2410.h中有如下定义。

 

#define CONFIG_COMMANDS \

                 (CONFIG_CMD_DFL  | \

                 CFG_CMD_CACHE     | \

                 CFG_CMD_REGINFO    | \

                 CFG_CMD_DATE      | \

                 CFG_CMD_ELF)

 

按照这3步,就可以添加新的U-Boot命令。

 

下面以添加 "Hello Word!" 命令为例!

(1)
在include/configs/qljt2440.h中增加一项:

#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
#define CONFIG_CMD_PING
#define CONFIG_CMD_NAND    //ql18
#define CONFIG_CMD_REGINFO   //ql18
#define  CONFIG_CMD_HELLOWORD

(2)
在 /board/qljt/qljt2440/ 目录下添加 helloword.c 文件
内容如下


#include
#include

#ifdef CONFIG_CMD_HELLOWORD
void helloword(void)
{
 qljt_printf("-----------------------------------------------Hello Word!\n");
}
U_BOOT_CMD(
 hello,
 1,
 2,
       helloword,
       "hell  - helloword command ",
       " QL add u-boot command!\n"
);

#endif
(3) 在/board/qljt/qljt2440/ 目录下的Makefile 添加要编译的目标文件,即在 Makefile的变量COBJS中加入:cmd_test_zwx.o

重新编译u-boot,完毕!

修改网卡控制字在文件dm9000x.c里,发送自定义包可以在/common/cmd_net.c文件里添加命令。

零值广播

static void start_ip_zerobro (void)
{
    int i = 0;
    uchar udp[14+20+8+306] = {
        0x23,0x45,0x3f,0x56,0xe3,0x2d,
        0x32,0x34,0xde,0x2d,0x4c,0x27,
        0x08,0x00,

       
        0x45,0x00,0x01,0x4e,
        0xc1,0x3e,0x00,0x00,
        0x40,0x11,0xf6,0x36,
        0xc0,0xa8,0x01,0x82,
        0x00,0x00,0x00,0x00,

       
        0x0f,0x10,0x00,0x50,
        0x01,0x3a,0x2d,0x3b

       
    };

    while (i++<10)
    {
        eth_send((volatile void*)udp,sizeof(udp));
        printf("send ip zerobro package ok\n");
        sleep("1");
    }
}

static int sleep (char *string)
{
    ulong start = get_timer(0);
    ulong delay;

    delay = simple_strtoul(string, NULL, 10) * CONFIG_SYS_HZ;

    while (get_timer(start) < delay) {
        if (ctrlc ()) {
            return (-1);
        }
        udelay (100);
    }
    return 0;
}

 

 

posted @ 2013-05-02 18:03  lihaiping  阅读(562)  评论(0编辑  收藏  举报