zoukankan      html  css  js  c++  java
  • (转)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;
    }

     

     

  • 相关阅读:
    java 日志体系
    java mail 接收邮件
    Spring 事物Transaction
    Spring 文件上传MultipartFile 执行流程分析
    centos7安装Elasticsearch7
    centos7安装docker笔记
    docker安装
    redis
    springboot+redis+nginx+分布式session
    tomcat程序和webapp分离
  • 原文地址:https://www.cnblogs.com/lihaiping/p/ubootcmd.html
Copyright © 2011-2022 走看看