经过devices_init(),创建了devlist,但是只有一个串口设备注册在内。显然,devlist中的设备都是可以做为console的。
16) jumptable_init ();初始化gd->jt。1.1.6版本的jumptable只起登记函数地址的作用。并没有其他作用。
17)console_init_r ();后期控制台初始化
主要过程:查看环境参数stdin,stdout,stderr中对标准IO的指定的设备名称,再按照环境指定的名称搜索devlist,将搜到的设备指针赋给标准IO数组stdio_devices[]。置gd->flag标志GD_FLG_DEVINIT。这个标志影响putc,getc函数的实现,未定义此标志时直接由串口serial_getc和serial_putc实现,定义以后通过标准设备数组stdio_devices[]中的 putc和getc来实现IO。 下面是相关代码:
void putc (const char c) {
#ifdef CONFIG_SILENT_CONSOLE
if (gd->flags & GD_FLG_SILENT)//GD_FLG_SILENT无输出标志 return; #endif
if (gd->flags & GD_FLG_DEVINIT) {//设备list已经初始化 /* Send to the standard output */ fputc (stdout, c); } else {
/* Send directly to the handler */
serial_putc (c);//未初始化时直接从串口输出。 } }
void fputc (int file, const char c) {
if (file < MAX_FILES)
stdio_devices[file]->putc (c); }
为什么要使用devlist,std_device[]?
为了更灵活地实现标准IO重定向,任何可以作为标准IO的设备,如USB键盘,LCD屏,串口等都可以对应一个device_t的结构体变量,只需要实现getc和putc等函数,就能加入到devlist列表中去,也就可以被assign为标准IO设备std_device中去。如函数 int console_assign (int file, char *devname); /* Assign the console 重定向标准输入输出*/
这个函数功能就是把名为devname的设备重定向为标准IO文件
file(stdin,stdout,stderr)。其执行过程是在devlist中查找devname的设备,返回这个设备的device_t指针,并把指针值赋给std_device[file]。
18)enable_interrupts(),使能中断。由于CONFIG_USE_IRQ没有定义,空实现。 #ifdef CONFIG_USE_IRQ /* enable IRQ interrupts */ void enable_interrupts (void)
{
unsigned long temp;
__asm__ __volatile__(\ \ \ : \ :
: \ } #else
void enable_interrupts (void) { }
19)设置CS8900的MAC地址。
cs8900_get_enetaddr (gd->bd->bi_enetaddr); 20)初始化以太网。
eth_initialize(gd->bd);//bd中已经IP,MAC已经初始化 21)main_loop ();定义于common/main.c
至此所有初始化工作已经完毕。main_loop在标准转入设备中接受命令行,然后分析,查找,执行。
关于U-boot中命令相关的编程:
1、命令相关的函数和定义
@main_loop:这个函数里有太多编译选项,对于smdk2410,去掉所有选项后等效下面的程序
void main_loop() {
static char lastcommand[CFG_CBSIZE] = { 0, }; int len; int rc = 1; int flag; char *s; int bootdelay;
s = getenv (\自动启动内核等待延时
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
debug (\ s = getenv (\取得环境中设置的启动命令行 debug (\
if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
run_command (s, 0);//执行启动命令行,smdk2410.h中没有定义CONFIG_BOOTCOMMAND,所以没有命令执行。
}
for (;;) {
len = readline(CFG_PROMPT);//读取键入的命令行到console_buffer
flag = 0; /* assume no special flags for now */ if (len > 0)
strcpy (lastcommand, console_buffer);//拷贝命令行到lastcommand. else if (len == 0) flag |= CMD_FLAG_REPEAT; if (len == -1) puts (\ else
rc = run_command (lastcommand, flag); //执行这个命令行。
if (rc <= 0) {
/* invalid command or not repeatable, forget it */ lastcommand[0] = 0; } }
@run_comman();在命令table中查找匹配的命令名称,得到对应命令结构体变量指针,以解析得到的参数调用其处理函数执行命令。