u-boot分析 七 (添加u-boot命令,学习u-boot命令实现原理)

u-boot分析 七

(添加u-boot命令,学习u-boot命令实现原理)

本文目标:

理解u-boot命令的实现原理。

上一篇文章分析了u-boot是如何启动kernel的,其中就涉及到bootm命令,考虑到文章主题需要,当时并没有对bootm命令做过多的解释。然而,u-boot命令行又是u-boot及其重要的一部分。这篇文章,我们就通过实战来理解u-boot命令的实现原理。

我们要做的很简单,就是添加一条uboot command,希望在开发板上,uboot命令行中输入itxiebo时,能够从串口打印出一句log。

一、具体实现步骤:

  1. 在./common文件夹下新建cmd_itxiebo.c,并在此文件中添加如下内容
#include <common.h>
#include <command.h>

static int do_itxiebo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
    printf("do_itxiebo command is ready now!");
    return 0;
}

U_BOOT_CMD(
    itxiebo,    2,  0,  do_itxiebo,
    "itxiebo - this is a itxiebo command, do nothing",
    "- this is a itxiebo command, do nothing"
);

2.在./common/Makefile中添加:

obj-y += cmd_itxiebo.o

3.在linux环境下,重新编译u-boot,得到u-boot.bin,并升级到自己的开发板中(如果你没有开发板,没有关系,你只需要明白我们要在开发板中验证自己添加的命令itxiebo)

4.升级完后,在开发板启动内核之前,按space键进入u-boot命令行模式。
u-boot分析 七 (添加u-boot命令,学习u-boot命令实现原理)_第1张图片

5.在串口终端中输入help命令,回车,可以发现itxiebo命令行已经添加成功。
u-boot分析 七 (添加u-boot命令,学习u-boot命令实现原理)_第2张图片

6.在串口终端中输入itxiebo命令,回车执行该命令,发现我们添加的打印log,可以正确打印出来:

二、命令原理分析

实战见效果了,我们继续分析。不难发现,只要能搞清上面代码中的“U_BOOT_CMD”,就能弄明白uboot命令实现原理。

U_BOOT_CMD格式如下:

U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)

其中,各个参数解释如下:

参数名 说明
_name 命令名,非字符串,但在U_BOOT_CMD中用“#”符号转化为字符串
_maxargs 命令的最大参数个数
_rep 是否自动重复(按Enter键是否会重复执行)
_cmd 该命令对应的响应函数
_usage 简短的使用说明(字符串)
_help 较详细的使用说明(字符串)

说明:
在内存中保存命令的help字段会占用一定的内存,通过配置U-Boot可以选择是否保存help字段。若在include/configs/s5p4418_urbetter.h 中定义了CONFIG_SYS_LONGHELP宏,则在U-Boot中使用help命令查看某个命令的帮助信息时将显示_usage和_help字段的内容,否则就只显示usage字段的内容,而不显示_help字段的内容。

另外,在include/command.h中,对U_BOOT_CMD的define 如下:

#define ll_entry_declare(_type, _name, _list)               \
    _type _u_boot_list_2_##_list##_2_##_name __aligned(4) __attribute__((unused,    section(".u_boot_list_2_"#_list"_2_"#_name)))

#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \
    ll_entry_declare(cmd_tbl_t, _name, cmd) =           \
        U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,  _usage, _help, _comp);

#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)      \
    U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)

最后,同样在include/command.h中定义了一个结构体cmd_tbl_t:

u-boot分析 七 (添加u-boot命令,学习u-boot命令实现原理)_第3张图片

如此,我们便可以将U_BOOT_COM解析,如下

U_BOOT_CMD( itxiebo, 2, 0, do_itxiebo, "itxiebo - this is a itxiebo command, do nothing", "- this is a itxiebo command, do nothing" );

解析为:

cmd_tbl_t _u_boot_list_2_do_itxiebo_2_itxiebo __aligned(4) __attribute__((unused,section(".u_boot_list_2_"do_itxiebo"_2_"itxiebo)))

其中,“u_boot_list”,《u-boot分析 三》分析u-boot.lds时解释过。也就是说咱们新增的itxiebo command会被储存在u_boot_list段内。

.u_boot_list : {
        KEEP(*(SORT(.u_boot_list*)));
        /*.data段结束后,紧接着存放u-boot自有的一些function,例如u-boot command等*/
    }

三、itxiebo命令的执行过程:

在U-Boot中输入(串口终端)“itxiebo”命令执行时,U-Boot接收输入的字符串“itxiebo”,传递给run_command()函数。run_command()函数调用common/command.c中实现的find_cmd()函数在u_boot_list段内查找命令,并返回itxiebo命令的cmd_tbl_t结构。然后run_command()函数使用返回的cmd_tbl_t结构中的函数指针调用itxiebo命令的响应函数do_itxiebo,从而完成了命令的执行。

参考:
http://www.cnblogs.com/sdphome/archive/2011/08/19/2146327.html

完事儿。

你可能感兴趣的:(命令,u-boot,U-BOOT-CMD,添加uboot命令)