上一部分讲到 uboot 跳转到 start_armboot 处执行(中间插了一篇 异常中断处理)。
这次主要是记录 start_armboot 的实现。
文件为 /lib_arm/board.c
1、参数声明
1 void start_armboot (void) 2 { 3 init_fnc_t **init_fnc_ptr; //这里实际上是创建数组指针 //指向的数组为 start_armboot 之前的 init_sequence 数组 4 char *s; 5 #if defined(CONFIG_VFD) || defined(CONFIG_LCD) 6 unsigned long addr; 7 #endif
2、两个结构体与内存屏障
8 9 /* Pointer is writable since we allocated a register for it */ 10 gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); 11 /* compiler optimization barrier needed for GCC >= 3.4 */ 12 __asm__ __volatile__("": : :"memory");
这里有两个结构体要展开
1)uboot所调用的配置信息,文件为/include/asm-arm/Global_data.h
typedef struct global_data { bd_t *bd; unsigned long flags; unsigned long baudrate; unsigned long have_console; /* serial_init() was called */ unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long fb_base; /* base address of frame buffer */ #ifdef CONFIG_VFD unsigned char vfd_type; /* display type */ #endif #ifdef CONFIG_FSL_ESDHC unsigned long sdhc_clk; #endif #if 0 unsigned long cpu_clk; /* CPU clock in Hz! */ unsigned long bus_clk; phys_size_t ram_size; /* RAM size */ unsigned long reset_status; /* reset status register at boot */ #endif void **jt; /* jump table */ } gd_t;
2)板子所调用的板级配置信息,文件为/include/asm-arm/U-boot.h
typedef struct bd_info { int bi_baudrate; /* serial console baudrate */ unsigned long bi_ip_addr; /* IP Address */ struct environment_s *bi_env; ulong bi_arch_number; /* unique id for this board */ ulong bi_boot_params; /* where this board expects params */ struct /* RAM configuration */ { ulong start; ulong size; } bi_dram[CONFIG_NR_DRAM_BANKS]; } bd_t;
这里的 gd 实际指向了一个地址,地址位置可以看下图
注意,这里为小端模式
_bss_start | TEXT/DATA | // = 0x100000 + 0x4000 CONFIG_SYS_MALLOC_LEN | // = sizeof(gd_t) gd_t // gd 实际指向的地址 | // = sizeof(bd_t) bd_t // gd_t 的第一部分就是 bd_t | _armboot_start // 定义在 start.S 中 | STACK // IRQ_STACK_START FIQ_STACK_START
然后是内存屏障
12 __asm__ __volatile__("": : :"memory");
简单理解起来就是:禁止编译器优化此处的汇编代码。
这样做,可以有效防止 编译器将当前的寄存器的值 直接替换在代码中。
这行代码大量地使用在内存屏障函数中,例如 mb()函数组。
更详细的介绍可以参详
http://blog.sina.com.cn/s/blog_7e741b830100wz1f.html
3、分配空间
13 14 memset ((void*)gd, 0, sizeof (gd_t)); //清空 gd 的对应空间 15 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); //设置 bd 指向地址 16 memset (gd->bd, 0, sizeof (bd_t)); //清空 bd 的对应空间 17 18 gd->flags |= GD_FLG_RELOC; // #define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM*/ 19 20 monitor_flash_len = _bss_start - _armboot_start;
4、初始化
21 22 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { 23 if ((*init_fnc_ptr)() != 0) { 24 hang (); 25 } 26 }
这里的 hang 其实是死循环,函数如下
void hang (void) { puts ("### ERROR ### Please RESET the board ###\n"); for (;;); }
意味着如果有初始化函数不存在,或者初始化失败(返回不为0),则出错。
5、清空 code 区
27 28 /* armboot_start is defined in the board-specific linker script */ 29 mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN, 30 CONFIG_SYS_MALLOC_LEN);
此处有
void mem_malloc_init(ulong start, ulong size) { mem_malloc_start = start; mem_malloc_end = start + size; mem_malloc_brk = start; memset((void *)mem_malloc_start, 0, size); }
6、之后有大量的可配置项,这些可配置项的内部实现都很简单清晰,所以仅列出标题了
32 #ifndef CONFIG_SYS_NO_FLASH 37 #ifdef CONFIG_VFD 50 #ifdef CONFIG_LCD 75 #ifdef CONFIG_HAS_DATAFLASH
7、变量搬移
79 80 /* initialize environment */ 81 env_relocate ();
具体实现在 /common/Env_common.c 中
8、可配置项
83 #ifdef CONFIG_VFD 88 #ifdef CONFIG_SERIAL_MULTI
9、这一段代码量较长、不继续深入
主要功能看代码自注
91 92 /* IP Address */ 93 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); 94 95 stdio_init (); /* get the devices list going. */ 96 97 jumptable_init ();
10、可配置项
99 #if defined(CONFIG_API)
11、控制台初始化
104 console_init_r (); /* fully init console as a device */
12、可配置项
106 #if defined(CONFIG_ARCH_MISC_INIT) 110 #if defined(CONFIG_MISC_INIT_R)
13、使能中断
114 115 /* enable exceptions */ 116 enable_interrupts ();
14、可配置项
119 #ifdef CONFIG_DRIVER_TI_EMAC 129 #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
16、
137 138 /* Initialize from environment */ 139 if ((s = getenv ("loadaddr")) != NULL) { 140 load_addr = simple_strtoul (s, NULL, 16); 141 }
17、可配置项
142 #if defined(CONFIG_CMD_NET) 148 #ifdef BOARD_LATE_INIT 152 #ifdef CONFIG_GENERIC_MMC 157 #ifdef CONFIG_BITBANGMII 160 #if defined(CONFIG_CMD_NET) 161 #if defined(CONFIG_NET_MULTI)
18、网卡设置
164 eth_initialize(gd->bd);
19、可配置项
165 #if defined(CONFIG_RESET_PHY_R)
20、进入主循环
170 /* main_loop() can return to retry autoboot, if so just run it again. */ 171 for (;;) { 172 main_loop (); 173 } 174 175 /* NOTREACHED - no way out of command loop except booting */
文件路径为 /common/Main.c