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 /* no long help info */
#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 /* CFG_LONGHELP */
每一个命令定义一个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 /* icache, dcache */
如果有更多的命令,也要在这里添加定义。
(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: /* 参数个数为1,则执行打开或者关闭指令cache操作 */
switch (on_off(argv[1])) {
case 0: icache_disable(); //打开指令cache
break;
case 1: icache_enable (); //关闭指令cache
break;
}
/* FALL TROUGH */
case 1: /* 参数个数为0,则获取指令cache状态*/
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中有如下定义。
/***********************************************************
* Command definition
***********************************************************/
#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 文件
内容如下
/*
*!ql add for test add u-boot command
*/
#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,
/* IP Header */
0x45,0x00,0x01,0x4e,
0xc1,0x3e,0x00,0x00,
0x40,0x11,0xf6,0x36,
0xc0,0xa8,0x01,0x82,
0x00,0x00,0x00,0x00,
/* UDP Header */
0x0f,0x10,0x00,0x50,
0x01,0x3a,0x2d,0x3b
/* DATA 306B*/
};
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;
}