u-boot-1.1.6 tq2440
u-boot有两个功能: 调试功能,启动内核。
调试功能实现是通过u-boot /common下定义的大量的命令的来实现的。
用户通过u-boot命令行来告诉要输入的命令,命令行交互是通过u-boot的main_loop来实现的。接下来我们就看看main_loop是怎么实现命令行交互的吧!
将tq2440修改过的main_loop代码根据宏定义,掐头去尾后代码如下:
main_loop命令行
/common/main.c 掐头去尾后代码如下
void main_loop (void)
{
#ifndef CFG_HUSH_PARSER
static char lastcommand[CFG_CBSIZE] = { 0, };
int len;
int rc = 1;
int flag;
#endif
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
char *s;
int bootdelay;
#endif
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
s = getenv ("bootdelay");//获得环境变量的bootdelay的值
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;//确定最后的bootdelay的值
s = getenv ("bootcmd");//获得超时后u-boot自启动的命令
if (bootdelay >= 0 && s && !abortboot (bootdelay)) //调用abortboot 倒计时计数
{
if (bBootFrmNORFlash())//从nor flash启动,执行menu命令,显示调试界面,用户自定义
run_command("menu", 0);
else //从nand flash启动,执行boot_zImage命令,启动内核,用户自定义
{
printf("Booting Linux ...\n");
run_command("boot_zImage", 0);
}
}
#endif/* CONFIG_BOOTDELAY */
//当abortboot 倒计时不为0时,按下键盘,则nand启动模式就进入命令行模式
//初始化mtd(不是很懂这个)标准的源码没有这个
#ifdef CONFIG_JFFS2_CMDLINE
extern int mtdparts_init(void);
if (!getenv("mtdparts"))
run_command("mtdparts default", 0);
else
mtdparts_init();
#endif
for (;;) {
len = readline (CFG_PROMPT);//获取用户输入的内容
flag = 0;
if (len > 0)
strcpy (lastcommand, console_buffer);//将用户输入保存在lastcommand数组中
else if (len == 0)
flag |= CMD_FLAG_REPEAT;//用户如果只是按了回车,那么重复执行上次那个命令
if (len == -1)
puts ("\n");//中断执行
else
rc = run_command (lastcommand, flag);//执行用户输入的命令
if (rc <= 0)
lastcommand[0] = 0;//无效的命令,清空lastcommand内容
}/*end for*/
}/*end main_loop*/
abortboot 倒计时显示
/common/main.c 掐头去尾后的代码如下
static __inline__ int abortboot(int bootdelay)
{
int abort = 0;//默认不终止倒计时
char c;
printf("Press any key to stop autoboot: %2d ", bootdelay);//在串口终端显示倒计时
while ((bootdelay > 0) && (!abort))
{
int i;
--bootdelay;//倒计时减1
for (i=0; !abort && i<100; ++i)
{
if (tstc()) //检查是否有按键输入
{
abort = 1; //终止倒计时
bootdelay = 0; //倒计时清零
(void) getc();
break; //退出for循环
}
udelay (10000); //延时0.01s
}/*end for*/
printf ("\b\b\b%2d ", bootdelay);
}/*end while*/
}
putc ('\n');
return abort;
}
readline读取用户输入
/common/main.c 掐头去尾结果
int readline (const char *const prompt)
{
char *p = console_buffer; //p指向当前要输入的字符的地址
int n = 0; //n输入的字符数
int plen = 0; //使用提示符大小 smdk2410#
int col; //输入的字符显示时相对开始的偏移量
char c; //每次读到的字符
if (prompt)
{
plen = strlen (prompt);
puts (prompt); //打印出输入提示符
}
col = plen;
for (;;) {
c = getc(); //获得输入
switch (c) { //特殊字符的处理
case '\r'://按下enter键,输入结束
case '\n':
*p = '\0';
puts ("\r\n");
return (p - console_buffer);//返回输入的字符数
case '\0':
continue;
case 0x03://按下ctrl+c,放弃输入
console_buffer[0] = '\0';
return (-1);
case 0x15://按下ctrl+u,删除输入行
while (col > plen){
puts (erase_seq);
--col;}
p = console_buffer;
n = 0;
continue;
case 0x17://按下ctrl+w,删除输入行的一个字
p=delete_char(console_buffer, p, &col, &n, plen);
while ((n > 0) && (*p != ' ')) {
p=delete_char(console_buffer, p, &col, &n, plen);}
continue;
case 0x08://按下ctr+h backspace
case 0x7F://按下del backspace
p=delete_char(console_buffer, p, &col, &n, plen);
continue;
default://默认处理
if (n < CFG_CBSIZE-2){
if (c == '\t') {//按下tab键
puts (tab_seq+(col&07));
col += 8 - (col&07);}
else {//可见字符处理
++col;
putc (c);}//屏幕回显输入的字符
*p++ = c; //保存输入的字符
++n; } //字符数加1
else //输入缓冲满
putc ('\a');
}/*end switch*/
}/*end for*/
}/*end readline*/
run_command执行命令( 点击访问u-boot命令实现)
/common/main.c
int run_command (const char *cmd, int flag)
{
cmd_tbl_t *cmdtp;
char cmdbuf[CFG_CBSIZE];
char *token;
char *sep;
char finaltoken[CFG_CBSIZE];
char *str = cmdbuf;
char *argv[CFG_MAXARGS + 1];
int argc, inquotes;
int repeatable = 1;
int rc = 0;
clear_ctrlc();
if (!cmd || !*cmd) return -1;
if (strlen(cmd) >= CFG_CBSIZE) {
puts ("## Command too long!\n");
return -1;}
strcpy (cmdbuf, cmd);
while (*str) {
for (inquotes = 0, sep = str; *sep; sep++) {
if ((*sep=='\'') && (*(sep-1) != '\\'))
inquotes=!inquotes;
if (!inquotes &&(*sep == ';') &&(sep != str) &&(*(sep-1) != '\\'))
break;
}
token = str;
if (*sep) { str = sep + 1;*sep = '\0';}
else
str = sep;
if ((argc = parse_line (finaltoken, argv)) == 0) {//解析命令缓冲中的参数
rc = -1;
continue;}
if ((cmdtp = find_cmd(argv[0])) == NULL) {//根据名称查找是否定义了该命令
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
rc = -1;
continue;}
if (argc > cmdtp->maxargs){
printf ("Usage:\n%s\n", cmdtp->usage);
rc = -1;
continue;}
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0)//调用命令执行
rc = -1;
repeatable &= cmdtp->repeatable;
if (had_ctrlc ())
return 0;
}
return rc ? rc : repeatable;
}
上面就是main_loop的大致过程了。