您的位置:首页 > 大数据 > 人工智能

UBOOT之源码分析(X4412)——main_loop函数分析

2014-09-15 17:09 666 查看
void main_loop (void)

{

#ifndefCONFIG_SYS_HUSH_PARSER

staticchar lastcommand[CONFIG_SYS_CBSIZE] = { 0, };

int len;

int rc= 1;

int flag;

#endif

//声明一些hush参数变量

#ifdefined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)

char*s;

int bootdelay;

#endif

/*在uboot启动后会倒计时CONFIG_BOOTDELAY,如果沒有收到用户的输入则自动去执行宏CONFIG_BOOTCOMMAND中设置的命令。这里声明倒计时使用的变量*/

#ifdefCONFIG_SYS_HUSH_PARSER

u_boot_hush_start ();

#endif

//使用hush命令解析器。u_boot_hush_start()在common/hush.c中实现

#ifdefCONFIG_AUTO_COMPLETE//自动补全命令,这里未定义使用

install_auto_complete();

#endif

#ifdefined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
s= getenv ("bootdelay");

bootdelay= s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

//从环境变量中获取bootdelay参数(倒计时参数),得到自动启动缺省镜像文件的延时(单位是秒)。CONFIG_BOOTDELAY在x4412.h中设置为3秒

debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);

s= getenv ("bootcmd");
//从环境变量中获取bootcmd参数,得到在启动延时过程中自动执行的命令。

debug("### main_loop: bootcmd=\"%s\"\n", s ? s :"<UNDEFINED>");

if(bootdelay >= 0 && s && !abortboot (bootdelay)){//判断延时时间和是否有按键

#ifndef CONFIG_SYS_HUSH_PARSER //定义
run_command(s, 0);

#else

parse_string_outer(s, FLAG_PARSE_SEMICOLON |

FLAG_EXIT_FROM_LOOP);

#endif

//当得到了bootcmd参数,bootdelay参数也是大于等于0,并且在启动延时过程中没有按下

//任意键时,执行parse_string_outer函数,该函数的作用是解释bootcmd参数并执行,它是

//在common目录下的hush.c文件内定义的。

}

#ifdef CONFIG_MENUKEY
//未定义

if(menukey == CONFIG_MENUKEY) {

s = getenv("menucmd");

if (s) {

# ifndef CONFIG_SYS_HUSH_PARSER

run_command (s,0);

#else

parse_string_outer(s, FLAG_PARSE_SEMICOLON |

FLAG_EXIT_FROM_LOOP);

#endif

}

}

#endif/* CONFIG_MENUKEY */

#endif/* CONFIG_BOOTDELAY */

/*

* Main Loop for Monitor Command Processing

*/

#ifdefCONFIG_SYS_HUSH_PARSER

parse_file_outer();

/*This point is never reached */

for(;;);

//parse_file_outer函数是在common目录下的hush.c文件中定义的,它的含义是依次读取命令序列中的命令并执行之,其中在该函数还调用了parse_stream_outer函数,这个函数体内有一个do-while循环,只有发生语法错误的时候才会跳出该循环,因此一般情况下永远也不会执行for(;;);代码,而是始终在那个do-while循环体内。

#else

for(;;) {

#ifdefCONFIG_BOOT_RETRY_TIME

if(rc >= 0) {

/*Saw enough of a valid command to

* restart the timeout.

*/

reset_cmd_timeout();

}

#endif

len= readline (CONFIG_SYS_PROMPT);

flag = 0; /* assume no specialflags for now */

if (len > 0)

strcpy (lastcommand,console_buffer);

else if (len == 0)

flag |=CMD_FLAG_REPEAT;

#ifdef CONFIG_BOOT_RETRY_TIME

else if (len== -2) {

/* -2 means timed out, retry autoboot

*/

puts("\nTimed out waiting for command\n");

#ifdef CONFIG_RESET_TO_RETRY

/* Reinit board to runinitialization code again */

do_reset (NULL, 0, 0, NULL);

#else

return; /* retry autoboot */

# endif

}

#endif

if(len == -1)

puts("<INTERRUPT>\n");

else

rc = run_command(lastcommand, flag);

if(rc <= 0) {

/* invalid command or not repeatable, forget it*/

lastcommand[0] = 0;

}

}

#endif/*CONFIG_SYS_HUSH_PARSER*/

}

1.abortboot函数的分析

//abortboot是uboot在引导期间的延时函数。期间可以按键进入uboot的命令行。

//common/main.c

static__inline__ int abortboot(int bootdelay)

{

int abort = 0;

#ifdefCONFIG_MENUPROMPT

printf(CONFIG_MENUPROMPT);

#else

printf("Hitany key to stop autoboot: %2d ", bootdelay);
//打印提示信息

#endif

#ifdefined CONFIG_ZERO_BOOTDELAY_CHECK//未定义。

//如果定义了这个宏,即使定义延时为0,也会检查一次是否有按键按下。只要在

//这里执行之前按键,还是能进入uboot的命令行。

/*

* Check if key already pressed

* Don't check if bootdelay <0

*/

if(bootdelay >= 0) {

if (tstc()) { /* we got a keypress */

(void) getc(); /* consume input */

puts("\b\b\b 0");

abort = 1; /* don't auto boot */

}

}

#endif

//如果延时大于零并且停止标记没有赋值则进入延时循环,直到延时完或者接收到了按键

while((bootdelay > 0) && (!abort)) {

inti;

--bootdelay;

/* delay 100 * 10ms每秒中测试按键100次,之后延时10ms。*/

for(i=0; !abort && i<100; ++i) {

if (tstc()) { /* wegot a key press */

abort = 1; /* don't auto boot 有键按下修改标识停止自动引导*/

bootdelay= 0; /* no more delay 延时清0*/

#ifdef CONFIG_MENUKEY

menukey = getc();

# else

(void)getc(); /* consume input 获取按键*/

#endif

break;

}

udelay(10000);//延时10000us,也就是10ms

}

printf("\b\b\b%2d", bootdelay); //打印当前剩余时间

}

putc('\n');

#ifdefCONFIG_SILENT_CONSOLE
//未定义

if(abort)

gd->flags&= ~GD_FLG_SILENT;

#endif

returnabort;
//返回结果:1-停止引导,进入命令行;0-引导内核。

}

