1:回归到main_loop

    uboot启动第二阶段的最后,进入死循环main_loop()函数,命令行中没输出一次命令,就会执行一次main_loop函数,完成一次命令的获取、解析和执行。


2:uboot命令体系的实现原理

    uboot中里面维护了很多命令,每个命令对应一个结构体变量,当我们在命令行输入一个命令时。这时就涉及如何去维护这些命令的问题,一般的方法有两种,数组或者链表,但是数组的缺陷在开始的时候需要确定数组的大小,链表的话效率比较低,所以uboot使用了另一种方式。uboot中一个命令对应一个__u_boot_cmd_命令结构,并且绑定了一个do_命令函数。

    uboot里面给命令添加了一个段属性,所以在链接的时候相同段属性的代码会连续的发到一起(命令的顺序是不定的),所以指定了段属性的起始地址和结束地址,那么我们就可以通过指针的方式去访问这些数据,这样实现方式在存储方面和数组类似,但是有避免数组大小一开始就需要确定的局限性。所以在添加和删除命令的时候很简单就可以实现。


3:结构体cmd_tbl_s,命令结构体

struct cmd_tbl_s {
    char        *name;        /* Command Name            */
    int        maxargs;    /* maximum number of arguments    */
    int        repeatable;    /* autorepeat allowed?        */
                    /* 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
};

参数解析:

name:命令的名字

maxargs:命令允许传入最多的参数个数

repeatable:命令是否允许连续执行(输入一次命令后,按下回车还会执行之前的命令)

cmd:命令对应的执行函数

usage:命令的短说明

help:命令的长说明


4:两个宏定义U_BOOT_CMD和Struct_Section

#define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))
#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}

Struct_Section宏的作用是添加段属性 .u_boot_cmd,段属性的起始地址在链接脚本中有指定。

U_BOOT_CMD宏的作用是实例化一个cmd_tbl_t类型的结构体__u_boot_cmd_##name,并且在实例化的时候同时初始化结构

##name:##是转义字符,效果是将##name用name替代

#name:#转义字符,效果是将name转成字符串类型的‘name’

5:添加uboot命令

    方法1:在原有的.c文件中加

uboot命令很多都保存在uboot/common/command.c文件中,所有要添加uboot命令只需要在command.c按照其他的命令的格式添加即可

    方法2:自己创建.c文件并添加命令

首先在uboot/common/中创建一个.c文件,然后添加U_BOOT_CMD宏和对应的命令函数,需要注意的是要添加相应的头文件,然后在uboot/common/Makefile下添加xxx.o,目的的编译的时候能将添加的.c文件编译链接进去。