uboot 2013.01 代码简析(3)第二阶段初始化
u-boot第二阶段初始化内容的入口函数是_main,_main位于arch/arm/lib/crt0.S文件中:
_main函数中先为调用board_init_f准备初始化环境(设置栈指针sp和并给gd_t结构分配空间):
- .global _main
- _main:
- /*
- * Set up initial C runtime environment and call board_init_f().
- */
- #if defined(CONFIG_NAND_SPL)
- /* deprecated, use instead CONFIG_SPL_BUILD */
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
- #elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
- ldr sp, =(CONFIG_SPL_STACK)
- #else
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
- #endif
- bic sp, sp, # /* -byte alignment for ABI compliance */
- sub sp, #GD_SIZE /* allocate one GD above SP */
- bic sp, sp, # /* -byte alignment for ABI compliance */
- mov r8, sp /* GD is above SP */
然后调用board_init_f(0),这是因为r0可以作为输入参数:
- mov r0, #
- bl board_init_f
board_init_f(0)代码如下:
- init_fnc_t *init_sequence[] = {
arch_cpu_init, /* basic arch cpu dependent setup */
mark_bootstage,
#ifdef CONFIG_OF_CONTROL
fdtdec_check_fdt,
#endif
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
timer_init, /* initialize timer */
#ifdef CONFIG_BOARD_POSTCLK_INIT
board_postclk_init,
#endif
#ifdef CONFIG_FSL_ESDHC
get_clocks,
#endif
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init, /* configure available RAM banks */
NULL,
};
- void board_init_f(ulong bootflag)
- {
- bd_t *bd;
- init_fnc_t **init_fnc_ptr;
- gd_t *id;
- ulong addr, addr_sp;
- #ifdef CONFIG_PRAM
- ulong reg;
- #endif
- void *new_fdt = NULL;
- size_t fdt_size = ;
- memset((void *)gd, , sizeof(gd_t));
- gd->mon_len = _bss_end_ofs;
- #ifdef CONFIG_OF_EMBED
- /* Get a pointer to the FDT */
- gd->fdt_blob = _binary_dt_dtb_start;
- #elif defined CONFIG_OF_SEPARATE
- /* FDT is at end of image */
- gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
- #endif
- /* Allow the early environment to override the fdt address */
- gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", ,
- (uintptr_t)gd->fdt_blob);
- for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
- if ((*init_fnc_ptr)() != ) {
- hang ();
- }
- }
- #ifdef CONFIG_OF_CONTROL
- /* For now, put this check after the console is ready */
- if (fdtdec_prepare_fdt()) {
- panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
- "doc/README.fdt-control");
- }
- #endif
- debug("monitor len: %08lX\n", gd->mon_len);
- /*
- * Ram is setup, size stored in gd !!
- */
- debug("ramsize: %08lX\n", gd->ram_size);
- #if defined(CONFIG_SYS_MEM_TOP_HIDE)
- /*
- * Subtract specified amount of memory to hide so that it won't
- * get "touched" at all by U-Boot. By fixing up gd->ram_size
- * the Linux kernel should now get passed the now "corrected"
- * memory size and won't touch it either. This should work
- * for arch/ppc and arch/powerpc. Only Linux board ports in
- * arch/powerpc with bootwrapper support, that recalculate the
- * memory size from the SDRAM controller setup will have to
- * get fixed.
- */
- gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
- #endif
- addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
- #ifdef CONFIG_LOGBUFFER
- #ifndef CONFIG_ALT_LB_ADDR
- /* reserve kernel log buffer */
- addr -= (LOGBUFF_RESERVE);
- debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN,
- addr);
- #endif
- #endif
- #ifdef CONFIG_PRAM
- /*
- * reserve protected RAM
- */
- reg = getenv_ulong("pram", , CONFIG_PRAM);
- addr -= (reg << ); /* size is in kB */
- debug("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
- #endif /* CONFIG_PRAM */
- #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
- /* reserve TLB table */
- gd->tlb_size = * ;
- addr -= gd->tlb_size;
- /* round down to next 64 kB limit */
- addr &= ~(0x10000 - );
- gd->tlb_addr = addr;
- debug("TLB table from %08lx to %08lx\n", addr, addr + gd->tlb_size);
- #endif
- /* round down to next 4 kB limit */
- addr &= ~( - );
- debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
- #ifdef CONFIG_LCD
- #ifdef CONFIG_FB_ADDR
- gd->fb_base = CONFIG_FB_ADDR;
- #else
- /* reserve memory for LCD display (always full pages) */
- addr = lcd_setmem(addr);
- gd->fb_base = addr;
- #endif /* CONFIG_FB_ADDR */
- #endif /* CONFIG_LCD */
- /*
- * reserve memory for U-Boot code, data & bss
- * round down to next 4 kB limit
- */
- addr -= gd->mon_len;
- addr &= ~( - );
- debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> , addr);
- #ifndef CONFIG_SPL_BUILD
- /*
- * reserve memory for malloc() arena
- */
- addr_sp = addr - TOTAL_MALLOC_LEN;
- debug("Reserving %dk for malloc() at: %08lx\n",
- TOTAL_MALLOC_LEN >> , addr_sp);
- /*
- * (permanently) allocate a Board Info struct
- * and a permanent copy of the "global" data
- */
- addr_sp -= sizeof (bd_t);
- bd = (bd_t *) addr_sp;
- gd->bd = bd;
- debug("Reserving %zu Bytes for Board Info at: %08lx\n",
- sizeof (bd_t), addr_sp);
- #ifdef CONFIG_MACH_TYPE
- gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
- #endif
- addr_sp -= sizeof (gd_t);
- id = (gd_t *) addr_sp;
- debug("Reserving %zu Bytes for Global Data at: %08lx\n",
- sizeof (gd_t), addr_sp);
- #if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL)
- /*
- * If the device tree is sitting immediate above our image then we
- * must relocate it. If it is embedded in the data section, then it
- * will be relocated with other data.
- */
- if (gd->fdt_blob) {
- fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, );
- addr_sp -= fdt_size;
- new_fdt = (void *)addr_sp;
- debug("Reserving %zu Bytes for FDT at: %08lx\n",
- fdt_size, addr_sp);
- }
- #endif
- /* setup stackpointer for exeptions */
- gd->irq_sp = addr_sp;
- #ifdef CONFIG_USE_IRQ
- addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
- debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",
- CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);
- #endif
- /* leave 3 words for abort-stack */
- addr_sp -= ;
- /* 8-byte alignment for ABI compliance */
- addr_sp &= ~0x07;
- #else
- addr_sp += ; /* leave 32 words for abort-stack */
- gd->irq_sp = addr_sp;
- #endif
- debug("New Stack Pointer is: %08lx\n", addr_sp);
- #ifdef CONFIG_POST
- post_bootmode_init();
- post_run(NULL, POST_ROM | post_bootmode_get());
- #endif
- gd->bd->bi_baudrate = gd->baudrate;
- /* Ram ist board specific, so move it to board code ... */
- dram_init_banksize();
- display_dram_config(); /* and display it */
- gd->relocaddr = addr;
- gd->start_addr_sp = addr_sp;
- gd->reloc_off = addr - _TEXT_BASE;
- debug("relocation Offset is: %08lx\n", gd->reloc_off);
- if (new_fdt) {
- memcpy(new_fdt, gd->fdt_blob, fdt_size);
- gd->fdt_blob = new_fdt;
- }
- memcpy(id, (void *)gd, sizeof(gd_t));
- }
从代码中可以看出,board_init_f对gd内容进行初始化并将其拷贝到id变量中。
此外,代码中还对init_sequence中的所有函数按顺序依次执行,
从而完成了对MPLL、UPLL、GPIO、Timer、波特率、串口配置以及显示u-boot版本号、显示CPU型号、显示DRAM信息等功能
接着设置新sp和gd,然后跳转到relocate_code进行重定位,relocate_code的代码如下:
- .globl relocate_code
- relocate_code:
- mov r4, r0 /* save addr_sp */
- mov r5, r1 /* save addr of gd */
- mov r6, r2 /* save addr of destination */
- adr r0, _start
- cmp r0, r6
- moveq r9, # /* no relocation. relocation offset(r9) = */
- beq relocate_done /* skip relocation */
- mov r1, r6 /* r1 <- scratch for copy_loop */
- ldr r3, _bss_start_ofs
- add r2, r0, r3 /* r2 <- source end address */
- copy_loop:
- ldmia r0!, {r9-r10} /* copy from source address [r0] */
- stmia r1!, {r9-r10} /* copy to target address [r1] */
- cmp r0, r2 /* until source end address [r2] */
- blo copy_loop
- #ifndef CONFIG_SPL_BUILD
- /*
- * fix .rel.dyn relocations
- */
- ldr r0, _TEXT_BASE /* r0 <- Text base */
- sub r9, r6, r0 /* r9 <- relocation offset */
- ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
- add r10, r10, r0 /* r10 <- sym table in FLASH */
- ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
- add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
- ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
- add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
- fixloop:
- ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
- add r0, r0, r9 /* r0 <- location to fix up in RAM */
- ldr r1, [r2, #]
- and r7, r1, #0xff
- cmp r7, # /* relative fixup? */
- beq fixrel
- cmp r7, # /* absolute fixup? */
- beq fixabs
- /* ignore unknown type of fixup */
- b fixnext
- fixabs:
- /* absolute fix: set location to (offset) symbol value */
- mov r1, r1, LSR # /* r1 <- symbol index in .dynsym */
- add r1, r10, r1 /* r1 <- address of symbol in table */
- ldr r1, [r1, #] /* r1 <- symbol value */
- add r1, r1, r9 /* r1 <- relocated sym addr */
- b fixnext
- fixrel:
- /* relative fix: increase location by offset */
- ldr r1, [r0]
- add r1, r1, r9
- fixnext:
- str r1, [r0]
- add r2, r2, # /* each rel.dyn entry is bytes */
- cmp r2, r3
- blo fixloop
- #endif
- relocate_done:
- mov pc, lr
relocate_code刚开始执行前先将here的值保存到lr寄存器中,然后执行重定位,执行完毕后跳转到lr寄存器(即here)执行。
然后对BSS段进行初始化:
- here:
- /* Set up final (full) environment */
- bl c_runtime_cpu_setup /* we still call old routine here */
- ldr r0, =__bss_start /* this is auto-relocated! */
- ldr r1, =__bss_end__ /* this is auto-relocated! */
- mov r2, #0x00000000 /* prepare zero to clear BSS */
- clbss_l:cmp r0, r1 /* while not at end of BSS */
- strlo r2, [r0] /* clear -bit BSS word */
- addlo r0, r0, # /* move to next */
- blo clbss_l
接着调用board_init_r()函数:
- bl coloured_LED_init
- bl red_led_on
- #if defined(CONFIG_NAND_SPL)
- /* call _nand_boot() */
- ldr pc, =nand_boot
- #else
- /* call board_init_r(gd_t *id, ulong dest_addr) */
- mov r0, r8 /* gd_t */
- ldr r1, [r8, #GD_RELOCADDR] /* dest_addr */
- /* call board_init_r */
- ldr pc, =board_init_r /* this is auto-relocated! */
- #endif
board_init_r函数代码如下:
- void board_init_r(gd_t *id, ulong dest_addr)
- {
- ulong malloc_start;
- #if !defined(CONFIG_SYS_NO_FLASH)
- ulong flash_size;
- #endif
- gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
- bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
- monitor_flash_len = _end_ofs;
- /* Enable caches */
- enable_caches();
- debug("monitor flash len: %08lX\n", monitor_flash_len);
- board_init(); /* Setup chipselects */
- /*
- * TODO: printing of the clock inforamtion of the board is now
- * implemented as part of bdinfo command. Currently only support for
- * davinci SOC's is added. Remove this check once all the board
- * implement this.
- */
- #ifdef CONFIG_CLOCKS
- set_cpu_clk_info(); /* Setup clock information */
- #endif
- serial_initialize();
- debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
- #ifdef CONFIG_LOGBUFFER
- logbuff_init_ptrs();
- #endif
- #ifdef CONFIG_POST
- post_output_backlog();
- #endif
- /* The Malloc area is immediately below the monitor copy in DRAM */
- malloc_start = dest_addr - TOTAL_MALLOC_LEN;
- mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
- #ifdef CONFIG_ARCH_EARLY_INIT_R
- arch_early_init_r();
- #endif
- power_init_board();
- #if !defined(CONFIG_SYS_NO_FLASH)
- puts("Flash: ");
- flash_size = flash_init();
- if (flash_size > ) {
- # ifdef CONFIG_SYS_FLASH_CHECKSUM
- print_size(flash_size, "");
- /*
- * Compute and print flash CRC if flashchecksum is set to 'y'
- *
- * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
- */
- if (getenv_yesno("flashchecksum") == ) {
- printf(" CRC: %08X", crc32(,
- (const unsigned char *) CONFIG_SYS_FLASH_BASE,
- flash_size));
- }
- putc('\n');
- # else /* !CONFIG_SYS_FLASH_CHECKSUM */
- print_size(flash_size, "\n");
- # endif /* CONFIG_SYS_FLASH_CHECKSUM */
- } else {
- puts(failed);
- hang();
- }
- #endif
- #if defined(CONFIG_CMD_NAND)
- puts("NAND: ");
- nand_init(); /* go init the NAND */
- #endif
- #if defined(CONFIG_CMD_ONENAND)
- onenand_init();
- #endif
- #ifdef CONFIG_GENERIC_MMC
- puts("MMC: ");
- mmc_initialize(gd->bd);
- #endif
- #ifdef CONFIG_HAS_DATAFLASH
- AT91F_DataflashInit();
- dataflash_print_info();
- #endif
- /* initialize environment */
- if (should_load_env())
- env_relocate();
- else
- set_default_env(NULL);
- #if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)
- arm_pci_init();
- #endif
- stdio_init(); /* get the devices list going. */
- jumptable_init();
- #if defined(CONFIG_API)
- /* Initialize API */
- api_init();
- #endif
- console_init_r(); /* fully init console as a device */
- #ifdef CONFIG_DISPLAY_BOARDINFO_LATE
- # ifdef CONFIG_OF_CONTROL
- /* Put this here so it appears on the LCD, now it is ready */
- display_fdt_model(gd->fdt_blob);
- # else
- checkboard();
- # endif
- #endif
- #if defined(CONFIG_ARCH_MISC_INIT)
- /* miscellaneous arch dependent initialisations */
- arch_misc_init();
- #endif
- #if defined(CONFIG_MISC_INIT_R)
- /* miscellaneous platform dependent initialisations */
- misc_init_r();
- #endif
- /* set up exceptions */
- interrupt_init();
- /* enable exceptions */
- enable_interrupts();
- /* Initialize from environment */
- load_addr = getenv_ulong("loadaddr", , load_addr);
- #ifdef CONFIG_BOARD_LATE_INIT
- board_late_init();
- #endif
- #ifdef CONFIG_BITBANGMII
- bb_miiphy_init();
- #endif
- #if defined(CONFIG_CMD_NET)
- puts("Net: ");
- eth_initialize(gd->bd);
- #if defined(CONFIG_RESET_PHY_R)
- debug("Reset Ethernet PHY\n");
- reset_phy();
- #endif
- #endif
- #ifdef CONFIG_POST
- post_run(NULL, POST_RAM | post_bootmode_get());
- #endif
- #if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
- /*
- * Export available size of memory for Linux,
- * taking into account the protected RAM at top of memory
- */
- {
- ulong pram = ;
- uchar memsz[];
- #ifdef CONFIG_PRAM
- pram = getenv_ulong("pram", , CONFIG_PRAM);
- #endif
- #ifdef CONFIG_LOGBUFFER
- #ifndef CONFIG_ALT_LB_ADDR
- /* Also take the logbuffer into account (pram is in kB) */
- pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / ;
- #endif
- #endif
- sprintf((char *)memsz, "%ldk", (gd->ram_size / ) - pram);
- setenv("mem", (char *)memsz);
- }
- #endif
- /* main_loop() can return to retry autoboot, if so just run it again. */
- for (;;) {
- main_loop();
- }
- /* NOTREACHED - no way out of command loop except booting */
- }
在board_init_r函数中依次执行使能数据Cache和指令Cache,三个串口初始化,内存分配初始化,flash初始化,nand初始化,mmc设备初始化,stdio初始化,stdout和stderr初始化,开中断,网卡初始化等操作,
然后反复执行main_loop函数。
u-boot第二个阶段的执行内容如下:
(1)为board_init_f准备sp和gd
(2)执行board_init_f,对MPLL、UPLL、GPIO、Timer、波特率、串口配置,显示u-boot版本号、CPU型号和DRAM信息,并初始化gd内容。
(3)调用relocate_code进行代码重定位
(4)初始化BSS
(5)调用board_init_r,使能数据Cache和指令Cache,三个串口初始化,内存分配初始化,flash初始化,nand初始化,
mmc设备初始化,stdio初始化,stdout和stderr初始化,开中断,网卡初始化,然后执行main_loop等待用户输入命令或者超时后进入linux内核。
uboot 2013.01 代码简析(3)第二阶段初始化的更多相关文章
- uboot 2013.01 代码简析(2)第一阶段初始化
uboot执行"make smdk2410_config"之后就可以进行编译了,可以执行make命令进行编译, 因为整个输出太长,我仅仅列出部分最关键的输出(部分我不关心的内容直接 ...
- uboot 2013.01 代码简析(1)开发板配置
u-boot下载地址:ftp://ftp.denx.de/pub/u-boot/u-boot-2013.01.01.tar.bz2 下载之后对该文件进行解压. 我试着分析smdk2410_config ...
- uboot 2013.01 s3c6400编译失败
通常我们对s3c6410平台开发u-boot是在s3c6400的基础上修改而成的,但是从uboot 2013.01这个版本之后的版本都把smdk6400对应的配置给删除了. 这是因为该版本smdk64 ...
- OpenStack之虚机冷迁移代码简析
OpenStack之虚机冷迁移代码简析 前不久我们看了openstack的热迁移代码,并进行了简单的分析.真的,很简单的分析.现在天气凉了,为了应时令,再简析下虚机冷迁移的代码. 还是老样子,前端的H ...
- WinForm 自动完成控件实例代码简析
在Web的应用方面有js的插件实现自动完成(或叫智能提示)功能,但在WinForm窗体应用方面就没那么好了. TextBox控件本身是提供了一个自动提示功能,只要用上这三个属性: AutoComple ...
- Log4js 工作原理及代码简析
本文地址 http://www.cnblogs.com/jasonxuli/p/6518650.html log4js 版本 0.6.16, 最新版1.1.1 大体类似. 使用 log4j ...
- Hive Metastore 代码简析
1. hive metastore 内部结构 1.1 包结构 从package结构来看,主要的5个package,让我们来看看这几个package的内容 (1) metastorepackage是m ...
- GPXReader工具代码简析
完整的文件在TerraExplorer Pro的默认安装目录下C:\Program Files (x86)\Skyline\TerraExplorer Pro\Tools\GPXReader: 如果你 ...
- ortp代码简析
ortp初始化 /** * Initialize the oRTP library. You should call this function first before using * ...
随机推荐
- Android文章收藏
Android集 1.Himi李华明的<Android游戏开发专栏>http://blog.csdn.net/column/details/androidgame.html2.老罗的&l ...
- 约瑟夫环用php实现
百度百科的解释:约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数 ...
- devpress grid表格自适应列宽的问题
/// <summary> /// 自适应列宽,显示横向滚轴,只有当所有列都已经在界面上加载完成之后才能生效 /// </summary> public void setAut ...
- zabbix自动发现监控远程端口
zabbix监控远程服务器端口,simple checks是zabbix用来监控无agent的主机 脚本和模板地址: https://github.com/mikeluwen/tcpmonitor
- js 正则表达式 取反
http://www.w3school.com.cn/jsref/jsref_obj_regexp.asp 以匹配中文为例 const test_value = '李钊鸿' if (/[^\u4e00 ...
- PHPthinking为全部PHP爱好者指路
1.新手学习路线:个人觉得.自己手上应该有本參考书.像细说PHP,然后看书学习,穿插网上的一些免费视频教程(随便百度一下即可,之后我尽量整理一些给大家).当然假设自控能力差的同学.也能够參加一些培训机 ...
- webpack 功能大全 【环境配置】
1. webpack简介 webpack 是一个模块打包工具.它使得模块相互依赖并且可构建等价于这些模块的静态资源.相比于已经存在的模块打包器(module bundler),webpack的开发动机 ...
- Android环境变量的设置(详细图解版)
分类: Android初学学习笔记2011-07-10 09:47 99479人阅读 评论(0) 收藏 举报 androidtoolspathcmd 查阅了网上很多的资料但是对于环境变量设置介绍的不够 ...
- 一个方便的图片载入框架——ImageViewEx
我的博客:http://mrfufufu.github.io/ 一.前言 近期在整理项目中的一些代码,以备即将开展的新项目中使用,刚刚整理到一个图片载入的 lib.用起来很的简单,和 picasso ...
- FP Tree算法原理总结(转载)
FP Tree算法原理总结 在Apriori算法原理总结中,我们对Apriori算法的原理做了总结.作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈.为了解决这个问题 ...