//可以看到uboot延时的单位是秒,如果想提高延时的精度,比如想进行10ms级的延时,将

//udelay(10000)改为udelay(100)就可以了。

2.引导命令s= getenv ("bootcmd");引导命令定义在include/configs/x4412.h

/*

* BOOTP options

*/

#define CONFIG_BOOTP_SUBNETMASK

#defineCONFIG_BOOTP_GATEWAY

#define CONFIG_BOOTP_HOSTNAME

#defineCONFIG_BOOTP_BOOTPATH

#defineCONFIG_ETHADDR 00:40:5c:26:0a:5b

#define CONFIG_NETMASK 255.255.255.0

#define CONFIG_IPADDR 192.168.0.20

#defineCONFIG_SERVERIP 192.168.0.10

#defineCONFIG_GATEWAYIP 192.168.0.1

/*在uboot启动后会倒计时CONFIG_BOOTDELAY,如果沒有收到用户的输入则自动去执行宏CONFIG_BOOTCOMMAND中设置的命令*/

#defineCONFIG_BOOTDELAY 3

/* Default boot commands for Android booting.*/

#define CONFIG_BOOTCOMMAND "movi read kernel 040008000;movi read rootfs 0 41000000 400000;bootm 40008000 41000000"

#defineCONFIG_BOOTARGS "lcd=vs070cxn tp=ft5x06-1024x600 cam=ov2655mac=00:09:c0:ff:ee:58"

#defineCONFIG_BOOTARGS_QT"root=/dev/mmcblk0p2 rw rootfstype=ext4lcd=vs070cxn tp=ft5x06-1024x600 cam=ov2655 mac=00:09:c0:ff:ee:58"

#defineCONFIG_BOOTCOMMAND2 "fdisk -c 0;sdfuse flashall;reset"

#defineCONFIG_BOOTCOMMAND3 "ext3format mmc 0:3;ext3format mmc0:4;" \

"movi read kernel 0 40008000;movi readrootfs 0 41000000 100000;bootm 40008000 41000000"

#defineCONFIG_BOOTCOMMAND_QT "movi read kernel 0 40008000;bootm40008000"

//*

可见,引导内核其实就是将内核读取到内存中然后再跳到那个地方引导.
CONFIG_BOOTARGS_QT和CONFIG_BOOTCOMMAND_QT为LINUX内核QT文件系统环境变量。

CONFIG_BOOTCOMMAND和CONFIG_BOOTARGS为linux内核android环境变量。

bootargs=lcd=vs070cxntp=ft5x06-1024x600 cam=ov2655 mac=00:09:c0:ff:ee:58

bootcmd=moviread kernel 0 40008000;movi read rootfs 0 41000000 400000;bootm40008000 41000000

CONFIG_BOOTCOMMAND2为MMC分区,SD烧录,重启命令。这个命令在board_late_init()函数中使用,下面将作介绍。
CONFIG_BOOTCOMMAND3MMC格式化命令,暂未实现。
*/

3.第二阶段板子初始化函数board_late_init()函数在board/samsung/x4212/x4212.c中。此函数由第二阶段板级初始化函数调用。
int board_late_init (void)
{
#ifdefCONFIG_UPDATE_SOLUTION
GPIO_Init();//GPIO引脚初始化
GPIO_SetFunctionEach(eGPIO_X1,eGPIO_0, 0);
//设置开发板左按键IO口输入
GPIO_SetPullUpDownEach(eGPIO_X1,eGPIO_0, 0);//关闭左按键IO口上下拉

udelay(10);
if(GPIO_GetDataEach(eGPIO_X1, eGPIO_0) == 0)//判断左按键是否按下
{
puts("LEFT MODE:[DOWN]\n");
setenv("bootcmd", CONFIG_BOOTCOMMAND2);
//左按键按下,从SD卡烧写文件
}
else
puts("LEFT MODE:[UP]\n");
#endif
return0;
}

//也就是说,通过SD卡烧录从这个地方进入

4.parse_string_outer()函数在common/hush.c中实现
#ifndef__U_BOOT__
staticint parse_string_outer(const char *s, int flag)
#else
intparse_string_outer(char *s, int flag)
#endif /*__U_BOOT__ */
{
structin_str input;
#ifdef__U_BOOT__
char*p = NULL;
intrcode;
if( !s || !*s)
return1;
if(!(p = strchr(s, '\n')) || *++p) {
p= xmalloc(strlen(s) + 2);
strcpy(p,s);
strcat(p,"\n");
setup_string_in_str(&input,p);
rcode= parse_stream_outer(&input, flag);
free(p);
returnrcode;
}else {
#endif
setup_string_in_str(&input,s);
returnparse_stream_outer(&input, flag);
#ifdef__U_BOOT__
}
#endif
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: