u-boot启动过程之STEP2
2017-04-27 22:01
246 查看
在STEP1的最后,代码通过调用void start_armboot (void)进入了u-boot启动的第二阶段
1. void start_armboot (void)主要是对硬件的初始化,代码详解
void start_armboot (void) { init_fnc_t **init_fnc_ptr; char *s; /* Pointer is writable since we allocated a register for it */ // 初始化gd,使其指向global data区的基地址 gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); /* compiler optimization barrier needed for GCC >= 3.4 */ //1. __asm__用于指示编译器在此插入汇编语句 //2. __volatile__用于告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。 //3. memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作废。 // cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。 //4. "":::表示这是个空指令。 __asm__ __volatile__("": : :"memory"); //清零global data区 memset ((void*)gd, 0, sizeof (gd_t)); //初始化gd->bd,使其指向bd_t的基地址 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); //清零bd_t区 memset (gd->bd, 0, sizeof (bd_t)); // u-boot代码的大小。根据u-boot.lds可知,monitor_flash_len是.text + .rodata + .data + .got + .u_boot_cmd 的总长度。 monitor_flash_len = _bss_start - _armboot_start; //init_sequence是初始化函数数组的起始地址,在这个循环中,会依次去执行初始化函数,若出现故障,则进入死循环。初始化函数包括 //1. cpu_init, /* basic cpu dependent setup, 分配IRQ, FIQ的栈地址 */ //2. board_init, /* basic board dependent setup, 初始化IO口 */ //3. interrupt_init, /* set up exceptions, 初始化时钟 */ //4. env_init, /* initialize environment, 初始化环境变量 */ //5. init_baudrate, /* initialze baudrate settings, 初始化波特率 */ //6. serial_init, /* serial communications setup , 初始化串口*/ //7. console_init_f, /* stage 1 init of console, 初始化终端 */ //8. display_banner, /* say that we are here, 打印一些信息到终端 */ //9. dram_init, /* configure available RAM banks, 初始化SDRAM的内存起始地址和大小。 */ //10. display_dram_config, 打印SDRAM的大小。 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } } /* configure available FLASH banks */ // 初始化NOR FLASH,配置每个sector的size等。 size = flash_init (); // 打印出NOR FLASH 的整个SIZE信息 display_flash_config (size); /* armboot_start is defined in the board-specific linker script */ // 初始化malloc区,并全部清零 mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); #if (CONFIG_COMMANDS & CFG_CMD_NAND) //初始化NAND FLASH相关的寄存器。 puts ("NAND: "); nand_init(); /* go init the NAND */ #endif /* initialize environment */ //初始化环境变量 env_relocate (); /* IP Address */ // 获取配置的IP地址 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); /* MAC Address */ // 获取配置的MAC值,并将其存储到gd->bd->bi_enetaddr中。 { int i; ulong reg; char *s, *e; char tmp[64]; i = getenv_r ("ethaddr", tmp, sizeof (tmp)); s = (i > 0) ? tmp : NULL; for (reg = 0; reg < 6; ++reg) { gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; } } // 初始化并注册外围设备,串口就是在这里初始化并注册的。 devices_init (); /* get the devices list going. */ // 初始化gd中的jump table中的函数,如get_version,malloc,getenv jumptable_init (); // 查找是否有可用的输入输出设备,若有,将其作为标准的输入输出设备: // 输入: getc, tstc // 输出: putc,puts,printf console_init_r (); /* fully init console as a device */ // 初始化ARM的IO口。 Port_Init(); // PreLoadedONRAM这个变量在start.S中定义的。 //.globl PreLoadedONRAM //PreLoadedONRAM: //.word 0 if (!PreLoadedONRAM) { /* enable exceptions */ enable_interrupts (); /* add by www.100ask.net */ // 初始化usb口 usb_init(); } /* main_loop() can return to retry autoboot, if so just run it again. */ // 经过一系列初始化后,进入主循环。 for (;;) { main_loop (); } }
2. void main_loop (void)用于对FLASH进行分区、调用kernel,执行u-boot中输入的命令,其被void start_armboot (void)调用。
void main_loop (void) { #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) //初始化bootdelay相关的变量 char *s; int bootdelay; #endif #ifdef CONFIG_JFFS2_CMDLINE // 初始化分区表,对FLASH进行分区 //mtdparts=mtdparts=nandflash0:256k@0(bootloader),128k(params),2m(kernel),-(root) extern int mtdparts_init(void); if (!getenv("mtdparts")) { run_command("mtdparts default", 0); } else { mtdparts_init(); } #endif #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) // 获取 bootdelay的值: bootdelay=2 s = getenv ("bootdelay"); // 转换成整数 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; // 获取bootcmd的参数: bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0 s = getenv ("bootcmd"); // 倒计时开始,若倒计时结束,没有按下任何按键,则该条件成立 if (bootdelay >= 0 && s && !abortboot (bootdelay)) { // 打印Booting Linux ... printf("Booting Linux ...\n"); // 执行bootcmd的参数,nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0 run_command (s, 0); } #endif /* CONFIG_BOOTDELAY */ // 执行 menu 命令 run_command("menu", 0); // 进入死循环,读取命令并执行之。 for (;;) { len = readline (CFG_PROMPT); flag = 0; /* assume no special flags for now */ if (len > 0) strcpy (lastcommand, console_buffer); else if (len == 0) flag |= CMD_FLAG_REPEAT; 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; } } }
相关文章推荐
- u-boot启动过程之STEP1
- u-boot启动过程
- U-BOOT启动过程分析 经典文章汇集
- u-boot 启动过程 —— 基于S3C2410 --转载自周明
- u-boot启动过程分析(源码)
- Linux 系统启动过程(initrd部分) --- Linux boot process (initrd part)
- Inside the Linux boot process(linux的启动过程)
- u-boot启动过程分析
- U-Boot启动的函数调用过程(以arm926ejs为例)
- AT91RM9200的U-BOOT启动烧写过程【转】
- 【原】用以太网Boot启动WinCE的过程浅析
- U-Boot的移植之(二)进阶篇:从源代码看系统启动过程
- AT91RM9200的U-BOOT启动烧写过程
- The Kernel Boot Process --linux2.6.25内核启动过程
- U-BOOT启动过程分析 经典文章汇集
- u-boot启动过程分析——基于lpc2210的移植代码
- u-boot启动过程分析——基于lpc2210的移植代码[转]
- u-boot启动过程分析——基于lpc2210的移植代码
- u-boot启动过程 u-boot (3)
- s3c2440开发日记,u-boot启动过程,Nand Flash启动分析irq_handler, 中断响应过程,