您的位置:首页 > 其它

(转)uboot命令增加过程

2013-05-02 18:03 267 查看
原文出处: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: