如何向 PPC-Boot中添加自定义命令
Sailor_forever sailing_9806@163.com 转载请注明
http://blog.csdn.net/sailor_8318/archive/2009/07/08/4332088.aspx
**********************************************************************
【摘要】:本文介绍了 PPC-Boot中命令的组织结构及解析过程,接着介绍了添加自定义命令的基本框架,为 Pbist项目中如何添加自定义测试功能奠定了基础。 PPC-Boot命令的检测及解析机制可在 PUC Boot中借鉴,其可扩展行裁剪性非常适合用嵌入式系统应用。
【关键字】: PPC-Boot; MPC8270; run_command ; parse_line; find_cmd
1、命令结构定义
2、命令解析过程
3、如何添加用户命令
1)、定义 CACHE命令标志位
2)、配置系统当前支持的 CMD
3)、实现 CACHE命令的操作函数
4)、添加命令表项宏定义
5)、添加命令到系统搜索列表中
6)、更改 Makefile
PPC-Boot的命令为用户提供了交互功能,并且已经实现了几十个常用的命令。如果开发板需要很特殊的操作,可以添加新的 PPC-Boot命令.
1 、命令结构定义
PPC-Boot的每一个命令都是通过 MK_CMD_TBL_ENTRY宏定义的。这个宏在 include/command.h头文件中定义,每一个命令定义一个 cmd_tbl_t结构体。
#ifdef CFG_LONGHELP
#define MK_CMD_TBL_ENTRY(name,lmin,maxargs,rep,cmd,usage,help) /
{ name, lmin, maxargs, rep, cmd, usage, help }
#else /* no help info */
#define MK_CMD_TBL_ENTRY(name,lmin,maxargs,rep,cmd,usage,help) /
{ name, lmin, maxargs, rep, cmd, usage }
#endif
struct cmd_tbl_s {
char *name; /* Command Name */
int lmin; /* minimum abbreviated length */
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
};
这样每一个 PPC-Boot命令有一个结构体来描述。结构体包含的成员变量:命令名称、最大参数个数、是否允许重复执行上一个命令、命令执行函数、用法、帮助。
Name是匹配因子,大小写必须一致,否则无法识别。
2 、命令解析过程
从控制台输入的命令是由 common/main.c中的程序解释执行的。
main_loop为循环入口函数,其在指定的延时时间内检测是否有输入,若没有,则自动运行“ bootcmd”所指定的命令;若有输入,则 readline循环检测用户输入,用户输入 Enter后, run_command执行输入命令,其解析由“;”所分割的每个命令, parse_line将命令及其参数重新组织, find_cmd进行命令匹配检测,命令匹配成功后,将其传给命令表中注册的执行函数
(cmdtp->cmd) (cmdtp, flag, argc, argv)
由具体的命令函数进一步检查相关参数。
涉及的相关函数列表如下:
/* common/main.c */
int readline (const char *const prompt)
int run_command (const char *cmd, int flag)
int parse_line (char *line, char *argv[])
/* common/command.c */
cmd_tbl_t *find_cmd(const char *cmd);
find_cmd()负责匹配输入的命令,从列表中找出对应的命令结构体。
3 、如何添加用户命令
由上面命令解析的过程可知,添加一个新命令,只需要实现命令对应的函数即可,命令的输入及解析无需我们关心。
基于 PPC-Boot命令的基本框架,来分析一下简单的 icache操作命令,就可以知道添加新命令的方法。
1 )、定义 CACHE 命令标志位
在 include/cmd_confdefs.h中定义了所有 PPC-Boot命令的标志位。
#define CFG_CMD_CACHE 0x00000010 /* icache, dcache */
如果有更多的命令,也需要在这里添加定义,不能与其他命令的标志位冲突。
2 )、配置系统当前支持的 CMD
PPC-Boot的命令系统扩展性非常好,可以定制,添加删除,打开 CONFIG_COMMANDS选项的命令标志位。这个程序文件开头 有 #if语句需要预处理是否包含这个命令函数。 CONFIG_COMMANDS选项在开发板的配置文件中定义当前支持的所有命令。例如: SMDK2410平台在 include/configs/smdk2410.h中有如下定义。
#define CONFIG_COMMANDS (CONFIG_CMD_DFL | /
CFG_CMD_I2C | /
CFG_CMD_CACHE | /
CFG_CMD_MII | /
CFG_CMD_EEPROM)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
3 )、实现 CACHE 命令的操作函数
下面是 common/cmd_cache.c文件中 icache命令部分的代码。
为了便于裁剪代码,程序都是通过 1和 2两步所定义的宏开关来控制的。
#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;
}
4 )、添加命令表项宏定义
一般在相应命令的头文件中定义该命令表项宏,如 /include/cmd_cache.h
#if (CONFIG_COMMANDS & CFG_CMD_CACHE)
#define CMD_TBL_ICACHE MK_CMD_TBL_ENTRY( /
"icache", 2, 2, 1, do_icache, /
"icache - enable or disable instruction cache/n", /
"[on, off]/n" /
" - enable or disable instruction cache/n" /
),
#define CMD_TBL_DCACHE MK_CMD_TBL_ENTRY( /
"dcache", 2, 2, 1, do_dcache, /
"dcache - enable or disable data cache/n", /
"[on, off]/n" /
" - enable or disable data (writethrough) cache/n" /
),
int do_icache (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_dcache (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_ICACHE
#define CMD_TBL_DCACHE
#endif /* CFG_CMD_CACHE */
当系统不支持某命令时,该宏自动实现为空,对系统不会有任何影响,尤其是下面的命令数组,其不需要再用宏来控制
5 )、添加命令到系统搜索列表中
/common/command.c中包括了系统所有的命令
首先添加上面某命令的头文件,如 #include <cmd_cache.h>
然后添加命令到搜索列表中,否则系统无法识别该命令。注意此数组的排列顺序是按照字母顺序组成的,便于搜索,因此新添加的命令一定要遵循此规则。
/*
* The commands in this table are sorted alphabetically by the
* command name and in descending order by the command name string
* length. This is to prevent conflicts in command name parsing.
* Please ensure that new commands are added according to that rule.
* Please use $(TOPDIR)/doc/README.commands as a reference AND make
* sure it gets updated.
*/
cmd_tbl_t cmd_tbl[] = {
CMD_TBL_ASKENV
CMD_TBL_ASM
CMD_TBL_AUTOSCRIPT
。。。。。
CMD_TBL_BSP
。。
CMD_TBL_DCACHE
。。
#if defined(CONFIG_PUC8250) || defined(CONFIG_PUC8260) || defined(CONFIG_PUC8270)
#if defined(AXR)
CMD_TBL_TEST_ALL_AXR
#elif defined(ODU_LC)
CMD_TBL_TEST_ALL_MSH
#elif defined(XMP1)
CMD_TBL_TEST_ALL_XMP1
#endif
CMD_TBL_TEST_EEPROM
CMD_TBL_TEST_ETHERNET
CMD_TBL_TEST_FLASH
CMD_TBL_TEST_RS232
CMD_TBL_TEST_SDRAM
#if defined(L2C)
CMD_TBL_INV_L2C
#endif
#endif
CMD_TBL_QUES /* keep this ("help") the last entry */
/* the following entry terminates this table */
MK_CMD_TBL_ENTRY( NULL, 0, 0, 0, NULL, NULL, NULL )
};
cmd_tbl数组的大小是由 CONFIG_COMMANDS 所定义支持的命令数来决定的,大小是动态的,因此需要一个表项来表示结束 MK_CMD_TBL_ENTRY( NULL, 0, 0, 0, NULL, NULL, NULL ) 。
裁剪 CONFIG_COMMANDS 时,无需再更改此数组,因为由第四步可知,相关表现自动为空。
6 )、更改 Makefile
在 common/Makefile中添加编译的目标文件,否则系统不会编译新添加的代码。
COBJS = main.o altera.o bedbug.o /
cmd_autoscript.o cmd_bedbug.o cmd_boot.o /
cmd_bootm.o cmd_cache.o cmd_console.o cmd_date.o /
cmd_dcr.o cmd_diag.o cmd_doc.o cmd_dtt.o /
cmd_eeprom.o cmd_elf.o cmd_fdc.o cmd_flash.o /
cmd_fpga.o cmd_i2c.o cmd_ide.o cmd_immap.o /
cmd_jffs2.o cmd_mem.o cmd_mii.o cmd_misc.o /
cmd_net.o cmd_nvedit.o env_common.o /
env_flash.o env_eeprom.o env_nvram.o env_nowhere.o /
cmd_pci.o cmd_pcmcia.o cmd_test.o/
cmd_reginfo.o cmd_scsi.o cmd_vfd.o cmd_usb.o /
command.o console.o devices.o dlmalloc.o /
docecc.o environment.o flash.o fpga.o /
hush.o kgdb.o lists.o miiphybb.o miiphyutil.o /
s_record.o soft_i2c.o soft_spi.o cmd_spi.o spartan2.o /
usb.o usb_kbd.o usb_storage.o /
virtex2.o xilinx.o